Class: TTY::Prompt::Reader Private
- Inherits:
-
Object
- Object
- TTY::Prompt::Reader
- Includes:
- Wisper::Publisher
- Defined in:
- lib/tty/prompt/reader.rb,
lib/tty/prompt/reader/line.rb,
lib/tty/prompt/reader/mode.rb,
lib/tty/prompt/reader/codes.rb,
lib/tty/prompt/reader/console.rb,
lib/tty/prompt/reader/history.rb,
lib/tty/prompt/reader/win_api.rb,
lib/tty/prompt/reader/key_event.rb,
lib/tty/prompt/reader/win_console.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
A class responsible for reading character input from STDIN
Used internally to provide key and line reading functionality
Defined Under Namespace
Modules: Codes, WinAPI Classes: Console, History, Key, KeyEvent, Line, Mode, WinConsole
Constant Summary collapse
- InputInterrupt =
Raised when the user hits the interrupt key(Control-C)
Class.new(StandardError)
- CARRIAGE_RETURN =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Key codes
13
- NEWLINE =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
10
- BACKSPACE =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
127
- DELETE =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
8
Instance Attribute Summary collapse
- #console ⇒ Object readonly private
- #env ⇒ Object readonly private
- #input ⇒ Object readonly private
- #output ⇒ Object readonly private
- #track_history ⇒ Object (also: #track_history?) readonly private
Instance Method Summary collapse
- #add_to_history(line) ⇒ Object private
-
#get_codes(options = {}, codes = []) ⇒ Array[Integer]
private
Get input code points.
- #history_next ⇒ Object private
- #history_next? ⇒ Boolean private
- #history_previous ⇒ Object private
- #history_previous? ⇒ Boolean private
-
#initialize(input = $stdin, output = $stdout, options = {}) ⇒ Reader
constructor
Initialize a Reader.
-
#inspect ⇒ String
Inspect class name and public attributes.
-
#keyctrl_d ⇒ Object
(also: #keyctrl_z)
private
Capture Ctrl+d and Ctrl+z key events.
-
#read_keypress(options = {}) ⇒ String
(also: #read_char)
Read a keypress including invisible multibyte codes and return a character as a string.
-
#read_line(*args) ⇒ String
Get a single line from STDIN.
-
#read_multiline(prompt = '') {|String| ... } ⇒ Array[String]
(also: #read_lines)
Read multiple lines and return them in an array.
-
#select_console(input) ⇒ Object
private
Select appropriate console.
-
#trigger(event, *args) ⇒ Object
Expose event broadcasting.
-
#unbufferred(&block) ⇒ Object
Get input in unbuffered mode.
Constructor Details
#initialize(input = $stdin, output = $stdout, options = {}) ⇒ Reader
Initialize a Reader
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/tty/prompt/reader.rb', line 58 def initialize(input = $stdin, output = $stdout, = {}) @input = input @output = output @interrupt = .fetch(:interrupt) { :error } @env = .fetch(:env) { ENV } @track_history = .fetch(:track_history) { true } @console = select_console(input) @history = History.new do |h| h.duplicates = false h.exclude = proc { |line| line.strip == '' } end @stop = false # gathering input subscribe(self) end |
Instance Attribute Details
#console ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
37 38 39 |
# File 'lib/tty/prompt/reader.rb', line 37 def console @console end |
#env ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
32 33 34 |
# File 'lib/tty/prompt/reader.rb', line 32 def env @env end |
#input ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
28 29 30 |
# File 'lib/tty/prompt/reader.rb', line 28 def input @input end |
#output ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
30 31 32 |
# File 'lib/tty/prompt/reader.rb', line 30 def output @output end |
#track_history ⇒ Object (readonly) Also known as: track_history?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
34 35 36 |
# File 'lib/tty/prompt/reader.rb', line 34 def track_history @track_history end |
Instance Method Details
#add_to_history(line) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
277 278 279 |
# File 'lib/tty/prompt/reader.rb', line 277 def add_to_history(line) @history.push(line) end |
#get_codes(options = {}, codes = []) ⇒ Array[Integer]
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get input code points
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/tty/prompt/reader.rb', line 135 def get_codes( = {}, codes = []) opts = { echo: true, raw: false }.merge() char = console.get_char(opts) return if char.nil? codes << char.ord condition = proc { |escape| (codes - escape).empty? || (escape - codes).empty? && !(64..126).include?(codes.last) } while console.escape_codes.any?(&condition) get_codes(, codes) end codes end |
#history_next ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
285 286 287 288 |
# File 'lib/tty/prompt/reader.rb', line 285 def history_next @history.next @history.get end |
#history_next? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
281 282 283 |
# File 'lib/tty/prompt/reader.rb', line 281 def history_next? @history.next? end |
#history_previous ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
294 295 296 297 298 |
# File 'lib/tty/prompt/reader.rb', line 294 def history_previous line = @history.get @history.previous line end |
#history_previous? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
290 291 292 |
# File 'lib/tty/prompt/reader.rb', line 290 def history_previous? @history.previous? end |
#inspect ⇒ String
Inspect class name and public attributes
304 305 306 |
# File 'lib/tty/prompt/reader.rb', line 304 def inspect "#<#{self.class}: @input=#{input}, @output=#{output}>" end |
#keyctrl_d ⇒ Object Also known as: keyctrl_z
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Capture Ctrl+d and Ctrl+z key events
272 273 274 |
# File 'lib/tty/prompt/reader.rb', line 272 def keyctrl_d(*) @stop = true end |
#read_keypress(options = {}) ⇒ String Also known as: read_char
Read a keypress including invisible multibyte codes and return a character as a string. Nothing is echoed to the console. This call will block for a single keypress, but will not wait for Enter to be pressed.
116 117 118 119 120 121 122 123 124 |
# File 'lib/tty/prompt/reader.rb', line 116 def read_keypress( = {}) opts = { echo: false, raw: true }.merge() codes = unbufferred { get_codes(opts) } char = codes ? codes.pack('U*') : nil trigger_key_event(char) if char handle_interrupt if char == console.keys[:ctrl_c] char end |
#read_line(*args) ⇒ String
Get a single line from STDIN. Each key pressed is echoed back to the shell. The input terminates when enter or return key is pressed.
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 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/tty/prompt/reader.rb', line 166 def read_line(*args) = args.last.respond_to?(:to_hash) ? args.pop : {} prompt = args.empty? ? '' : args.pop opts = { echo: true, raw: true }.merge() line = Line.new('') ctrls = console.keys.keys.grep(/ctrl/) clear_line = "\e[2K\e[1G" while (codes = unbufferred { get_codes(opts) }) && (code = codes[0]) char = codes.pack('U*') trigger_key_event(char) if console.keys[:backspace] == char || BACKSPACE == code next if line.start? line.left line.delete elsif console.keys[:delete] == char || DELETE == code line.delete elsif [console.keys[:ctrl_d], console.keys[:ctrl_z]].include?(char) break elsif console.keys[:ctrl_c] == char handle_interrupt elsif ctrls.include?(console.keys.key(char)) # skip elsif console.keys[:up] == char next unless history_previous? line.replace(history_previous) elsif console.keys[:down] == char line.replace(history_next? ? history_next : '') elsif console.keys[:left] == char line.left elsif console.keys[:right] == char line.right else if opts[:raw] && code == CARRIAGE_RETURN char = "\n" line.move_to_end end line.insert(char) end if opts[:raw] && opts[:echo] output.print(clear_line) output.print(prompt + line.to_s) if char == "\n" line.move_to_start elsif !line.end? output.print("\e[#{line.size - line.cursor}D") end end break if (code == CARRIAGE_RETURN || code == NEWLINE) if (console.keys[:backspace] == char || BACKSPACE == code) && opts[:echo] if opts[:raw] output.print("\e[1X") unless line.start? else output.print(?\s + (line.start? ? '' : ?\b)) end end end add_to_history(line.to_s.rstrip) if track_history? line.to_s end |
#read_multiline(prompt = '') {|String| ... } ⇒ Array[String] Also known as: read_lines
Read multiple lines and return them in an array. Skip empty lines in the returned lines array. The input gathering is terminated by Ctrl+d or Ctrl+z.
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/tty/prompt/reader.rb', line 244 def read_multiline(prompt = '') @stop = false lines = [] loop do line = read_line(prompt) break if !line || line == '' next if line !~ /\S/ && !@stop if block_given? yield(line) unless line.to_s.empty? else lines << line unless line.to_s.empty? end break if @stop end lines end |
#select_console(input) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Select appropriate console
77 78 79 80 81 82 83 |
# File 'lib/tty/prompt/reader.rb', line 77 def select_console(input) if windows? && !env['TTY_TEST'] WinConsole.new(input) else Console.new(input) end end |
#trigger(event, *args) ⇒ Object
Expose event broadcasting
265 266 267 |
# File 'lib/tty/prompt/reader.rb', line 265 def trigger(event, *args) publish(event, *args) end |
#unbufferred(&block) ⇒ Object
Get input in unbuffered mode.
93 94 95 96 97 98 99 100 |
# File 'lib/tty/prompt/reader.rb', line 93 def unbufferred(&block) bufferring = output.sync # Immediately flush output output.sync = true block[] if block_given? ensure output.sync = bufferring end |