Skip to content
This repository
tree: 4a6dbd19d9
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 219 lines (187 sloc) 4.283 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
class Terminal

  attr_reader :client

  def initialize given_uri, id_amount = nil
    check_highline_gem
    check_picky_client_gem

    require 'uri'
    uri = URI.parse given_uri

    # If the user gave a whole url without http, add that and reparse.
    #
    unless uri.path
      uri = URI.parse "http://#{given_uri}"
    end

    # If the user gave a path without / in front, add one.
    #
    unless uri.path =~ /^\//
      uri.path = "/#{uri.path}"
    end

    @searches = 0
    @durations = 0
    @current_text = ''
    @cursor_offset = 0
    @last_ids = ''
    @id_amount = id_amount && Integer(id_amount) || 20
    @client = Picky::Client.new :host => (uri.host || 'localhost'), :port => (uri.port || 8080), :path => uri.path

    install_trap
  end
  def check_highline_gem # :nodoc:
    require "highline/system_extensions"
    extend HighLine::SystemExtensions
  rescue LoadError
    warn_gem_missing 'highline', 'the terminal interface'
    exit 1
  end
  def check_picky_client_gem # :nodoc:
    require 'picky-client'
  rescue LoadError
    warn_gem_missing 'picky-client', 'the terminal interface'
    exit 1
  end

  # Install the Ctrl-C handler.
  #
  def install_trap
    Signal.trap('INT') do
      print "\e[100D"
      flush
      puts "\n"
      puts "You performed #{@searches} searches, totalling #{"%.3f" % @durations} seconds."
      print "\e[100D"
      flush
      exit
    end
  end

  # Flush to STDOUT.
  #
  def flush
    STDOUT.flush
  end

  # Position cursor amount to the left.
  #
  def left amount = 1
    print "\e[#{amount}D"
    flush
  end

  # Position cursor amount to the right.
  #
  def right amount = 1
    print "\e[#{amount}C"
    flush
  end

  # Move cursor to position.
  #
  def move_to position
    relative = position - @cursor_offset
    if relative > 0
      right relative
    else
      left relative
    end
    @cursor_offset = position
    flush
  end

  # Delete one character.
  #
  def backspace
    chop_text
    print "\e[1D \e[1D"
    flush
  end

  # Write the text to the input area.
  #
  def write text
    @cursor_offset += text.size
    print text
    flush
  end

  # Chop off one character.
  #
  def chop_text
    @current_text.chop!
  end

  # Add the given text to the current text.
  #
  def add_text text
    @current_text << text
  end

  # Type the given text into the input area.
  #
  def type_search character
    add_text character
    write character
  end

  # Write the amount of result ids.
  #
  def write_results results
    move_to 0
    write "%9d" % (results && results.total || 0)
    move_to 10 + @current_text.size
  end

  # Move to the id area.
  #
  def move_to_ids
    move_to 12 + @current_text.size
  end

  # Write the result ids.
  #
  def write_ids results
    move_to_ids
    write "=> #{results.total ? results.ids(@id_amount) : []}"
  rescue StandardError => e
    p e.message
    p e.backtrace
  end

  # Clear the result ids.
  #
  def clear_ids
    move_to_ids
    write @ids_clearing_string ||= " "*200
  end

  # Log a search.
  #
  def log results
    @searches += 1
    @durations += (results[:duration] || 0)
  end

  # Perform a search.
  #
  def search full = false
    client.search @current_text, :ids => (full ? @id_amount : 0)
  end

  # Perform a search and write the results.
  #
  # Handles 404s and connection problems.
  #
  def search_and_write full = false
    results = search full
    results.extend Picky::Convenience

    log results

    full ? write_ids(results) : clear_ids

    write_results results
  rescue Errno::ECONNREFUSED => e
    write "Please start a Picky server listening to #{@client.path}."
  rescue Yajl::ParseError => e
    write "Got a 404. Maybe the path #{@client.path} isn't a correct one?"
  end

  # Run the terminal.
  #
  # Note: Uses a simple loop to handle input.
  #
  def run
    puts "Type and see the result count update. Press enter for the first #{@id_amount} result ids."
    puts "Break with Ctrl-C."

    search_and_write

    loop do
      input = get_character

      case input
      when 127
        backspace
        search_and_write
      when 13
        search_and_write true
      else # All other.
        type_search input.chr
        search_and_write
      end
    end
  end

end
Something went wrong with that request. Please try again.