Class: Zashoku::Util::Readline

Inherits:
Object
  • Object
show all
Defined in:
lib/core/util/readline.rb

Constant Summary collapse

COLOR =
"\e[0m"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(prompt = '', ac_tree: {}, history: []) ⇒ Readline

Returns a new instance of Readline.



10
11
12
13
14
15
16
17
18
# 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

Instance Attribute Details

#ac_indexObject

Returns the value of attribute ac_index.



8
9
10
# File 'lib/core/util/readline.rb', line 8

def ac_index
  @ac_index
end

#ac_sortedObject

Returns the value of attribute ac_sorted.



8
9
10
# File 'lib/core/util/readline.rb', line 8

def ac_sorted
  @ac_sorted
end

#historyObject

Returns the value of attribute history.



8
9
10
# File 'lib/core/util/readline.rb', line 8

def history
  @history
end

#hy_indexObject

Returns the value of attribute hy_index.



8
9
10
# File 'lib/core/util/readline.rb', line 8

def hy_index
  @hy_index
end

#promptObject

Returns the value of attribute prompt.



8
9
10
# File 'lib/core/util/readline.rb', line 8

def prompt
  @prompt
end

#xObject

Returns the value of attribute x.



8
9
10
# File 'lib/core/util/readline.rb', line 8

def x
  @x
end

#yObject

Returns the value of attribute y.



8
9
10
# File 'lib/core/util/readline.rb', line 8

def y
  @y
end

Instance Method Details

#ac_list(string) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
# 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) ⇒ Object



24
25
26
# 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 = '') ⇒ Object



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
# 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) ⇒ Object



105
106
107
108
109
# 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) ⇒ Object



123
124
125
# File 'lib/core/util/readline.rb', line 123

def sort_ac_list(list, string)
  list.select { |e| /^#{string}.*/i.match?(e.to_s) }
end