class Zashoku::Util::Readline

Constants

COLOR

Attributes

ac_index[RW]
ac_sorted[RW]
history[RW]
hy_index[RW]
prompt[RW]
x[RW]
y[RW]

Public Class Methods

new(prompt = '', ac_tree: {}, history: []) click to toggle source
# File lib/core/util/readline.rb, line 10
def initialize(prompt = '', ac_tree: {}, history: [])
  @prompt    = prompt
  @ac_index  = 0
  @history   = history
  @hy_index  = 0
  @ac_sorted = []
  @tree = ac_tree
  #@y = Term.rows
end

Public Instance Methods

ac_list(string) click to toggle source
# File lib/core/util/readline.rb, line 111
def ac_list(string)
  path = string.split
  path << '' if string[-1] == ' '
  if path.length > 1
    ac = safe_dig(@tree, path[0...-1])
    return [string] unless ac
    ac.map { |n| (path[0...-1] + [n]).join(' ') }
  else
    @tree.keys
  end
end
draw(string) click to toggle source
# File lib/core/util/readline.rb, line 24
def draw(string)
  print "#{COLOR}\e[#{y};0H#{prompt}#{string}\e[K\e[#{y};#{@x + 1}H"
end
read(string = '') click to toggle source
# File lib/core/util/readline.rb, line 28
def read(string = '')
  @x = prompt.length
  Curses.curs_set(1)
  max = Term.cols

  loop do
    draw(string)
    c = Curses.getch
    @ac_index = 0 unless c == 9
    case c
    when Curses::KEY_LEFT
      @x = [prompt.length, x-1].max
    when Curses::KEY_RIGHT
      @x = [prompt.length + string.length, x+1].min
    when Curses::KEY_UP
      @history.unshift(string) if hy_index == 0
      @hy_index += 1
      if hy_index >= history.length
        @hy_index = history.length - 1
        Curses.beep
      end
      string = history[hy_index]
      @x = string.length + prompt.length
    when Curses::KEY_DOWN
      if hy_index == 1
        @hy_index = 0
        string = @history.shift
      elsif hy_index > 1
        string = history[@hy_index -= 1] || ''
      else
        @hy_index = 0
        Curses.beep
      end
      @x = string.length + prompt.length
    when 10, ?\n, ?\r
      break
    when 127, 8, ?\b #backspace
      print "\e[#{y};#{x}H "
      @x -= 1
      break if @x < prompt.length
      rx = @x - prompt.length
      string = string[0...rx] + string[rx..-1]
      string[x - prompt.length] = ''
    when 9 #tab
      next if @tree.empty?
      if @ac_index == 0
        acl = ac_list(string)
        @ac_sorted = sort_ac_list(acl, string)
      end
      string = @ac_sorted[@ac_index] || ''
      @x = @prompt.length + string.length
      @ac_index += 1
      @ac_index = 0 if @ac_index >= ac_sorted.length
    when /[[:print:]]/
      if (@x < max)
        rx = @x - prompt.length
        string = string[0...rx] + c.chr + string[rx..-1]
        @x += 1
      else
        Curses.beep
      end
    else
      Zashoku.logger.warn("unbound key pressed: #{c}")
      Curses.beep
    end
    @history[@hy_index] = string
  end

  Curses.curs_set(0)
  print "\e[#{y};0H\e[2K"

  @hy_index = 0
  @history.unshift(string)
  @history.reject! { |e| e.empty? }
  string
end
safe_dig(tree, path) click to toggle source
# File lib/core/util/readline.rb, line 105
def safe_dig(tree, path)
  l = @tree.dig(path.shift)
  return l if l.class != Hash || path.empty?
  safe_dig(tree, path)
end
sort_ac_list(list, string) click to toggle source
# File lib/core/util/readline.rb, line 123
def sort_ac_list(list, string)
  list.select { |e| /^#{string}.*/i.match?(e.to_s) }
end