Class: Reline::ANSI

Inherits:
Object
  • Object
show all
Defined in:
lib/reline/ansi.rb

Constant Summary collapse

RAW_KEYSTROKE_CONFIG =
{
  # Console (80x25)
  [27, 91, 49, 126] => :ed_move_to_beg, # Home
  [27, 91, 52, 126] => :ed_move_to_end, # End
  [27, 91, 51, 126] => :key_delete,     # Del
  [27, 91, 65] => :ed_prev_history,     # ↑
  [27, 91, 66] => :ed_next_history,     # ↓
  [27, 91, 67] => :ed_next_char,        # →
  [27, 91, 68] => :ed_prev_char,        # ←

  # KDE
  [27, 91, 72] => :ed_move_to_beg,      # Home
  [27, 91, 70] => :ed_move_to_end,      # End
  # Del is 0x08
  [27, 71, 65] => :ed_prev_history,     # ↑
  [27, 71, 66] => :ed_next_history,     # ↓
  [27, 71, 67] => :ed_next_char,        # →
  [27, 71, 68] => :ed_prev_char,        # ←

  # urxvt / exoterm
  [27, 91, 55, 126] => :ed_move_to_beg, # Home
  [27, 91, 56, 126] => :ed_move_to_end, # End

  # GNOME
  [27, 79, 72] => :ed_move_to_beg,      # Home
  [27, 79, 70] => :ed_move_to_end,      # End
  # Del is 0x08
  # Arrow keys are the same of KDE

  # iTerm2
  [27, 27, 91, 67] => :em_next_word,    # Option+→
  [27, 27, 91, 68] => :ed_prev_word,    # Option+←
  [195, 166] => :em_next_word,          # Option+f
  [195, 162] => :ed_prev_word,          # Option+b

  # others
  [27, 32] => :em_set_mark,             # M-<space>
  [24, 24] => :em_exchange_mark,        # C-x C-x TODO also add Windows
  [27, 91, 49, 59, 53, 67] => :em_next_word, # Ctrl+→
  [27, 91, 49, 59, 53, 68] => :ed_prev_word, # Ctrl+←

  [27, 79, 65] => :ed_prev_history,     # ↑
  [27, 79, 66] => :ed_next_history,     # ↓
  [27, 79, 67] => :ed_next_char,        # →
  [27, 79, 68] => :ed_prev_char,        # ←
}
@@input =
STDIN
@@output =
STDOUT
@@buf =
[]
@@old_winch_handler =
nil

Class Method Summary collapse

Class Method Details

.clear_screenObject



196
197
198
199
# File 'lib/reline/ansi.rb', line 196

def self.clear_screen
  @@output.write "\e[2J"
  @@output.write "\e[1;1H"
end

.cursor_posObject



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
# File 'lib/reline/ansi.rb', line 132

