Class: RawLine::Editor
- Inherits:
-
Object
- Object
- RawLine::Editor
- Extended by:
- Forwardable
- Includes:
- HighLine::SystemExtensions
- Defined in:
- lib/rawline/editor.rb,
lib/rawline/editor.rb
Overview
The Editor class defines methods to:
-
Read characters from STDIN or any type of input
-
Write characters to STDOUT or any type of output
-
Bind keys to specific actions
-
Perform line-related operations like moving, navigating through history, etc.
Note that the following default key bindings are provided:
-
TAB: word completion defined via completion_proc
-
LEFT/RIGHT ARROWS: cursor movement (left/right)
-
UP/DOWN ARROWS: history navigation
-
DEL: Delete character under cursor
-
BACKSPACE: Delete character before cursor
-
INSERT: Toggle insert/replace mode (default: insert)
-
CTRL+K: Clear the whole line
-
CTRL+Z: undo (unless already registered by the OS)
-
CTRL+Y: redo (unless already registered by the OS)
Defined Under Namespace
Classes: Environment
Instance Attribute Summary collapse
-
#char ⇒ Object
Returns the value of attribute char.
-
#completion_proc ⇒ Object
Returns the value of attribute completion_proc.
-
#content_box ⇒ Object
TODO: dom traversal for lookup rather than assignment.
-
#dom ⇒ Object
Returns the value of attribute dom.
-
#event_loop ⇒ Object
readonly
Returns the value of attribute event_loop.
-
#focused_input_box ⇒ Object
TODO: dom traversal for lookup rather than assignment.
-
#history ⇒ Object
Returns the value of attribute history.
-
#input ⇒ Object
readonly
Returns the value of attribute input.
-
#input_box ⇒ Object
TODO: dom traversal for lookup rather than assignment.
-
#keyboard_input_processors ⇒ Object
readonly
Returns the value of attribute keyboard_input_processors.
-
#line ⇒ Object
Returns the value of attribute line.
-
#match_hidden_files ⇒ Object
Returns the value of attribute match_hidden_files.
-
#mode ⇒ Object
Returns the value of attribute mode.
-
#prompt_box ⇒ Object
TODO: dom traversal for lookup rather than assignment.
-
#terminal ⇒ Object
Returns the value of attribute terminal.
-
#word_break_characters ⇒ Object
Returns the value of attribute word_break_characters.
Class Method Summary collapse
Instance Method Summary collapse
-
#add_to_history(allow_empty: false) ⇒ Object
Add the current line (
@line.text) to the editor history. -
#add_to_line_history(allow_empty: false) ⇒ Object
Add the current line (
@line.text) to the line history, to allow undo/redo operations. -
#bind(key, &block) ⇒ Object
Bind a key to an action specified via
block. -
#check_for_keyboard_input ⇒ Object
INPUT.
-
#clear_history ⇒ Object
Clear the editor history.
-
#clear_line ⇒ Object
Clear the current line, i.e.
- #clear_screen ⇒ Object
-
#complete ⇒ Object
Complete the current word according to what returned by
@completion_proc. - #completion_class ⇒ Object
- #completion_done ⇒ Object
- #completion_found(completion:, possible_completions:) ⇒ Object
- #completion_not_found ⇒ Object
- #completion_selected(completion) ⇒ Object
-
#debug_line ⇒ Object
Print debug information about the current line.
-
#default_action ⇒ Object
Execute the default action for the last character read via
read. -
#delete_character(no_line_history = false) ⇒ Object
Delete the character under the cursor.
-
#delete_left_character(no_line_history = false) ⇒ Object
Delete the character at the left of the cursor.
- #delete_n_characters(number_of_characters_to_delete, no_line_history = false) ⇒ Object
- #env ⇒ Object
- #escape(string) ⇒ Object
-
#events ⇒ Object
Returns the Editor’s event loop.
-
#filename_completion_proc ⇒ Object
Complete file and directory names.
- #focus_input_box(box) ⇒ Object
- #highlight_text_up_to(text, position) ⇒ Object
-
#history_back ⇒ Object
Load the previous entry of the editor in place of the current line (
@line.text). -
#history_forward ⇒ Object
Load the next entry of the editor history in place of the current line (
@line.text). -
#initialize(dom:, input:, renderer:, terminal:) {|_self| ... } ⇒ Editor
constructor
Create an instance of RawLine::Editor which can be used to read from input and perform line-editing operations.
-
#insert(string, add_to_line_history: true) ⇒ Object
Inserts a string at the current line position, shifting characters to right if necessary.
-
#key_bound? ⇒ Boolean
Return true if the last character read via
readis bound to an action. - #keyboard_input_processor ⇒ Object
- #keys ⇒ Object
- #kill_forward ⇒ Object
-
#library_version ⇒ Object
Return the current RawLine version.
-
#move_left ⇒ Object
Move the cursor left (if possible) by printing a backspace, updating
@line.positionaccordingly. -
#move_right ⇒ Object
Move the cursor right (if possible) by re-printing the character at the right of the cursor, if any, and updating
@line.positionaccordingly. - #move_to_beginning_of_input ⇒ Object
- #move_to_end_of_input ⇒ Object
-
#move_to_position(pos) ⇒ Object
Move the cursor to
pos. - #new_env ⇒ Object
-
#newline ⇒ Object
Adds
@line.textto the editor history. - #on_read_line(&blk) ⇒ Object
- #on_word_complete(&blk) ⇒ Object
- #on_word_complete_done(&blk) ⇒ Object
- #on_word_complete_no_match(&blk) ⇒ Object
- #on_word_completion_selected(&blk) ⇒ Object
-
#overwrite_line(new_line, position: nil, highlight_up_to: nil) ⇒ Object
Overwrite the current line (
@line.text) withnew_line, and optionally reset the cursor position toposition. -
#parse_key_code_sequences(bytes) ⇒ Object
Parse a key or key sequence into the corresponding codes.
- #pop_env ⇒ Object
- #pop_keyboard_input_processor ⇒ Object
-
#press_key ⇒ Object
Call the action bound to the last character read via
read. -
#process_character ⇒ Object
Process a character.
- #process_line ⇒ Object
- #prompt ⇒ Object
- #prompt=(text) ⇒ Object
- #push_env(env) ⇒ Object
- #push_keyboard_input_processor(kip) ⇒ Object
-
#puts(*args) ⇒ Object
Write to
outputand then immediately re-render. - #read_bytes(bytes) ⇒ Object
-
#redo ⇒ Object
Redo a previously-undone modification to the current line (
@line.text). - #redraw_prompt ⇒ Object
- #reset_line ⇒ Object
-
#show_history ⇒ Object
Print the content of the editor history.
-
#start ⇒ Object
Starts the editor event loop.
-
#subscribe(*args, &blk) ⇒ Object
Subscribes to an event with the given block as a callback.
- #terminal_height ⇒ Object
- #terminal_width ⇒ Object
-
#toggle_mode ⇒ Object
Toggle the editor
@modeto :replace or :insert (default). - #unbind(key) ⇒ Object
-
#undo ⇒ Object
Undo the last modification to the current line (
@line.text). -
#write(string, add_to_line_history: true) ⇒ Object
Write a string starting from the cursor position ovewriting any character at the current position if necessary.
- #yank_forward(text) ⇒ Object
Constructor Details
#initialize(dom:, input:, renderer:, terminal:) {|_self| ... } ⇒ Editor
Create an instance of RawLine::Editor which can be used to read from input and perform line-editing operations. This method takes an optional block used to override the following instance attributes:
-
@word_break_characters- a regex used for word separation, default inclues: “ tn"\‘`@$><=;|&{(” -
@mode- The editor’s character insertion mode (:insert). -
@completion_proc- a Proc object used to perform word completion. -
@terminal- a RawLine::Terminal containing character key codes.
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/rawline/editor.rb', line 131 def initialize(dom:, input:, renderer:, terminal:) @dom = dom @input = input @renderer = renderer @terminal = terminal @env_stack = [Environment.new(terminal: terminal)] @word_break_characters = " \t\n\"'@><=;|&{()}" @mode = :insert @completion_proc = filename_completion_proc @match_hidden_files = false set_default_keys @add_history = false push_keyboard_input_processor self yield self if block_given? update_word_separator @char = nil initialize_events initialize_line end |
Instance Attribute Details
#char ⇒ Object
Returns the value of attribute char.
44 45 46 |
# File 'lib/rawline/editor.rb', line 44 def char @char end |
#completion_proc ⇒ Object
Returns the value of attribute completion_proc.
46 47 48 |
# File 'lib/rawline/editor.rb', line 46 def completion_proc @completion_proc end |
#content_box ⇒ Object
TODO: dom traversal for lookup rather than assignment
52 53 54 |
# File 'lib/rawline/editor.rb', line 52 def content_box @content_box end |
#dom ⇒ Object
Returns the value of attribute dom.
49 50 51 |
# File 'lib/rawline/editor.rb', line 49 def dom @dom end |
#event_loop ⇒ Object (readonly)
Returns the value of attribute event_loop.
156 157 158 |
# File 'lib/rawline/editor.rb', line 156 def event_loop @event_loop end |
#focused_input_box ⇒ Object
TODO: dom traversal for lookup rather than assignment
52 53 54 |
# File 'lib/rawline/editor.rb', line 52 def focused_input_box @focused_input_box end |
#history ⇒ Object
Returns the value of attribute history.
46 47 48 |
# File 'lib/rawline/editor.rb', line 46 def history @history end |
#input ⇒ Object (readonly)
Returns the value of attribute input.
156 157 158 |
# File 'lib/rawline/editor.rb', line 156 def input @input end |
#input_box ⇒ Object
TODO: dom traversal for lookup rather than assignment
52 53 54 |
# File 'lib/rawline/editor.rb', line 52 def input_box @input_box end |
#keyboard_input_processors ⇒ Object (readonly)
Returns the value of attribute keyboard_input_processors.
157 158 159 |
# File 'lib/rawline/editor.rb', line 157 def keyboard_input_processors @keyboard_input_processors end |
#line ⇒ Object
Returns the value of attribute line.
46 47 48 |
# File 'lib/rawline/editor.rb', line 46 def line @line end |
#match_hidden_files ⇒ Object
Returns the value of attribute match_hidden_files.
47 48 49 |
# File 'lib/rawline/editor.rb', line 47 def match_hidden_files @match_hidden_files end |
#mode ⇒ Object
Returns the value of attribute mode.
45 46 47 |
# File 'lib/rawline/editor.rb', line 45 def mode @mode end |
#prompt_box ⇒ Object
TODO: dom traversal for lookup rather than assignment
52 53 54 |
# File 'lib/rawline/editor.rb', line 52 def prompt_box @prompt_box end |
#terminal ⇒ Object
Returns the value of attribute terminal.
45 46 47 |
# File 'lib/rawline/editor.rb', line 45 def terminal @terminal end |
#word_break_characters ⇒ Object
Returns the value of attribute word_break_characters.
48 49 50 |
# File 'lib/rawline/editor.rb', line 48 def word_break_characters @word_break_characters end |
Class Method Details
.create(dom: nil, &blk) ⇒ Object
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 |
# File 'lib/rawline/editor.rb', line 54 def self.create(dom: nil, &blk) terminal = nil input = STDIN output = STDOUT case RUBY_PLATFORM when /mswin/i then terminal = WindowsTerminal.new(input, output) if RawLine.win32console? then win32_io = Win32::Console::ANSI::IO.new end else terminal = VT220Terminal.new(input, output) end dom ||= DomTree.new renderer = RawLine::Renderer.new( dom: dom, output: terminal.output, width: terminal.width, height: terminal.height ) KeyBindings.default_terminal = terminal new( dom: dom, input: NonBlockingInput.new(input), renderer: renderer, terminal: terminal, &blk ) end |
Instance Method Details
#add_to_history(allow_empty: false) ⇒ Object
Add the current line (@line.text) to the editor history.
789 790 791 792 793 794 |
# File 'lib/rawline/editor.rb', line 789 def add_to_history(allow_empty: false) if @add_history && (allow_empty || !@line.text.empty?) Treefell['editor'].puts "add_to_history text=#{@line.text}" history << @line.text.dup end end |
#add_to_line_history(allow_empty: false) ⇒ Object
Add the current line (@line.text) to the line history, to allow undo/redo operations.
779 780 781 782 783 784 |
# File 'lib/rawline/editor.rb', line 779 def add_to_line_history(allow_empty: false) if allow_empty || !@line.text.empty? Treefell['editor'].puts "add_to_line_history text=#{@line.text}" @line.history << @line.text.dup end end |
#bind(key, &block) ⇒ Object
Bind a key to an action specified via block. key can be:
-
A Symbol identifying a character or character sequence defined for the current terminal
-
A Fixnum identifying a character defined for the current terminal
-
An Array identifying a character or character sequence defined for the current terminal
-
A String identifying a character or character sequence, even if it is not defined for the current terminal
-
An Hash identifying a character or character sequence, even if it is not defined for the current terminal
If key is a hash, then:
-
It must contain only one key/value pair
-
The key identifies the name of the character or character sequence
-
The value identifies the code(s) corresponding to the character or character sequence
-
The value can be a Fixnum, a String or an Array.
331 332 333 |
# File 'lib/rawline/editor.rb', line 331 def bind(key, &block) keys.bind(key, &block) end |
#check_for_keyboard_input ⇒ Object
INPUT
246 247 248 249 250 251 252 |
# File 'lib/rawline/editor.rb', line 246 def check_for_keyboard_input bytes = @input.read if bytes.any? keyboard_input_processor.read_bytes(bytes) end @event_loop.add_event name: 'check_for_keyboard_input', source: self end |
#clear_history ⇒ Object
Clear the editor history.
732 733 734 |
# File 'lib/rawline/editor.rb', line 732 def clear_history history.empty end |
#clear_line ⇒ Object
Clear the current line, i.e. @line.text and @line.position. This action is bound to ctrl+k by default.
394 395 396 397 398 399 |
# File 'lib/rawline/editor.rb', line 394 def clear_line Treefell['editor'].puts "clear_line" add_to_line_history @line_editor.clear_line history.clear_position end |
#clear_screen ⇒ Object
401 402 403 404 405 |
# File 'lib/rawline/editor.rb', line 401 def clear_screen Treefell['editor'].puts "clear_screen" @terminal.clear_screen render(reset: true) end |
#complete ⇒ Object
Complete the current word according to what returned by @completion_proc. Characters can be appended to the completed word via @completion_append_character and word separators can be defined via @word_separator.
This action is bound to the tab key by default, so the first match is displayed the first time the user presses tab, and all the possible messages will be displayed (cyclically) when tab is pressed again.
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 |
# File 'lib/rawline/editor.rb', line 595 def complete focused_input_box.cursor_off completer = completion_class.new( char: @char, line: @line, completion: @completion_proc, completion_found: -> (completion:, possible_completions:) { completion_found(completion: completion, possible_completions: possible_completions) }, completion_not_found: -> { completion_not_found }, completion_selected: -> (completion) { completion_selected(completion) }, done: -> (*leftover_bytes){ completion_done leftover_bytes = leftover_bytes.flatten pop_keyboard_input_processor if leftover_bytes.any? keyboard_input_processor.read_bytes(leftover_bytes) end focused_input_box.cursor_on }, keys: terminal.keys ) push_keyboard_input_processor(completer) completer.read_bytes(@char) end |
#completion_class ⇒ Object
167 |
# File 'lib/rawline/editor.rb', line 167 def completion_class ; @env_stack.first.completion_class ; end |
#completion_done ⇒ Object
661 662 663 664 665 666 667 668 |
# File 'lib/rawline/editor.rb', line 661 def completion_done if @on_word_complete_done Treefell['editor'].puts "word-completion-done calling on_word_complete_done callback" @on_word_complete_done.call else Treefell['editor'].puts 'word-completion-done no on_word_complete_done callback to call' end end |
#completion_found(completion:, possible_completions:) ⇒ Object
625 626 627 628 629 630 631 632 633 634 |
# File 'lib/rawline/editor.rb', line 625 def completion_found(completion:, possible_completions:) Treefell['editor'].puts "word-completion-found: #{completion.inspect} possible_completions: #{possible_completions.inspect}" if @on_word_complete word = @line.word[:text] sub_word = @line.text[@line.word[:start]..@line.position-1] || "" @on_word_complete.call(name: "word-completion", payload: { sub_word: sub_word, word: word, completion: completion, possible_completions: possible_completions }) end completion_selected(completion) end |
#completion_not_found ⇒ Object
648 649 650 651 652 653 654 655 656 657 658 659 |
# File 'lib/rawline/editor.rb', line 648 def completion_not_found Treefell['editor'].puts 'word-completion-not-found' if @on_word_complete_no_match word = @line.word[:text] sub_word = @line.text[@line.word[:start]..@line.position-1] || "" payload = { sub_word: sub_word, word: word } Treefell['editor'].puts "word-completion-not-found calling callback with payload: #{payload.inspect}" @on_word_complete_no_match.call(name: "word-completion-no-match", payload: payload) else Treefell['editor'].puts 'word-completion-not-found no on_word_complete_no_match callback to call' end end |
#completion_selected(completion) ⇒ Object
636 637 638 639 640 641 642 643 644 645 646 |
# File 'lib/rawline/editor.rb', line 636 def completion_selected(completion) Treefell['editor'].puts "word-completion-selected #{completion.inspect}" move_to_position @line.word[:end] delete_n_characters(@line.word[:end] - @line.word[:start], true) write completion.to_s if @on_word_completion_selected Treefell['editor'].puts "word-completion-selected callback called with #{completioni}" @on_word_completion_selected.call(name: "word-completion-selected", payload: { completion: completion }) end end |
#debug_line ⇒ Object
Print debug information about the current line. Note that after the message is displayed, the line text and position will be restored.
806 807 808 809 810 811 812 813 814 815 816 817 818 |
# File 'lib/rawline/editor.rb', line 806 def debug_line pos = @line.position text = @line.text word = @line.word # terminal.puts # terminal.puts "Text: [#{text}]" # terminal.puts "Length: #{@line.length}" # terminal.puts "Position: #{pos}" # terminal.puts "Character at Position: [#{text[pos].chr}] (#{text[pos]})" unless pos >= @line.length # terminal.puts "Current Word: [#{word[:text]}] (#{word[:start]} -- #{word[:end]})" clear_line overwrite_line(text, position: pos) end |
#default_action ⇒ Object
Execute the default action for the last character read via read. By default it prints the character to the screen via write. This method is called automatically by process_character.
359 360 361 |
# File 'lib/rawline/editor.rb', line 359 def default_action insert(@char) end |
#delete_character(no_line_history = false) ⇒ Object
Delete the character under the cursor. If no_line_hisytory is set to true, the deletion won’t be recorded in the line history. This action is bound to the delete key by default.
435 436 437 438 439 440 441 |
# File 'lib/rawline/editor.rb', line 435 def delete_character(no_line_history=false) Treefell['editor'].puts "delete_character" if @line_editor.delete_character add_to_line_history unless no_line_history history.clear_position end end |
#delete_left_character(no_line_history = false) ⇒ Object
Delete the character at the left of the cursor. If no_line_hisytory is set to true, the deletion won’t be recorded in the line history. This action is bound to the backspace key by default.
413 414 415 416 417 418 419 |
# File 'lib/rawline/editor.rb', line 413 def delete_left_character(no_line_history=false) Treefell['editor'].puts "delete_left_character" if @line_editor.delete_left_character add_to_line_history unless no_line_history history.clear_position end end |
#delete_n_characters(number_of_characters_to_delete, no_line_history = false) ⇒ Object
421 422 423 424 425 426 427 |
# File 'lib/rawline/editor.rb', line 421 def delete_n_characters(number_of_characters_to_delete, no_line_history=false) Treefell['editor'].puts "delete_n_characters n=#{number_of_characters_to_delete}" if @line_editor.delete_n_characters(number_of_characters_to_delete) add_to_line_history unless no_line_history history.clear_position end end |
#env ⇒ Object
159 |
# File 'lib/rawline/editor.rb', line 159 def env ; @env_stack.last ; end |
#escape(string) ⇒ Object
945 946 947 |
# File 'lib/rawline/editor.rb', line 945 def escape(string) string.each_byte { |c| @win32_io.putc c } end |
#events ⇒ Object
Returns the Editor’s event loop.
236 237 238 |
# File 'lib/rawline/editor.rb', line 236 def events @event_loop end |
#filename_completion_proc ⇒ Object
Complete file and directory names. Hidden files and directories are matched only if @match_hidden_files is true.
694 695 696 697 698 699 700 701 702 703 704 705 706 |
# File 'lib/rawline/editor.rb', line 694 def filename_completion_proc lambda do |word, _| dirs = @line.text.split('/') path = @line.text.match(/^\/|[a-zA-Z]:\//) ? "/" : Dir.pwd+"/" if dirs.length == 0 then # starting directory dir = path else dirs.delete(dirs.last) unless File.directory?(path+dirs.join('/')) dir = path+dirs.join('/') end Dir.entries(dir).select { |e| (e =~ /^\./ && @match_hidden_files && word == '') || (e =~ /^#{word}/ && e !~ /^\./) } end end |
#focus_input_box(box) ⇒ Object
820 821 822 823 |
# File 'lib/rawline/editor.rb', line 820 def focus_input_box(box) @dom.focus_input_box(box) @renderer.render_cursor end |
#highlight_text_up_to(text, position) ⇒ Object
443 444 445 446 |
# File 'lib/rawline/editor.rb', line 443 def highlight_text_up_to(text, position) Treefell['editor'].puts "highlight_text_up_to text=#{text} position=#{position}" @line_editor.highlight_text_up_to(text, position) end |
#history_back ⇒ Object
Load the previous entry of the editor in place of the current line (@line.text). This action is bound to the up arrow key by default.
759 760 761 762 |
# File 'lib/rawline/editor.rb', line 759 def history_back generic_history_back(history) add_to_line_history end |
#history_forward ⇒ Object
Load the next entry of the editor history in place of the current line (@line.text). This action is bound to down arrow key by default.
769 770 771 772 |
# File 'lib/rawline/editor.rb', line 769 def history_forward generic_history_forward(history) add_to_line_history end |
#insert(string, add_to_line_history: true) ⇒ Object
Inserts a string at the current line position, shifting characters to right if necessary.
452 453 454 455 456 457 |
# File 'lib/rawline/editor.rb', line 452 def insert(string, add_to_line_history: true) Treefell['editor'].puts "insert string=#{string} add_to_line_history=#{add_to_line_history}" if @line_editor.insert(string) self.add_to_line_history if add_to_line_history end end |
#key_bound? ⇒ Boolean
Return true if the last character read via read is bound to an action.
342 343 344 |
# File 'lib/rawline/editor.rb', line 342 def key_bound? keys.bound?(@char) end |
#keyboard_input_processor ⇒ Object
163 |
# File 'lib/rawline/editor.rb', line 163 def keyboard_input_processor ; env.keyboard_input_processors.last ; end |
#keys ⇒ Object
169 |
# File 'lib/rawline/editor.rb', line 169 def keys ; @env_stack.first.keys ; end |
#kill_forward ⇒ Object
459 460 461 462 463 464 465 |
# File 'lib/rawline/editor.rb', line 459 def kill_forward Treefell['editor'].puts "kill_forward" @line_editor.kill_forward.tap do add_to_line_history(allow_empty: true) history.clear_position end end |
#library_version ⇒ Object
Return the current RawLine version
174 175 176 |
# File 'lib/rawline/editor.rb', line 174 def library_version "RawLine v#{RawLine::VERSION}" end |
#move_left ⇒ Object
Move the cursor left (if possible) by printing a backspace, updating @line.position accordingly. This action is bound to the left arrow key by default.
491 492 493 494 |
# File 'lib/rawline/editor.rb', line 491 def move_left Treefell['editor'].puts "move_left" @line_editor.move_left end |
#move_right ⇒ Object
Move the cursor right (if possible) by re-printing the character at the right of the cursor, if any, and updating @line.position accordingly. This action is bound to the right arrow key by default.
502 503 504 505 |
# File 'lib/rawline/editor.rb', line 502 def move_right Treefell['editor'].puts "move_right" @line_editor.move_right end |
#move_to_beginning_of_input ⇒ Object
507 508 509 510 |
# File 'lib/rawline/editor.rb', line 507 def move_to_beginning_of_input Treefell['editor'].puts "move_to_beginning_of_input" @line_editor.move_to_beginning_of_input end |
#move_to_end_of_input ⇒ Object
512 513 514 515 |
# File 'lib/rawline/editor.rb', line 512 def move_to_end_of_input Treefell['editor'].puts "move_to_end_of_input" @line_editor.move_to_end_of_input end |
#move_to_position(pos) ⇒ Object
Move the cursor to pos.
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 |
# File 'lib/rawline/editor.rb', line 520 def move_to_position(pos) Treefell['editor'].puts "move_to_position position=#{pos}" rows_to_move = current_terminal_row - terminal_row_for_line_position(pos) if rows_to_move > 0 # rows_to_move.times { @output.print @terminal.term_info.control_string("cuu1") } # @terminal.move_up_n_rows(rows_to_move) else # rows_to_move.abs.times { @output.print @terminal.term_info.control_string("cud1") } # @terminal.move_down_n_rows(rows_to_move.abs) end column = (@line.prompt.length + pos) % terminal_width # @output.print @terminal.term_info.control_string("hpa", column) # @terminal.move_to_column((@line.prompt.length + pos) % terminal_width) @line_editor.position = pos end |
#new_env ⇒ Object
160 |
# File 'lib/rawline/editor.rb', line 160 def new_env ; Environment.new ; end |
#newline ⇒ Object
Adds @line.text to the editor history. This action is bound to the enter key by default.
374 375 376 377 |
# File 'lib/rawline/editor.rb', line 374 def newline add_to_history history.clear_position end |
#on_read_line(&blk) ⇒ Object
379 380 381 |
# File 'lib/rawline/editor.rb', line 379 def on_read_line(&blk) @event_registry.subscribe :line_read, &blk end |
#on_word_complete(&blk) ⇒ Object
670 671 672 673 |
# File 'lib/rawline/editor.rb', line 670 def on_word_complete(&blk) Treefell['editor'].puts "setting on_word_complete callback" @on_word_complete = blk end |
#on_word_complete_done(&blk) ⇒ Object
680 681 682 683 |
# File 'lib/rawline/editor.rb', line 680 def on_word_complete_done(&blk) Treefell['editor'].puts "setting on_word_complete_done callback" @on_word_complete_done = blk end |
#on_word_complete_no_match(&blk) ⇒ Object
675 676 677 678 |
# File 'lib/rawline/editor.rb', line 675 def on_word_complete_no_match(&blk) Treefell['editor'].puts "setting on_word_complete_no_match callback" @on_word_complete_no_match = blk end |
#on_word_completion_selected(&blk) ⇒ Object
685 686 687 688 |
# File 'lib/rawline/editor.rb', line 685 def on_word_completion_selected(&blk) Treefell['editor'].puts "setting on_word_completion_selected callback" @on_word_completion_selected = blk end |
#overwrite_line(new_line, position: nil, highlight_up_to: nil) ⇒ Object
Overwrite the current line (@line.text) with new_line, and optionally reset the cursor position to position.
541 542 543 544 545 546 |
# File 'lib/rawline/editor.rb', line 541 def overwrite_line(new_line, position: nil, highlight_up_to: nil) Treefell['editor'].puts "overwrite_line new_line=#{new_line} position=#{position} highlight_up_to=#{highlight_up_to}" if @line_editor.overwrite_line(new_line, position: position, highlight_up_to: highlight_up_to) @event_loop.add_event name: "render", source: focused_input_box end end |
#parse_key_code_sequences(bytes) ⇒ Object
Parse a key or key sequence into the corresponding codes.
366 367 368 |
# File 'lib/rawline/editor.rb', line 366 def parse_key_code_sequences(bytes) KeycodeParser.new(@terminal.keys).parse_bytes_into_sequences(bytes) end |
#pop_env ⇒ Object
162 |
# File 'lib/rawline/editor.rb', line 162 def pop_env ; @env_stack.pop ; end |
#pop_keyboard_input_processor ⇒ Object
165 |
# File 'lib/rawline/editor.rb', line 165 def pop_keyboard_input_processor ; env.keyboard_input_processors.pop ; end |
#press_key ⇒ Object
Call the action bound to the last character read via read. This method is called automatically by process_character.
350 351 352 |
# File 'lib/rawline/editor.rb', line 350 def press_key keys[@char].call end |
#process_character ⇒ Object
Process a character. If the key corresponding to the inputted character is bound to an action, call press_key, otherwise call default_action. This method is called automatically by read
306 307 308 309 310 311 312 |
# File 'lib/rawline/editor.rb', line 306 def process_character if @char.is_a?(Array) press_key if key_bound? else default_action end end |
#process_line ⇒ Object
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 |
# File 'lib/rawline/editor.rb', line 281 def process_line @event_loop.immediately(name: "process_line", source: self) do add_to_history @terminal.snapshot_tty_attrs @terminal.pseudo_cooked! @terminal.move_to_beginning_of_row @terminal.puts end @event_loop.immediately(name: "line_read", source: self, payload: { line: @line.text.without_ansi.dup }) @event_loop.immediately(name: "prepare_new_line", source: self) do history.clear_position reset_line move_to_beginning_of_input end @event_loop.immediately(name: "restore_tty_attrs", source: self) { @terminal.restore_tty_attrs } @event_loop.immediately(name: "render", source: self, payload: { reset: true }) end |
#prompt ⇒ Object
178 179 180 |
# File 'lib/rawline/editor.rb', line 178 def prompt @prompt end |
#prompt=(text) ⇒ Object
182 183 184 185 186 187 |
# File 'lib/rawline/editor.rb', line 182 def prompt=(text) return if @line && @line.prompt == text @prompt = Prompt.new(text) Treefell['editor'].puts "prompt=#{prompt.inspect}" @dom.prompt_box.content = @prompt end |
#push_env(env) ⇒ Object
161 |
# File 'lib/rawline/editor.rb', line 161 def push_env(env) ; @env_stack.push env ; end |
#push_keyboard_input_processor(kip) ⇒ Object
164 |
# File 'lib/rawline/editor.rb', line 164 def push_keyboard_input_processor(kip) ; env.keyboard_input_processors.push kip ; end |
#puts(*args) ⇒ Object
Write to output and then immediately re-render.
573 574 575 576 |
# File 'lib/rawline/editor.rb', line 573 def puts(*args) @terminal.puts(*args) render(reset: true) end |
#read_bytes(bytes) ⇒ Object
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/rawline/editor.rb', line 254 def read_bytes(bytes) return unless bytes.any? Treefell['editor'].puts "read_bytes #{bytes.inspect}" old_position = @line.position key_code_sequences = parse_key_code_sequences(bytes) Treefell['editor'].puts "key code sequences: #{key_code_sequences.inspect}" begin key_code_sequences.each do |sequence| @char = sequence if @char == @terminal.keys[:enter] || !@char Treefell['editor'].puts "processing line: #{@line.text.inspect}" @renderer.pause process_line else process_character new_position = @line.position end end ensure @renderer.unpause end end |
#redo ⇒ Object
Redo a previously-undone modification to the current line (@line.text). This action is bound to ctrl+y by default.
750 751 752 |
# File 'lib/rawline/editor.rb', line 750 def redo generic_history_forward(@line.history) end |
#redraw_prompt ⇒ Object
189 190 191 192 |
# File 'lib/rawline/editor.rb', line 189 def redraw_prompt Treefell['editor'].puts "redrawing prompt=#{prompt.inspect} reset=true" render(reset: true) end |
#reset_line ⇒ Object
548 549 550 551 552 |
# File 'lib/rawline/editor.rb', line 548 def reset_line Treefell['editor'].puts "reset_line" initialize_line render(reset: true) end |
#show_history ⇒ Object
Print the content of the editor history. Note that after the message is displayed, the line text and position will be restored.
718 719 720 721 722 723 724 725 726 727 |
# File 'lib/rawline/editor.rb', line 718 def show_history pos = @line.position text = @line.text max_index_width = history.length.to_s.length history.each_with_index do |item, i| @terminal.puts sprintf("%-#{max_index_width}d %s\n", i+1, item) end render(reset: true) overwrite_line(text, position: pos) end |
#start ⇒ Object
Starts the editor event loop. Must be called before the editor can be interacted with.
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/rawline/editor.rb', line 210 def start @terminal.raw! at_exit { @terminal.cooked! } Signal.trap("SIGWINCH") do Treefell['editor'].puts "terminal-resized trap=SIGWINCH" @event_loop.add_event name: "terminal-resized", source: self end @event_registry.subscribe("terminal-resized") do width, height = terminal_width, terminal_height Treefell['editor'].puts "terminal-resizing width=#{width} height=#{height}" @renderer.update_dimensions(width: width, height: height) @event_loop.add_event name: "render", source: self end @event_loop.add_event name: "render", source: self @event_loop.start end |
#subscribe(*args, &blk) ⇒ Object
Subscribes to an event with the given block as a callback.
231 232 233 |
# File 'lib/rawline/editor.rb', line 231 def subscribe(*args, &blk) @event_registry.subscribe(*args, &blk) end |
#terminal_height ⇒ Object
195 |
# File 'lib/rawline/editor.rb', line 195 def terminal_height ; @terminal.height ; end |
#terminal_width ⇒ Object
194 |
# File 'lib/rawline/editor.rb', line 194 def terminal_width ; @terminal.width ; end |
#toggle_mode ⇒ Object
Toggle the editor @mode to :replace or :insert (default).
557 558 559 560 561 562 |
# File 'lib/rawline/editor.rb', line 557 def toggle_mode case @mode when :insert then @mode = :replace when :replace then @mode = :insert end end |
#unbind(key) ⇒ Object
335 336 337 |
# File 'lib/rawline/editor.rb', line 335 def unbind(key) keys.unbind(key) end |
#undo ⇒ Object
Undo the last modification to the current line (@line.text). This action is bound to ctrl+z by default.
740 741 742 743 |
# File 'lib/rawline/editor.rb', line 740 def undo generic_history_back(@line.history) if @line.history.position == nil generic_history_back(@line.history) end |
#write(string, add_to_line_history: true) ⇒ Object
Write a string starting from the cursor position ovewriting any character at the current position if necessary.
471 472 473 474 475 476 |
# File 'lib/rawline/editor.rb', line 471 def write(string, add_to_line_history: true) Treefell['editor'].puts "write string=#{string}" if @line_editor.write(string) self.add_to_line_history if add_to_line_history end end |
#yank_forward(text) ⇒ Object
478 479 480 481 482 483 484 |
# File 'lib/rawline/editor.rb', line 478 def yank_forward(text) Treefell['editor'].puts "yank_forward" @line_editor.yank_forward(text).tap do add_to_line_history history.clear_position end end |