def self.cursor_pos
  begin
    res = ''
    m = nil
    @@input.raw do |stdin|
      @@output << "\e[6n"
      @@output.flush
      loop do
        c = stdin.getc
        next if c.nil?
        res << c
        m = res.match(/\e\[(?<row>\d+);(?<column>\d+)R/)
        break if m
      end
      (m.pre_match + m.post_match).chars.reverse_each do |ch|
        stdin.ungetc ch
      end
    end
    column = m[:column].to_i - 1
    row = m[:row].to_i - 1
  rescue Errno::ENOTTY
    begin
      buf = @@output.pread(@@output.pos, 0)
      row = buf.count("\n")
      column = buf.rindex("\n") ? (buf.size - buf.rindex("\n")) - 1 : 0
    rescue Errno::ESPIPE
      # Just returns column 1 for ambiguous width because this I/O is not
      # tty and can't seek.
      row = 0
      column = 1
    end
  end
  Reline::CursorPos.new(column, row)
end

.deprep(otio) ⇒ Object



213
214
215
216
217
# File 'lib/reline/ansi.rb', line 213

def self.deprep(otio)
  int_handle = Signal.trap('INT', 'IGNORE')
  Signal.trap('INT', int_handle)
  Signal.trap('WINCH', @@old_winch_handler) if @@old_winch_handler
end

.empty_buffer?Boolean

Returns:

  • (Boolean)


87
88
89
90
91
92
93
94
95
96
97
# File 'lib/reline/ansi.rb', line 87

def self.empty_buffer?
  unless @@buf.empty?
    return false
  end
  rs, = IO.select([@@input], [], [], 0.00001)
  if rs and rs[0]
    false
  else
    true
  end
end

.encodingObject



4
5
6
# File 'lib/reline/ansi.rb', line 4

def self.encoding
  Encoding.default_external
end

.erase_after_cursorObject



187
188
189
# File 'lib/reline/ansi.rb', line 187

def self.erase_after_cursor
  @@output.write "\e[K"
end

.get_screen_sizeObject



115
116
117
118
119
120
121
122
123
# File 'lib/reline/ansi.rb', line 115

def self.get_screen_size
  s = @@input.winsize
  return s if s[0] > 0 && s[1] > 0
  s = [ENV["LINES"].to_i, ENV["COLUMNS"].to_i]
  return s if s[0] > 0 && s[1] > 0
  [24, 80]
rescue Errno::ENOTTY
  [24, 80]
end

.getcObject



70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/reline/ansi.rb', line 70

def self.getc
  unless @@buf.empty?
    return @@buf.shift
  end
  until c = @@input.raw(intr: true, &:getbyte)
    sleep 0.1
  end
  (c == 0x16 && @@input.raw(min: 0, tim: 0, &:getbyte)) || c
rescue Errno::EIO
  # Maybe the I/O has been closed.
  nil
end

.in_pasting?Boolean

Returns:

  • (Boolean)


83
84
85
# File 'lib/reline/ansi.rb', line 83

def self.in_pasting?
  not Reline::IOGate.empty_buffer?
end

.input=(val) ⇒ Object



60
61
62
# File 'lib/reline/ansi.rb', line 60

def self.input=(val)
  @@input = val
end

.move_cursor_column(x) ⇒ Object



167
168
169
# File 'lib/reline/ansi.rb', line 167

def self.move_cursor_column(x)
  @@output.write "\e[#{x + 1}G"
end

.move_cursor_down(x) ⇒ Object



179
180
181
182
183
184
185
# File 'lib/reline/ansi.rb', line 179

def self.move_cursor_down(x)
  if x > 0
    @@output.write "\e[#{x}B" if x > 0
  elsif x < 0
    move_cursor_up(-x)
  end
end

.move_cursor_up(x) ⇒ Object



171
172
173
174
175
176
177
# File 'lib/reline/ansi.rb', line 171

def self.move_cursor_up(x)
  if x > 0
    @@output.write "\e[#{x}A" if x > 0
  elsif x < 0
    move_cursor_down(-x)
  end
end

.output=(val) ⇒ Object



65
66
67
# File 'lib/reline/ansi.rb', line 65

def self.output=(val)
  @@output = val
end

.prepObject



206
207
208
209
210
211
# File 'lib/reline/ansi.rb', line 206

def self.prep
  retrieve_keybuffer
  int_handle = Signal.trap('INT', 'IGNORE')
  Signal.trap('INT', int_handle)
  nil
end

.retrieve_keybufferObject



103
104
105
106
107
108
109
110
111
112
113
# File 'lib/reline/ansi.rb', line 103

def self.retrieve_keybuffer
  begin
    result = select([@@input], [], [], 0.001)
    return if result.nil?
    str = @@input.read_nonblock(1024)
    str.bytes.each do |c|
      @@buf.push(c)
    end
  rescue EOFError
  end
end

.scroll_down(x) ⇒ Object



191
192
193
194
# File 'lib/reline/ansi.rb', line 191

def self.scroll_down(x)
  return if x.zero?
  @@output.write "\e[#{x}S"
end

.set_screen_size(rows, columns) ⇒ Object



125
126
127
128
129
130
# File 'lib/reline/ansi.rb', line 125

def self.set_screen_size(rows, columns)
  @@input.winsize = [rows, columns]
  self
rescue Errno::ENOTTY
  self
end

.set_winch_handler(&handler) ⇒ Object



202
203
204
# File 'lib/reline/ansi.rb', line 202

def self.set_winch_handler(&handler)
  @@old_winch_handler = Signal.trap('WINCH', &handler)
end

.ungetc(c) ⇒ Object



99
100
101
# File 'lib/reline/ansi.rb', line 99

def self.ungetc(c)
  @@buf.unshift(c)
end

.win?Boolean

Returns:

  • (Boolean)


8
9
10
# File 'lib/reline/ansi.rb', line 8

def self.win?
  false
end