類別 Reline::LineEditor
常數
- CompletionJourneyData
- DIALOG_DEFAULT_HEIGHT
- MINIMUM_SCROLLBAR_HEIGHT
- MenuInfo
- PROMPT_LIST_CACHE_TIMEOUT
- VI_MOTIONS
屬性
auto_indent_proc[RW]
byte_pointer[R]
completion_append_character[RW]
completion_proc[RW]
confirm_multiline_termination_proc[RW]
dig_perfect_match_proc[RW]
line[R]
待辦事項:取消 TODO:在放棄 Ruby 2.5 後使用「private alias_method」慣用語。
output[W]
output_modifier_proc[RW]
pre_input_hook[RW]
prompt_proc[RW]
公共類別方法
new(config, encoding) 按一下以切換來源
# File lib/reline/line_editor.rb, line 57 def initialize(config, encoding) @config = config @completion_append_character = '' reset_variables(encoding: encoding) end
公共實例方法
add_dialog_proc(name, p, context = nil) 按一下以切換來源
# File lib/reline/line_editor.rb, line 639 def add_dialog_proc(name, p, context = nil) dialog = Dialog.new(name, @config, DialogProcScope.new(self, @config, p, context)) if index = @dialogs.find_index { |d| d.name == name } @dialogs[index] = dialog else @dialogs << dialog end end
byte_pointer=(val) 按一下以切換來源
# File lib/reline/line_editor.rb, line 1839 def byte_pointer=(val) @byte_pointer = val str = @line.byteslice(0, @byte_pointer) @cursor = calculate_width(str) @cursor_max = calculate_width(@line) end
call_completion_proc() 按一下以切換來源
# File lib/reline/line_editor.rb, line 1610 def call_completion_proc result = retrieve_completion_block(true) pre, target, post = result result = call_completion_proc_with_checking_args(pre, target, post) Reline.core.instance_variable_set(:@completion_quote_character, nil) result end
call_completion_proc_with_checking_args(pre, target, post) 按一下以切換來源
# File lib/reline/line_editor.rb, line 1618 def call_completion_proc_with_checking_args(pre, target, post) if @completion_proc and target argnum = @completion_proc.parameters.inject(0) { |result, item| case item.first when :req, :opt result + 1 when :rest break 3 end } case argnum when 1 result = @completion_proc.(target) when 2 result = @completion_proc.(target, pre) when 3..Float::INFINITY result = @completion_proc.(target, pre, post) end end result end
confirm_multiline_termination() 按一下以切換來源
# File lib/reline/line_editor.rb, line 1757 def confirm_multiline_termination temp_buffer = @buffer_of_lines.dup if @previous_line_index and @line_index == (@buffer_of_lines.size - 1) temp_buffer[@previous_line_index] = @line else temp_buffer[@line_index] = @line end @confirm_multiline_termination_proc.(temp_buffer.join("\n") + "\n") end
delete_text(start = nil, length = nil) 按一下以切換來源
# File lib/reline/line_editor.rb, line 1779 def delete_text(start = nil, length = nil) if start.nil? and length.nil? if @is_multiline if @buffer_of_lines.size == 1 @line&.clear @byte_pointer = 0 @cursor = 0 @cursor_max = 0 elsif @line_index == (@buffer_of_lines.size - 1) and @line_index > 0 @buffer_of_lines.pop @line_index -= 1 @line = @buffer_of_lines[@line_index] @byte_pointer = 0 @cursor = 0 @cursor_max = calculate_width(@line) elsif @line_index < (@buffer_of_lines.size - 1) @buffer_of_lines.delete_at(@line_index) @line = @buffer_of_lines[@line_index] @byte_pointer = 0 @cursor = 0 @cursor_max = calculate_width(@line) end else @line&.clear @byte_pointer = 0 @cursor = 0 @cursor_max = 0 end elsif not start.nil? and not length.nil? if @line before = @line.byteslice(0, start) after = @line.byteslice(start + length, @line.bytesize) @line = before + after @byte_pointer = @line.bytesize if @byte_pointer > @line.bytesize str = @line.byteslice(0, @byte_pointer) @cursor = calculate_width(str) @cursor_max = calculate_width(@line) end elsif start.is_a?(Range) range = start first = range.first last = range.last last = @line.bytesize - 1 if last > @line.bytesize last += @line.bytesize if last < 0 first += @line.bytesize if first < 0 range = range.exclude_end? ? first...last : first..last @line = @line.bytes.reject.with_index{ |c, i| range.include?(i) }.map{ |c| c.chr(Encoding::ASCII_8BIT) }.join.force_encoding(@encoding) @byte_pointer = @line.bytesize if @byte_pointer > @line.bytesize str = @line.byteslice(0, @byte_pointer) @cursor = calculate_width(str) @cursor_max = calculate_width(@line) else @line = @line.byteslice(0, start) @byte_pointer = @line.bytesize if @byte_pointer > @line.bytesize str = @line.byteslice(0, @byte_pointer) @cursor = calculate_width(str) @cursor_max = calculate_width(@line) end end
editing_mode() 按一下以切換來源
# File lib/reline/line_editor.rb, line 1226 def editing_mode @config.editing_mode end
eof?() 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 252 def eof? @eof end
finalize() 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 248 def finalize Signal.trap('INT', @old_trap) end
finish() 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 1865 def finish @finished = true @rerender_all = true @config.reset end
finished?() 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 1861 def finished? @finished end
input_key(key) 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 1535 def input_key(key) @last_key = key @config.reset_oneshot_key_bindings @dialogs.each do |dialog| if key.char.instance_of?(Symbol) and key.char == dialog.name return end end @just_cursor_moving = nil if key.char.nil? if @first_char @line = nil end finish return end old_line = @line.dup @first_char = false completion_occurs = false if @config.editing_mode_is?(:emacs, :vi_insert) and key.char == "\C-i".ord unless @config.disable_completion result = call_completion_proc if result.is_a?(Array) completion_occurs = true process_insert if @config.autocompletion move_completed_list(result, :down) else complete(result) end end end elsif @config.editing_mode_is?(:emacs, :vi_insert) and key.char == :completion_journey_up if not @config.disable_completion and @config.autocompletion result = call_completion_proc if result.is_a?(Array) completion_occurs = true process_insert move_completed_list(result, :up) end end elsif not @config.disable_completion and @config.editing_mode_is?(:vi_insert) and ["\C-p".ord, "\C-n".ord].include?(key.char) unless @config.disable_completion result = call_completion_proc if result.is_a?(Array) completion_occurs = true process_insert move_completed_list(result, "\C-p".ord == key.char ? :up : :down) end end elsif Symbol === key.char and respond_to?(key.char, true) process_key(key.char, key.char) else normal_char(key) end unless completion_occurs @completion_state = CompletionState::NORMAL @completion_journey_data = nil end if not @in_pasting and @just_cursor_moving.nil? if @previous_line_index and @buffer_of_lines[@previous_line_index] == @line @just_cursor_moving = true elsif @previous_line_index.nil? and @buffer_of_lines[@line_index] == @line and old_line == @line @just_cursor_moving = true else @just_cursor_moving = false end else @just_cursor_moving = false end if @is_multiline and @auto_indent_proc and not simplified_rendering? and @line process_auto_indent end end
insert_text(text) 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 1767 def insert_text(text) width = calculate_width(text) if @cursor == @cursor_max @line += text else @line = byteinsert(@line, @byte_pointer, text) end @byte_pointer += text.bytesize @cursor += width @cursor_max += width end
io_gate() 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 63 def io_gate Reline::IOGate end
just_move_cursor() 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 932 def just_move_cursor prompt, prompt_width, prompt_list = check_multiline_prompt(@buffer_of_lines) move_cursor_up(@started_from) new_first_line_started_from = if @line_index.zero? 0 else calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt) end first_line_diff = new_first_line_started_from - @first_line_started_from @cursor, @cursor_max, _, @byte_pointer = calculate_nearest_cursor(@buffer_of_lines[@line_index], @cursor, @started_from, @byte_pointer, false) new_started_from = calculate_height_by_width(prompt_width + @cursor) - 1 calculate_scroll_partial_screen(@highest_in_all, new_first_line_started_from + new_started_from) @previous_line_index = nil @line = @buffer_of_lines[@line_index] if @rerender_all rerender_all_lines @rerender_all = false true else @first_line_started_from = new_first_line_started_from @started_from = new_started_from move_cursor_down(first_line_diff + @started_from) Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) false end end
multiline_off() 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 318 def multiline_off @is_multiline = false end
multiline_on() 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 314 def multiline_on @is_multiline = true end
rerender() 按一下以切換來源
# File lib/reline/line_editor.rb, line 426 def rerender return if @line.nil? if @menu_info scroll_down(@highest_in_all - @first_line_started_from) @rerender_all = true end if @menu_info show_menu @menu_info = nil end prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines) cursor_column = (prompt_width + @cursor) % @screen_size.last if @cleared clear_screen_buffer(prompt, prompt_list, prompt_width) @cleared = false return end if @is_multiline and finished? and @scroll_partial_screen # Re-output all code higher than the screen when finished. Reline::IOGate.move_cursor_up(@first_line_started_from + @started_from - @scroll_partial_screen) Reline::IOGate.move_cursor_column(0) @scroll_partial_screen = nil new_lines = whole_lines prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines) modify_lines(new_lines).each_with_index do |line, index| @output.write "#{prompt_list ? prompt_list[index] : prompt}#{line}\r\n" Reline::IOGate.erase_after_cursor end @output.flush clear_dialog(cursor_column) return end new_highest_in_this = calculate_height_by_width(prompt_width + calculate_width(@line.nil? ? '' : @line)) rendered = false if @add_newline_to_end_of_buffer clear_dialog_with_trap_key(cursor_column) rerender_added_newline(prompt, prompt_width, prompt_list) @add_newline_to_end_of_buffer = false else if @just_cursor_moving and not @rerender_all clear_dialog_with_trap_key(cursor_column) rendered = just_move_cursor @just_cursor_moving = false return elsif @previous_line_index or new_highest_in_this != @highest_in_this clear_dialog_with_trap_key(cursor_column) rerender_changed_current_line @previous_line_index = nil rendered = true elsif @rerender_all rerender_all_lines @rerender_all = false rendered = true else end end if @is_multiline if finished? # Always rerender on finish because output_modifier_proc may return a different output. new_lines = whole_lines line = modify_lines(new_lines)[@line_index] clear_dialog(cursor_column) prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines) render_partial(prompt, prompt_width, line, @first_line_started_from) move_cursor_down(@highest_in_all - (@first_line_started_from + @highest_in_this - 1) - 1) scroll_down(1) Reline::IOGate.move_cursor_column(0) Reline::IOGate.erase_after_cursor else if not rendered and not @in_pasting line = modify_lines(whole_lines)[@line_index] prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines) render_partial(prompt, prompt_width, line, @first_line_started_from) end render_dialog(cursor_column) end @buffer_of_lines[@line_index] = @line @rest_height = 0 if @scroll_partial_screen else line = modify_lines(whole_lines)[@line_index] render_partial(prompt, prompt_width, line, 0) if finished? scroll_down(1) Reline::IOGate.move_cursor_column(0) Reline::IOGate.erase_after_cursor end end end
rerender_all() 按一下以切換來源
# File lib/reline/line_editor.rb, line 420 def rerender_all @rerender_all = true process_insert(force: true) rerender end
reset(prompt = '', encoding:) 按一下以切換來源
# File lib/reline/line_editor.rb, line 154 def reset(prompt = '', encoding:) @rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y @screen_size = Reline::IOGate.get_screen_size @screen_height = @screen_size.first reset_variables(prompt, encoding: encoding) Reline::IOGate.set_winch_handler do @resized = true end if ENV.key?('RELINE_ALT_SCROLLBAR') @full_block = '::' @upper_half_block = "''" @lower_half_block = '..' @block_elem_width = 2 elsif Reline::IOGate.win? @full_block = '█' @upper_half_block = '▀' @lower_half_block = '▄' @block_elem_width = 1 elsif @encoding == Encoding::UTF_8 @full_block = '█' @upper_half_block = '▀' @lower_half_block = '▄' @block_elem_width = Reline::Unicode.calculate_width('█') else @full_block = '::' @upper_half_block = "''" @lower_half_block = '..' @block_elem_width = 2 end end
reset_line() 按一下以切換來源
# File lib/reline/line_editor.rb, line 296 def reset_line @cursor = 0 @cursor_max = 0 @byte_pointer = 0 @buffer_of_lines = [String.new(encoding: @encoding)] @line_index = 0 @previous_line_index = nil @line = @buffer_of_lines[0] @first_line_started_from = 0 @move_up = 0 @started_from = 0 @highest_in_this = 1 @highest_in_all = 1 @line_backup_in_history = nil @multibyte_buffer = String.new(encoding: 'ASCII-8BIT') @check_new_auto_indent = false end
reset_variables(prompt = '', encoding:) 按一下以切換來源
# File lib/reline/line_editor.rb, line 256 def reset_variables(prompt = '', encoding:) @prompt = prompt.gsub("\n", "\\n") @mark_pointer = nil @encoding = encoding @is_multiline = false @finished = false @cleared = false @rerender_all = false @history_pointer = nil @kill_ring ||= Reline::KillRing.new @vi_clipboard = '' @vi_arg = nil @waiting_proc = nil @waiting_operator_proc = nil @waiting_operator_vi_arg = nil @completion_journey_data = nil @completion_state = CompletionState::NORMAL @perfect_matched = nil @menu_info = nil @first_prompt = true @searching_prompt = nil @first_char = true @add_newline_to_end_of_buffer = false @just_cursor_moving = nil @cached_prompt_list = nil @prompt_cache_time = nil @eof = false @continuous_insertion_buffer = String.new(encoding: @encoding) @scroll_partial_screen = nil @prev_mode_string = nil @drop_terminate_spaces = false @in_pasting = false @auto_indent_proc = nil @dialogs = [] @previous_rendered_dialog_y = 0 @last_key = nil @resized = false reset_line end
resize() 按一下以切換來源
# File lib/reline/line_editor.rb, line 185 def resize return unless @resized @resized = false @rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y old_screen_size = @screen_size @screen_size = Reline::IOGate.get_screen_size @screen_height = @screen_size.first if old_screen_size.last < @screen_size.last # columns increase @rerender_all = true rerender else back = 0 new_buffer = whole_lines prompt, prompt_width, prompt_list = check_multiline_prompt(new_buffer) new_buffer.each_with_index do |line, index| prompt_width = calculate_width(prompt_list[index], true) if @prompt_proc width = prompt_width + calculate_width(line) height = calculate_height_by_width(width) back += height end @highest_in_all = back @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max) @first_line_started_from = if @line_index.zero? 0 else calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt) end if @prompt_proc prompt = prompt_list[@line_index] prompt_width = calculate_width(prompt, true) end calculate_nearest_cursor @started_from = calculate_height_by_width(prompt_width + @cursor) - 1 Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max) @rerender_all = true end end
retrieve_completion_block(set_completion_quote_character = false) 按一下以切換來源
# File lib/reline/line_editor.rb, line 1679 def retrieve_completion_block(set_completion_quote_character = false) if Reline.completer_word_break_characters.empty? word_break_regexp = nil else word_break_regexp = /\A[#{Regexp.escape(Reline.completer_word_break_characters)}]/ end if Reline.completer_quote_characters.empty? quote_characters_regexp = nil else quote_characters_regexp = /\A[#{Regexp.escape(Reline.completer_quote_characters)}]/ end before = @line.byteslice(0, @byte_pointer) rest = nil break_pointer = nil quote = nil closing_quote = nil escaped_quote = nil i = 0 while i < @byte_pointer do slice = @line.byteslice(i, @byte_pointer - i) unless slice.valid_encoding? i += 1 next end if quote and slice.start_with?(closing_quote) quote = nil i += 1 rest = nil elsif quote and slice.start_with?(escaped_quote) # skip i += 2 elsif quote_characters_regexp and slice =~ quote_characters_regexp # find new " rest = $' quote = $& closing_quote = /(?!\\)#{Regexp.escape(quote)}/ escaped_quote = /\\#{Regexp.escape(quote)}/ i += 1 break_pointer = i - 1 elsif word_break_regexp and not quote and slice =~ word_break_regexp rest = $' i += 1 before = @line.byteslice(i, @byte_pointer - i) break_pointer = i else i += 1 end end postposing = @line.byteslice(@byte_pointer, @line.bytesize - @byte_pointer) if rest preposing = @line.byteslice(0, break_pointer) target = rest if set_completion_quote_character and quote Reline.core.instance_variable_set(:@completion_quote_character, quote) if postposing !~ /(?!\\)#{Regexp.escape(quote)}/ # closing quote insert_text(quote) end end else preposing = '' if break_pointer preposing = @line.byteslice(0, break_pointer) else preposing = '' end target = before end if @is_multiline lines = whole_lines if @line_index > 0 preposing = lines[0..(@line_index - 1)].join("\n") + "\n" + preposing end if (lines.size - 1) > @line_index postposing = postposing + "\n" + lines[(@line_index + 1)..-1].join("\n") end end [preposing.encode(@encoding), target.encode(@encoding), postposing.encode(@encoding)] end
set_pasting_state(in_pasting) 按一下以切換來源
# File lib/reline/line_editor.rb, line 67 def set_pasting_state(in_pasting) @in_pasting = in_pasting end
set_signal_handlers() 按一下以切換來源
# File lib/reline/line_editor.rb, line 225 def set_signal_handlers @old_trap = Signal.trap('INT') { clear_dialog(0) if @scroll_partial_screen move_cursor_down(@screen_height - (@line_index - @scroll_partial_screen) - 1) else move_cursor_down(@highest_in_all - @line_index - 1) end Reline::IOGate.move_cursor_column(0) scroll_down(1) case @old_trap when 'DEFAULT', 'SYSTEM_DEFAULT' raise Interrupt when 'IGNORE' # Do nothing when 'EXIT' exit else @old_trap.call if @old_trap.respond_to?(:call) end } end
simplified_rendering?() 按一下以切換來源
# File lib/reline/line_editor.rb, line 71 def simplified_rendering? if finished? false elsif @just_cursor_moving and not @rerender_all true else not @rerender_all and not finished? and @in_pasting end end
whole_buffer() 按一下以切換來源
# File lib/reline/line_editor.rb, line 1853 def whole_buffer if @buffer_of_lines.size == 1 and @line.nil? nil else whole_lines.join("\n") end end
whole_lines() 按一下以切換來源
# File lib/reline/line_editor.rb, line 1846 def whole_lines index = @previous_line_index || @line_index temp_lines = @buffer_of_lines.dup temp_lines[index] = @line temp_lines end
wrap_method_call(method_symbol, method_obj, key, with_operator = false) 按一下以切換來源
# File lib/reline/line_editor.rb, line 1418 def wrap_method_call(method_symbol, method_obj, key, with_operator = false) if @config.editing_mode_is?(:emacs, :vi_insert) and @waiting_proc.nil? and @waiting_operator_proc.nil? not_insertion = method_symbol != :ed_insert process_insert(force: not_insertion) end if @vi_arg and argumentable?(method_obj) if with_operator and inclusive?(method_obj) method_obj.(key, arg: @vi_arg, inclusive: true) else method_obj.(key, arg: @vi_arg) end else if with_operator and inclusive?(method_obj) method_obj.(key, inclusive: true) else method_obj.(key) end end end
私人實例方法
argumentable?(method_obj) 按一下以切換來源
# File lib/reline/line_editor.rb, line 1408 def argumentable?(method_obj) method_obj and method_obj.parameters.any? { |param| param[0] == :key and param[1] == :arg } end
byteinsert(str, byte_pointer, other) 按一下以切換來源
# File lib/reline/line_editor.rb, line 1877 def byteinsert(str, byte_pointer, other) new_str = str.byteslice(0, byte_pointer) new_str << other new_str << str.byteslice(byte_pointer, str.bytesize) new_str end
byteslice!(str, byte_pointer, size) 按一下以切換來源
# File lib/reline/line_editor.rb, line 1871 def byteslice!(str, byte_pointer, size) new_str = str.byteslice(0, byte_pointer) new_str << str.byteslice(byte_pointer + size, str.bytesize) [new_str, str.byteslice(byte_pointer, size)] end
calculate_height_by_lines(lines, prompt) 按一下以切換來源
# File lib/reline/line_editor.rb, line 322 def calculate_height_by_lines(lines, prompt) result = 0 prompt_list = prompt.is_a?(Array) ? prompt : nil lines.each_with_index { |line, i| prompt = prompt_list[i] if prompt_list and prompt_list[i] result += calculate_height_by_width(calculate_width(prompt, true) + calculate_width(line)) } result end
calculate_height_by_width(width) 按一下以切換來源
# File lib/reline/line_editor.rb, line 340 def calculate_height_by_width(width) width.div(@screen_size.last) + 1 end
calculate_nearest_cursor(line_to_calc = @line, cursor = @cursor, started_from = @started_from, byte_pointer = @byte_pointer, update = true) 按一下以切換來源
# File lib/reline/line_editor.rb, line 378 def calculate_nearest_cursor(line_to_calc = @line, cursor = @cursor, started_from = @started_from, byte_pointer = @byte_pointer, update = true) new_cursor_max = calculate_width(line_to_calc) new_cursor = 0 new_byte_pointer = 0 height = 1 max_width = @screen_size.last if @config.editing_mode_is?(:vi_command) last_byte_size = Reline::Unicode.get_prev_mbchar_size(line_to_calc, line_to_calc.bytesize) if last_byte_size > 0 last_mbchar = line_to_calc.byteslice(line_to_calc.bytesize - last_byte_size, last_byte_size) last_width = Reline::Unicode.get_mbchar_width(last_mbchar) end_of_line_cursor = new_cursor_max - last_width else end_of_line_cursor = new_cursor_max end else end_of_line_cursor = new_cursor_max end line_to_calc.grapheme_clusters.each do |gc| mbchar = gc.encode(Encoding::UTF_8) mbchar_width = Reline::Unicode.get_mbchar_width(mbchar) now = new_cursor + mbchar_width if now > end_of_line_cursor or now > cursor break end new_cursor += mbchar_width if new_cursor > max_width * height height += 1 end new_byte_pointer += gc.bytesize end new_started_from = height - 1 if update @cursor = new_cursor @cursor_max = new_cursor_max @started_from = new_started_from @byte_pointer = new_byte_pointer else [new_cursor, new_cursor_max, new_started_from, new_byte_pointer] end end
calculate_scroll_partial_screen(highest_in_all, cursor_y) 按一下以切換來源
# File lib/reline/line_editor.rb, line 875 def calculate_scroll_partial_screen(highest_in_all, cursor_y) if @screen_height < highest_in_all old_scroll_partial_screen = @scroll_partial_screen if cursor_y == 0 @scroll_partial_screen = 0 elsif cursor_y == (highest_in_all - 1) @scroll_partial_screen = highest_in_all - @screen_height else if @scroll_partial_screen if cursor_y <= @scroll_partial_screen @scroll_partial_screen = cursor_y elsif (@scroll_partial_screen + @screen_height - 1) < cursor_y @scroll_partial_screen = cursor_y - (@screen_height - 1) end else if cursor_y > (@screen_height - 1) @scroll_partial_screen = cursor_y - (@screen_height - 1) else @scroll_partial_screen = 0 end end end if @scroll_partial_screen != old_scroll_partial_screen @rerender_all = true end else if @scroll_partial_screen @rerender_all = true end @scroll_partial_screen = nil end end
calculate_width(str, allow_escape_code = false) 按一下以切換來源
# File lib/reline/line_editor.rb, line 1884 def calculate_width(str, allow_escape_code = false) Reline::Unicode.calculate_width(str, allow_escape_code) end
check_mode_string() 按一下以切換來源
# File lib/reline/line_editor.rb, line 81 def check_mode_string mode_string = nil if @config.show_mode_in_prompt if @config.editing_mode_is?(:vi_command) mode_string = @config.vi_cmd_mode_string elsif @config.editing_mode_is?(:vi_insert) mode_string = @config.vi_ins_mode_string elsif @config.editing_mode_is?(:emacs) mode_string = @config.emacs_mode_string else mode_string = '?' end end if mode_string != @prev_mode_string @rerender_all = true end @prev_mode_string = mode_string mode_string end
check_multiline_prompt(buffer, force_recalc: false) 按一下以切換來源
# File lib/reline/line_editor.rb, line 101 def check_multiline_prompt(buffer, force_recalc: false) if @vi_arg prompt = "(arg: #{@vi_arg}) " @rerender_all = true elsif @searching_prompt prompt = @searching_prompt @rerender_all = true else prompt = @prompt end if simplified_rendering? && !force_recalc mode_string = check_mode_string prompt = mode_string + prompt if mode_string return [prompt, calculate_width(prompt, true), [prompt] * buffer.size] end if @prompt_proc use_cached_prompt_list = false if @cached_prompt_list if @just_cursor_moving use_cached_prompt_list = true elsif Time.now.to_f < (@prompt_cache_time + PROMPT_LIST_CACHE_TIMEOUT) and buffer.size == @cached_prompt_list.size use_cached_prompt_list = true end end use_cached_prompt_list = false if @rerender_all if use_cached_prompt_list prompt_list = @cached_prompt_list else prompt_list = @cached_prompt_list = @prompt_proc.(buffer).map { |pr| pr.gsub("\n", "\\n") } @prompt_cache_time = Time.now.to_f end prompt_list.map!{ prompt } if @vi_arg or @searching_prompt prompt_list = [prompt] if prompt_list.empty? mode_string = check_mode_string prompt_list = prompt_list.map{ |pr| mode_string + pr } if mode_string prompt = prompt_list[@line_index] prompt = prompt_list[0] if prompt.nil? prompt = prompt_list.last if prompt.nil? if buffer.size > prompt_list.size (buffer.size - prompt_list.size).times do prompt_list << prompt_list.last end end prompt_width = calculate_width(prompt, true) [prompt, prompt_width, prompt_list] else mode_string = check_mode_string prompt = mode_string + prompt if mode_string prompt_width = calculate_width(prompt, true) [prompt, prompt_width, nil] end end
clear_dialog(cursor_column) 按一下以切換來源
# File lib/reline/line_editor.rb, line 859 def clear_dialog(cursor_column) changes = @dialogs.map do |dialog| old_dialog = dialog.dup dialog.contents = nil [old_dialog, dialog] end render_dialog_changes(changes, cursor_column) end
clear_dialog_with_trap_key(cursor_column) 按一下以切換來源
# File lib/reline/line_editor.rb, line 868 def clear_dialog_with_trap_key(cursor_column) clear_dialog(cursor_column) @dialogs.each do |dialog| dialog.trap_key = nil end end
clear_screen_buffer(prompt, prompt_list, prompt_width) 按一下以切換來源
# File lib/reline/line_editor.rb, line 1205 def clear_screen_buffer(prompt, prompt_list, prompt_width) Reline::IOGate.clear_screen back = 0 modify_lines(whole_lines).each_with_index do |line, index| if @prompt_proc pr = prompt_list[index] height = render_partial(pr, calculate_width(pr), line, back, with_control: false) else height = render_partial(prompt, prompt_width, line, back, with_control: false) end if index < (@buffer_of_lines.size - 1) move_cursor_down(1) back += height end end move_cursor_up(back) move_cursor_down(@first_line_started_from + @started_from) @rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) end
complete(list, just_show_list = false) 按一下以切換來源
# File lib/reline/line_editor.rb, line 1280 def complete(list, just_show_list = false) case @completion_state when CompletionState::NORMAL, CompletionState::JOURNEY @completion_state = CompletionState::COMPLETION when CompletionState::PERFECT_MATCH @dig_perfect_match_proc&.(@perfect_matched) end if just_show_list is_menu = true elsif @completion_state == CompletionState::MENU is_menu = true elsif @completion_state == CompletionState::MENU_WITH_PERFECT_MATCH is_menu = true else is_menu = false end result = complete_internal_proc(list, is_menu) if @completion_state == CompletionState::MENU_WITH_PERFECT_MATCH @completion_state = CompletionState::PERFECT_MATCH end return if result.nil? target, preposing, completed, postposing = result return if completed.nil? if target <= completed and (@completion_state == CompletionState::COMPLETION) if list.include?(completed) if list.one? @completion_state = CompletionState::PERFECT_MATCH else @completion_state = CompletionState::MENU_WITH_PERFECT_MATCH end @perfect_matched = completed else @completion_state = CompletionState::MENU end if not just_show_list and target < completed @line = (preposing + completed + completion_append_character.to_s + postposing).split("\n")[@line_index] || String.new(encoding: @encoding) line_to_pointer = (preposing + completed + completion_append_character.to_s).split("\n").last || String.new(encoding: @encoding) @cursor_max = calculate_width(@line) @cursor = calculate_width(line_to_pointer) @byte_pointer = line_to_pointer.bytesize end end end
complete_internal_proc(list, is_menu) 按一下以切換來源
# File lib/reline/line_editor.rb, line 1234 def complete_internal_proc(list, is_menu) preposing, target, postposing = retrieve_completion_block list = list.select { |i| if i and not Encoding.compatible?(target.encoding, i.encoding) raise Encoding::CompatibilityError, "#{target.encoding.name} is not compatible with #{i.encoding.name}" end if @config.completion_ignore_case i&.downcase&.start_with?(target.downcase) else i&.start_with?(target) end }.uniq if is_menu menu(target, list) return nil end completed = list.inject { |memo, item| begin memo_mbchars = memo.unicode_normalize.grapheme_clusters item_mbchars = item.unicode_normalize.grapheme_clusters rescue Encoding::CompatibilityError memo_mbchars = memo.grapheme_clusters item_mbchars = item.grapheme_clusters end size = [memo_mbchars.size, item_mbchars.size].min result = '' size.times do |i| if @config.completion_ignore_case if memo_mbchars[i].casecmp?(item_mbchars[i]) result << memo_mbchars[i] else break end else if memo_mbchars[i] == item_mbchars[i] result << memo_mbchars[i] else break end end end result } [target, preposing, completed, postposing] end
copy_for_vi(text) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2801 def copy_for_vi(text) if @config.editing_mode_is?(:vi_insert) or @config.editing_mode_is?(:vi_command) @vi_clipboard = text end end
dialog_range(dialog, dialog_y) 按一下以切換來源
# File lib/reline/line_editor.rb, line 671 def dialog_range(dialog, dialog_y) x_range = dialog.column...dialog.column + dialog.width y_range = dialog_y + dialog.vertical_offset...dialog_y + dialog.vertical_offset + dialog.contents.size [x_range, y_range] end
ed_argument_digit(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 3100 def ed_argument_digit(key) if @vi_arg.nil? if key.chr.to_i.zero? if key.anybits?(0b10000000) unescaped_key = key ^ 0b10000000 unless unescaped_key.chr.to_i.zero? @vi_arg = unescaped_key.chr.to_i end end else @vi_arg = key.chr.to_i end else @vi_arg = @vi_arg * 10 + key.chr.to_i end end
ed_clear_screen(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2665 def ed_clear_screen(key) @cleared = true end
別名:clear_screen
ed_delete_next_char(key, arg: 1) 按一下以切換來源
# File lib/reline/line_editor.rb, line 3012 def ed_delete_next_char(key, arg: 1) byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer) unless @line.empty? || byte_size == 0 @line, mbchar = byteslice!(@line, @byte_pointer, byte_size) copy_for_vi(mbchar) width = Reline::Unicode.get_mbchar_width(mbchar) @cursor_max -= width if @cursor > 0 and @cursor >= @cursor_max byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer) mbchar = @line.byteslice(@byte_pointer - byte_size, byte_size) width = Reline::Unicode.get_mbchar_width(mbchar) @byte_pointer -= byte_size @cursor -= width end end arg -= 1 ed_delete_next_char(key, arg: arg) if arg > 0 end
ed_delete_prev_char(key, arg: 1) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2930 def ed_delete_prev_char(key, arg: 1) deleted = '' arg.times do if @cursor > 0 byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer) @byte_pointer -= byte_size @line, mbchar = byteslice!(@line, @byte_pointer, byte_size) deleted.prepend(mbchar) width = Reline::Unicode.get_mbchar_width(mbchar) @cursor -= width @cursor_max -= width end end copy_for_vi(deleted) end
ed_delete_prev_word(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2698 def ed_delete_prev_word(key) if @byte_pointer > 0 byte_size, width = Reline::Unicode.em_backward_word(@line, @byte_pointer) @line, word = byteslice!(@line, @byte_pointer - byte_size, byte_size) @kill_ring.append(word, true) @byte_pointer -= byte_size @cursor -= width @cursor_max -= width end end
ed_insert(key) 按一下以切換來源
- Editline
-
ed-insert
(vi 輸入:幾乎所有;emacs:可列印字元) 在插入模式中,在游標位置的左側插入輸入字元。在取代模式中,覆寫游標處的字元,並將游標向右移動一個字元位置。接受一個引數來重複此動作。如果輸入字元為 NUL 字元 (Ctrl-@
),則會發生錯誤。無法擴充編輯緩衝區也會導致錯誤。 - Editline
-
ed-digit
(emacs:0 到 9) 如果在引數輸入模式中,將輸入數字附加到正在讀取的引數。否則,呼叫ed-insert
。如果輸入字元不是數字,或現有引數已大於一百萬,則會發生錯誤。 - GNU
Readline
-
self-insert
(a, b, A, 1, !, …) 插入您自己。
# File lib/reline/line_editor.rb, line 1941 def ed_insert(key) str = nil width = nil bytesize = nil if key.instance_of?(String) begin key.encode(Encoding::UTF_8) rescue Encoding::UndefinedConversionError return end str = key bytesize = key.bytesize else begin key.chr.encode(Encoding::UTF_8) rescue Encoding::UndefinedConversionError return end str = key.chr bytesize = 1 end if @in_pasting @continuous_insertion_buffer << str return elsif not @continuous_insertion_buffer.empty? process_insert end width = Reline::Unicode.get_mbchar_width(str) if @cursor == @cursor_max @line += str else @line = byteinsert(@line, @byte_pointer, str) end last_byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer) @byte_pointer += bytesize last_mbchar = @line.byteslice((@byte_pointer - bytesize - last_byte_size), last_byte_size) combined_char = last_mbchar + str if last_byte_size != 0 and combined_char.grapheme_clusters.size == 1 # combined char last_mbchar_width = Reline::Unicode.get_mbchar_width(last_mbchar) combined_char_width = Reline::Unicode.get_mbchar_width(combined_char) if combined_char_width > last_mbchar_width width = combined_char_width - last_mbchar_width else width = 0 end end @cursor += width @cursor_max += width end
別名:ed_digit, self_insert
ed_kill_line(key) 按一下以切換來源
- Editline
-
ed-kill-line
(vi 指令:D
,Ctrl-K
;emacs:Ctrl-K
,Ctrl-U
) + 從游標刪除到該行的結尾。 - GNU
Readline
-
kill-line
(C-k
) 從點刪除到該行的結尾。使用負數數字引數,從游標向後刪除到目前行的開頭。
# File lib/reline/line_editor.rb, line 2548 def ed_kill_line(key) if @line.bytesize > @byte_pointer @line, deleted = byteslice!(@line, @byte_pointer, @line.bytesize - @byte_pointer) @byte_pointer = @line.bytesize @cursor = @cursor_max = calculate_width(@line) @kill_ring.append(deleted) elsif @is_multiline and @byte_pointer == @line.bytesize and @buffer_of_lines.size > @line_index + 1 @cursor = calculate_width(@line) @byte_pointer = @line.bytesize @line += @buffer_of_lines.delete_at(@line_index + 1) @cursor_max = calculate_width(@line) @buffer_of_lines[@line_index] = @line @rerender_all = true @rest_height += 1 end end
別名:kill_line
ed_move_to_beg(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2054 def ed_move_to_beg(key) @byte_pointer = @cursor = 0 end
ed_move_to_end(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2059 def ed_move_to_end(key) @byte_pointer = 0 @cursor = 0 byte_size = 0 while @byte_pointer < @line.bytesize byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer) if byte_size > 0 mbchar = @line.byteslice(@byte_pointer, byte_size) @cursor += Reline::Unicode.get_mbchar_width(mbchar) end @byte_pointer += byte_size end end
別名為:end_of_line
ed_newline(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2487 def ed_newline(key) process_insert(force: true) if @is_multiline if @config.editing_mode_is?(:vi_command) if @line_index < (@buffer_of_lines.size - 1) ed_next_history(key) # means cursor down else # should check confirm_multiline_termination to finish? finish end else if @line_index == (@buffer_of_lines.size - 1) if confirm_multiline_termination finish else key_newline(key) end else # should check confirm_multiline_termination to finish? @previous_line_index = @line_index @line_index = @buffer_of_lines.size - 1 finish end end else if @history_pointer Reline::HISTORY[@history_pointer] = @line @history_pointer = nil end finish end end
ed_next_char(key, arg: 1) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2010 def ed_next_char(key, arg: 1) byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer) if (@byte_pointer < @line.bytesize) mbchar = @line.byteslice(@byte_pointer, byte_size) width = Reline::Unicode.get_mbchar_width(mbchar) @cursor += width if width @byte_pointer += byte_size elsif @is_multiline and @config.editing_mode_is?(:emacs) and @byte_pointer == @line.bytesize and @line_index < @buffer_of_lines.size - 1 next_line = @buffer_of_lines[@line_index + 1] @cursor = 0 @byte_pointer = 0 @cursor_max = calculate_width(next_line) @previous_line_index = @line_index @line_index += 1 end arg -= 1 ed_next_char(key, arg: arg) if arg > 0 end
別名為:forward_char
ed_next_history(key, arg: 1) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2439 def ed_next_history(key, arg: 1) if @is_multiline and @line_index < (@buffer_of_lines.size - 1) @previous_line_index = @line_index @line_index += 1 return end if @history_pointer.nil? return elsif @history_pointer == (Reline::HISTORY.size - 1) if @is_multiline @history_pointer = nil @buffer_of_lines = @line_backup_in_history.split("\n") @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? @line_index = 0 @line = @buffer_of_lines.first @rerender_all = true else @history_pointer = nil @line = @line_backup_in_history end else if @is_multiline Reline::HISTORY[@history_pointer] = whole_buffer @history_pointer += 1 @buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n") @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? @line_index = 0 @line = @buffer_of_lines.first @rerender_all = true else Reline::HISTORY[@history_pointer] = @line @history_pointer += 1 @line = Reline::HISTORY[@history_pointer] end end @line = '' unless @line if @config.editing_mode_is?(:emacs, :vi_insert) @cursor_max = @cursor = calculate_width(@line) @byte_pointer = @line.bytesize elsif @config.editing_mode_is?(:vi_command) @byte_pointer = @cursor = 0 @cursor_max = calculate_width(@line) end arg -= 1 ed_next_history(key, arg: arg) if arg > 0 end
別名為:next_history
ed_prev_char(key, arg: 1) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2030 def ed_prev_char(key, arg: 1) if @cursor > 0 byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer) @byte_pointer -= byte_size mbchar = @line.byteslice(@byte_pointer, byte_size) width = Reline::Unicode.get_mbchar_width(mbchar) @cursor -= width elsif @is_multiline and @config.editing_mode_is?(:emacs) and @byte_pointer == 0 and @line_index > 0 prev_line = @buffer_of_lines[@line_index - 1] @cursor = calculate_width(prev_line) @byte_pointer = prev_line.bytesize @cursor_max = calculate_width(prev_line) @previous_line_index = @line_index @line_index -= 1 end arg -= 1 ed_prev_char(key, arg: arg) if arg > 0 end
別名為:backward_char
ed_prev_history(key, arg: 1) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2388 def ed_prev_history(key, arg: 1) if @is_multiline and @line_index > 0 @previous_line_index = @line_index @line_index -= 1 return end if Reline::HISTORY.empty? return end if @history_pointer.nil? @history_pointer = Reline::HISTORY.size - 1 if @is_multiline @line_backup_in_history = whole_buffer @buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n") @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? @line_index = @buffer_of_lines.size - 1 @line = @buffer_of_lines.last @rerender_all = true else @line_backup_in_history = @line @line = Reline::HISTORY[@history_pointer] end elsif @history_pointer.zero? return else if @is_multiline Reline::HISTORY[@history_pointer] = whole_buffer @history_pointer -= 1 @buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n") @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? @line_index = @buffer_of_lines.size - 1 @line = @buffer_of_lines.last @rerender_all = true else Reline::HISTORY[@history_pointer] = @line @history_pointer -= 1 @line = Reline::HISTORY[@history_pointer] end end if @config.editing_mode_is?(:emacs, :vi_insert) @cursor_max = @cursor = calculate_width(@line) @byte_pointer = @line.bytesize elsif @config.editing_mode_is?(:vi_command) @byte_pointer = @cursor = 0 @cursor_max = calculate_width(@line) end arg -= 1 ed_prev_history(key, arg: arg) if arg > 0 end
別名為:previous_history
ed_prev_word(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2679 def ed_prev_word(key) if @byte_pointer > 0 byte_size, width = Reline::Unicode.em_backward_word(@line, @byte_pointer) @byte_pointer -= byte_size @cursor -= width end end
別名為:backward_word
ed_quoted_insert(str, arg: 1) 按一下以切換來源
# File lib/reline/line_editor.rb, line 1994 def ed_quoted_insert(str, arg: 1) @waiting_proc = proc { |key| arg.times do if key == "\C-j".ord or key == "\C-m".ord key_newline(key) elsif key == 0 # Ignore NUL. else ed_insert(key) end end @waiting_proc = nil } end
別名為:quoted_insert
ed_search_next_history(key, arg: 1) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2336 def ed_search_next_history(key, arg: 1) substr = @line.slice(0, @byte_pointer) if @history_pointer.nil? return elsif @history_pointer == (Reline::HISTORY.size - 1) and not substr.empty? return end history = Reline::HISTORY.slice((@history_pointer + 1)..-1) h_pointer = nil line_no = nil if @is_multiline h_pointer = history.index { |h| h.split("\n").each_with_index { |l, i| if l.start_with?(substr) line_no = i break end } not line_no.nil? } else h_pointer = history.index { |l| l.start_with?(substr) } end h_pointer += @history_pointer + 1 if h_pointer and @history_pointer return if h_pointer.nil? and not substr.empty? @history_pointer = h_pointer if @is_multiline if @history_pointer.nil? and substr.empty? @buffer_of_lines = [] @line_index = 0 else @buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n") @line_index = line_no end @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? @line = @buffer_of_lines[@line_index] @rerender_all = true else if @history_pointer.nil? and substr.empty? @line = '' else @line = Reline::HISTORY[@history_pointer] end end @cursor_max = calculate_width(@line) arg -= 1 ed_search_next_history(key, arg: arg) if arg > 0 end
ed_search_prev_history(key, arg: 1) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2289 def ed_search_prev_history(key, arg: 1) history = nil h_pointer = nil line_no = nil substr = @line.slice(0, @byte_pointer) if @history_pointer.nil? return if not @line.empty? and substr.empty? history = Reline::HISTORY elsif @history_pointer.zero? history = nil h_pointer = nil else history = Reline::HISTORY.slice(0, @history_pointer) end return if history.nil? if @is_multiline h_pointer = history.rindex { |h| h.split("\n").each_with_index { |l, i| if l.start_with?(substr) line_no = i break end } not line_no.nil? } else h_pointer = history.rindex { |l| l.start_with?(substr) } end return if h_pointer.nil? @history_pointer = h_pointer if @is_multiline @buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n") @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? @line_index = line_no @line = @buffer_of_lines[@line_index] @rerender_all = true else @line = Reline::HISTORY[@history_pointer] end @cursor_max = calculate_width(@line) arg -= 1 ed_search_prev_history(key, arg: arg) if arg > 0 end
ed_transpose_chars(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2710 def ed_transpose_chars(key) if @byte_pointer > 0 if @cursor_max > @cursor byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer) mbchar = @line.byteslice(@byte_pointer, byte_size) width = Reline::Unicode.get_mbchar_width(mbchar) @cursor += width @byte_pointer += byte_size end back1_byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer) if (@byte_pointer - back1_byte_size) > 0 back2_byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer - back1_byte_size) back2_pointer = @byte_pointer - back1_byte_size - back2_byte_size @line, back2_mbchar = byteslice!(@line, back2_pointer, back2_byte_size) @line = byteinsert(@line, @byte_pointer - back2_byte_size, back2_mbchar) end end end
別名為:transpose_chars
ed_transpose_words(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2730 def ed_transpose_words(key) left_word_start, middle_start, right_word_start, after_start = Reline::Unicode.ed_transpose_words(@line, @byte_pointer) before = @line.byteslice(0, left_word_start) left_word = @line.byteslice(left_word_start, middle_start - left_word_start) middle = @line.byteslice(middle_start, right_word_start - middle_start) right_word = @line.byteslice(right_word_start, after_start - right_word_start) after = @line.byteslice(after_start, @line.bytesize - after_start) return if left_word.empty? or right_word.empty? @line = before + right_word + middle + left_word + after from_head_to_left_word = before + right_word + middle + left_word @byte_pointer = from_head_to_left_word.bytesize @cursor = calculate_width(from_head_to_left_word) end
別名為:transpose_words
ed_unassigned(key) 按一下以切換來源
- Editline
-
ed-unassigned
此編輯器指令總是會導致錯誤。 - GNU
Readline
-
沒有對應的巨集。
# File lib/reline/line_editor.rb, line 1911 def ed_unassigned(key) end
em_capitol_case(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2745 def em_capitol_case(key) if @line.bytesize > @byte_pointer byte_size, _, new_str = Reline::Unicode.em_forward_word_with_capitalization(@line, @byte_pointer) before = @line.byteslice(0, @byte_pointer) after = @line.byteslice((@byte_pointer + byte_size)..-1) @line = before + new_str + after @byte_pointer += new_str.bytesize @cursor += calculate_width(new_str) end end
別名為:capitalize_word
em_delete(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2597 def em_delete(key) if @line.empty? and (not @is_multiline or @buffer_of_lines.size == 1) and key == "\C-d".ord @line = nil if @buffer_of_lines.size > 1 scroll_down(@highest_in_all - @first_line_started_from) end Reline::IOGate.move_cursor_column(0) @eof = true finish elsif @byte_pointer < @line.bytesize splitted_last = @line.byteslice(@byte_pointer, @line.bytesize) mbchar = splitted_last.grapheme_clusters.first width = Reline::Unicode.get_mbchar_width(mbchar) @cursor_max -= width @line, = byteslice!(@line, @byte_pointer, mbchar.bytesize) elsif @is_multiline and @byte_pointer == @line.bytesize and @buffer_of_lines.size > @line_index + 1 @cursor = calculate_width(@line) @byte_pointer = @line.bytesize @line += @buffer_of_lines.delete_at(@line_index + 1) @cursor_max = calculate_width(@line) @buffer_of_lines[@line_index] = @line @rerender_all = true @rest_height += 1 end end
別名:delete_char
em_delete_next_word(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2688 def em_delete_next_word(key) if @line.bytesize > @byte_pointer byte_size, width = Reline::Unicode.em_forward_word(@line, @byte_pointer) @line, word = byteslice!(@line, @byte_pointer, byte_size) @kill_ring.append(word) @cursor_max -= width end end
別名:kill_word
em_delete_or_list(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2624 def em_delete_or_list(key) if @line.empty? or @byte_pointer < @line.bytesize em_delete(key) else # show completed list result = call_completion_proc if result.is_a?(Array) complete(result, true) end end end
em_delete_prev_char(key, arg: 1) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2520 def em_delete_prev_char(key, arg: 1) if @is_multiline and @cursor == 0 and @line_index > 0 @buffer_of_lines[@line_index] = @line @cursor = calculate_width(@buffer_of_lines[@line_index - 1]) @byte_pointer = @buffer_of_lines[@line_index - 1].bytesize @buffer_of_lines[@line_index - 1] += @buffer_of_lines.delete_at(@line_index) @line_index -= 1 @line = @buffer_of_lines[@line_index] @cursor_max = calculate_width(@line) @rerender_all = true elsif @cursor > 0 byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer) @byte_pointer -= byte_size @line, mbchar = byteslice!(@line, @byte_pointer, byte_size) width = Reline::Unicode.get_mbchar_width(mbchar) @cursor -= width @cursor_max -= width end arg -= 1 em_delete_prev_char(key, arg: arg) if arg > 0 end
em_exchange_mark(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 3284 def em_exchange_mark(key) return unless @mark_pointer new_pointer = [@byte_pointer, @line_index] @previous_line_index = @line_index @byte_pointer, @line_index = @mark_pointer @cursor = calculate_width(@line.byteslice(0, @byte_pointer)) @cursor_max = calculate_width(@line) @mark_pointer = new_pointer end
em_kill_line(key) 按一下以切換來源
- Editline
-
em-kill-line
(未繫結) 刪除編輯緩衝區的全部內容,並將其儲存到剪下緩衝區。vi-kill-line-prev
- GNU
Readline
-
kill-whole-line
(未繫結) 刪除目前行上的所有字元,不論指標位置為何。
# File lib/reline/line_editor.rb, line 2586 def em_kill_line(key) if @line.size > 0 @kill_ring.append(@line.dup, true) @line.clear @byte_pointer = 0 @cursor_max = 0 @cursor = 0 end end
em_kill_region(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2789 def em_kill_region(key) if @byte_pointer > 0 byte_size, width = Reline::Unicode.em_big_backward_word(@line, @byte_pointer) @line, deleted = byteslice!(@line, @byte_pointer - byte_size, byte_size) @byte_pointer -= byte_size @cursor -= width @cursor_max -= width @kill_ring.append(deleted, true) end end
em_lower_case(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2757 def em_lower_case(key) if @line.bytesize > @byte_pointer byte_size, = Reline::Unicode.em_forward_word(@line, @byte_pointer) part = @line.byteslice(@byte_pointer, byte_size).grapheme_clusters.map { |mbchar| mbchar =~ /[A-Z]/ ? mbchar.downcase : mbchar }.join rest = @line.byteslice((@byte_pointer + byte_size)..-1) @line = @line.byteslice(0, @byte_pointer) + part @byte_pointer = @line.bytesize @cursor = calculate_width(@line) @cursor_max = @cursor + calculate_width(rest) @line += rest end end
em_meta_next(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 3295 def em_meta_next(key) end
em_next_word(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2670 def em_next_word(key) if @line.bytesize > @byte_pointer byte_size, width = Reline::Unicode.em_forward_word(@line, @byte_pointer) @byte_pointer += byte_size @cursor += width end end
別名:forward_word
em_set_mark(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 3279 def em_set_mark(key) @mark_pointer = [@byte_pointer, @line_index] end
別名:set_mark
em_upper_case(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2773 def em_upper_case(key) if @line.bytesize > @byte_pointer byte_size, = Reline::Unicode.em_forward_word(@line, @byte_pointer) part = @line.byteslice(@byte_pointer, byte_size).grapheme_clusters.map { |mbchar| mbchar =~ /[a-z]/ ? mbchar.upcase : mbchar }.join rest = @line.byteslice((@byte_pointer + byte_size)..-1) @line = @line.byteslice(0, @byte_pointer) + part @byte_pointer = @line.bytesize @cursor = calculate_width(@line) @cursor_max = @cursor + calculate_width(rest) @line += rest end end
別名:upcase_word
em_yank(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2636 def em_yank(key) yanked = @kill_ring.yank if yanked @line = byteinsert(@line, @byte_pointer, yanked) yanked_width = calculate_width(yanked) @cursor += yanked_width @cursor_max += yanked_width @byte_pointer += yanked.bytesize end end
別名:yank
em_yank_pop(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2648 def em_yank_pop(key) yanked, prev_yank = @kill_ring.yank_pop if yanked prev_yank_width = calculate_width(prev_yank) @cursor -= prev_yank_width @cursor_max -= prev_yank_width @byte_pointer -= prev_yank.bytesize @line, = byteslice!(@line, @byte_pointer, prev_yank.bytesize) @line = byteinsert(@line, @byte_pointer, yanked) yanked_width = calculate_width(yanked) @cursor += yanked_width @cursor_max += yanked_width @byte_pointer += yanked.bytesize end end
別名為: yank_pop
generate_searcher() 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 2074 def generate_searcher Fiber.new do |first_key| prev_search_key = first_key search_word = String.new(encoding: @encoding) multibyte_buf = String.new(encoding: 'ASCII-8BIT') last_hit = nil case first_key when "\C-r".ord prompt_name = 'reverse-i-search' when "\C-s".ord prompt_name = 'i-search' end loop do key = Fiber.yield(search_word) search_again = false case key when -1 # determined Reline.last_incremental_search = search_word break when "\C-h".ord, "\C-?".ord grapheme_clusters = search_word.grapheme_clusters if grapheme_clusters.size > 0 grapheme_clusters.pop search_word = grapheme_clusters.join end when "\C-r".ord, "\C-s".ord search_again = true if prev_search_key == key prev_search_key = key else multibyte_buf << key if multibyte_buf.dup.force_encoding(@encoding).valid_encoding? search_word << multibyte_buf.dup.force_encoding(@encoding) multibyte_buf.clear end end hit = nil if not search_word.empty? and @line_backup_in_history&.include?(search_word) @history_pointer = nil hit = @line_backup_in_history else if search_again if search_word.empty? and Reline.last_incremental_search search_word = Reline.last_incremental_search end if @history_pointer case prev_search_key when "\C-r".ord history_pointer_base = 0 history = Reline::HISTORY[0..(@history_pointer - 1)] when "\C-s".ord history_pointer_base = @history_pointer + 1 history = Reline::HISTORY[(@history_pointer + 1)..-1] end else history_pointer_base = 0 history = Reline::HISTORY end elsif @history_pointer case prev_search_key when "\C-r".ord history_pointer_base = 0 history = Reline::HISTORY[0..@history_pointer] when "\C-s".ord history_pointer_base = @history_pointer history = Reline::HISTORY[@history_pointer..-1] end else history_pointer_base = 0 history = Reline::HISTORY end case prev_search_key when "\C-r".ord hit_index = history.rindex { |item| item.include?(search_word) } when "\C-s".ord hit_index = history.index { |item| item.include?(search_word) } end if hit_index @history_pointer = history_pointer_base + hit_index hit = Reline::HISTORY[@history_pointer] end end case prev_search_key when "\C-r".ord prompt_name = 'reverse-i-search' when "\C-s".ord prompt_name = 'i-search' end if hit if @is_multiline @buffer_of_lines = hit.split("\n") @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? @line_index = @buffer_of_lines.size - 1 @line = @buffer_of_lines.last @byte_pointer = @line.bytesize @cursor = @cursor_max = calculate_width(@line) @rerender_all = true @searching_prompt = "(%s)`%s'" % [prompt_name, search_word] else @line = hit @searching_prompt = "(%s)`%s': %s" % [prompt_name, search_word, hit] end last_hit = hit else if @is_multiline @rerender_all = true @searching_prompt = "(failed %s)`%s'" % [prompt_name, search_word] else @searching_prompt = "(failed %s)`%s': %s" % [prompt_name, search_word, last_hit] end end end end end
inclusive?(method_obj) 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 1412 def inclusive?(method_obj) # If a motion method with the keyword argument "inclusive" follows the # operator, it must contain the character at the cursor position. method_obj and method_obj.parameters.any? { |param| param[0] == :key and param[1] == :inclusive } end
incremental_search_history(key) 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 2192 def incremental_search_history(key) unless @history_pointer if @is_multiline @line_backup_in_history = whole_buffer else @line_backup_in_history = @line end end searcher = generate_searcher searcher.resume(key) @searching_prompt = "(reverse-i-search)`': " termination_keys = ["\C-j".ord] termination_keys.concat(@config.isearch_terminators&.chars&.map(&:ord)) if @config.isearch_terminators @waiting_proc = ->(k) { case k when *termination_keys if @history_pointer buffer = Reline::HISTORY[@history_pointer] else buffer = @line_backup_in_history end if @is_multiline @buffer_of_lines = buffer.split("\n") @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? @line_index = @buffer_of_lines.size - 1 @line = @buffer_of_lines.last @rerender_all = true else @line = buffer end @searching_prompt = nil @waiting_proc = nil @cursor_max = calculate_width(@line) @cursor = @byte_pointer = 0 @rerender_all = true @cached_prompt_list = nil searcher.resume(-1) when "\C-g".ord if @is_multiline @buffer_of_lines = @line_backup_in_history.split("\n") @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? @line_index = @buffer_of_lines.size - 1 @line = @buffer_of_lines.last @rerender_all = true else @line = @line_backup_in_history end @history_pointer = nil @searching_prompt = nil @waiting_proc = nil @line_backup_in_history = nil @cursor_max = calculate_width(@line) @cursor = @byte_pointer = 0 @rerender_all = true else chr = k.is_a?(String) ? k : k.chr(Encoding::ASCII_8BIT) if chr.match?(/[[:print:]]/) or k == "\C-h".ord or k == "\C-?".ord or k == "\C-r".ord or k == "\C-s".ord searcher.resume(k) else if @history_pointer line = Reline::HISTORY[@history_pointer] else line = @line_backup_in_history end if @is_multiline @line_backup_in_history = whole_buffer @buffer_of_lines = line.split("\n") @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? @line_index = @buffer_of_lines.size - 1 @line = @buffer_of_lines.last @rerender_all = true else @line_backup_in_history = @line @line = line end @searching_prompt = nil @waiting_proc = nil @cursor_max = calculate_width(@line) @cursor = @byte_pointer = 0 @rerender_all = true @cached_prompt_list = nil searcher.resume(-1) end end } end
insert_new_line(cursor_line, next_line) 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 332 def insert_new_line(cursor_line, next_line) @line = cursor_line @buffer_of_lines.insert(@line_index + 1, String.new(next_line, encoding: @encoding)) @previous_line_index = @line_index @line_index += 1 @just_cursor_moving = false end
key_delete(key) 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 1888 def key_delete(key) if @config.editing_mode_is?(:vi_insert) ed_delete_next_char(key) elsif @config.editing_mode_is?(:emacs) em_delete(key) end end
key_newline(key) 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 1896 def key_newline(key) if @is_multiline if (@buffer_of_lines.size - 1) == @line_index and @line.bytesize == @byte_pointer @add_newline_to_end_of_buffer = true end next_line = @line.byteslice(@byte_pointer, @line.bytesize - @byte_pointer) cursor_line = @line.byteslice(0, @byte_pointer) insert_new_line(cursor_line, next_line) @cursor = 0 @check_new_auto_indent = true unless @in_pasting end end
modify_lines(before, force_recalc: false) 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 1182 def modify_lines(before, force_recalc: false) return before if !force_recalc && (before.nil? || before.empty? || simplified_rendering?) if after = @output_modifier_proc&.call("#{before.join("\n")}\n", complete: finished?) after.lines("\n").map { |l| l.chomp('') } else before end end
move_completed_list(list, direction) 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 1324 def move_completed_list(list, direction) case @completion_state when CompletionState::NORMAL, CompletionState::COMPLETION, CompletionState::MENU, CompletionState::MENU_WITH_PERFECT_MATCH @completion_state = CompletionState::JOURNEY result = retrieve_completion_block return if result.nil? preposing, target, postposing = result @completion_journey_data = CompletionJourneyData.new( preposing, postposing, [target] + list.select{ |item| item.start_with?(target) }, 0) if @completion_journey_data.list.size == 1 @completion_journey_data.pointer = 0 else case direction when :up @completion_journey_data.pointer = @completion_journey_data.list.size - 1 when :down @completion_journey_data.pointer = 1 end end @completion_state = CompletionState::JOURNEY else case direction when :up @completion_journey_data.pointer -= 1 if @completion_journey_data.pointer < 0 @completion_journey_data.pointer = @completion_journey_data.list.size - 1 end when :down @completion_journey_data.pointer += 1 if @completion_journey_data.pointer >= @completion_journey_data.list.size @completion_journey_data.pointer = 0 end end end completed = @completion_journey_data.list[@completion_journey_data.pointer] new_line = (@completion_journey_data.preposing + completed + @completion_journey_data.postposing).split("\n")[@line_index] @line = new_line.nil? ? String.new(encoding: @encoding) : new_line line_to_pointer = (@completion_journey_data.preposing + completed).split("\n").last line_to_pointer = String.new(encoding: @encoding) if line_to_pointer.nil? @cursor_max = calculate_width(@line) @cursor = calculate_width(line_to_pointer) @byte_pointer = line_to_pointer.bytesize end
move_cursor_down(val) 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 368 def move_cursor_down(val) if val > 0 Reline::IOGate.move_cursor_down(val) @rest_height -= val @rest_height = 0 if @rest_height < 0 elsif val < 0 move_cursor_up(-val) end end
move_cursor_up(val) 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 359 def move_cursor_up(val) if val > 0 Reline::IOGate.move_cursor_up(val) @rest_height += val elsif val < 0 move_cursor_down(-val) end end
normal_char(key) 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 1495 def normal_char(key) method_symbol = method_obj = nil if key.combined_char.is_a?(Symbol) process_key(key.combined_char, key.combined_char) return end @multibyte_buffer << key.combined_char if @multibyte_buffer.size > 1 if @multibyte_buffer.dup.force_encoding(@encoding).valid_encoding? process_key(@multibyte_buffer.dup.force_encoding(@encoding), nil) @multibyte_buffer.clear else # invalid return end else # single byte return if key.char >= 128 # maybe, first byte of multi byte method_symbol = @config.editing_mode.get_method(key.combined_char) if key.with_meta and method_symbol == :ed_unassigned if @config.editing_mode_is?(:vi_command, :vi_insert) # split ESC + key in vi mode method_symbol = @config.editing_mode.get_method("\e".ord) process_key("\e".ord, method_symbol) method_symbol = @config.editing_mode.get_method(key.char) process_key(key.char, method_symbol) end else process_key(key.combined_char, method_symbol) end @multibyte_buffer.clear end if @config.editing_mode_is?(:vi_command) and @cursor > 0 and @cursor == @cursor_max byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer) @byte_pointer -= byte_size mbchar = @line.byteslice(@byte_pointer, byte_size) width = Reline::Unicode.get_mbchar_width(mbchar) @cursor -= width end end
padding_space_with_escape_sequences(str, width) 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 658 def padding_space_with_escape_sequences(str, width) padding_width = width - calculate_width(str, true) # padding_width should be only positive value. But macOS and Alacritty returns negative value. padding_width = 0 if padding_width < 0 str + (' ' * padding_width) end
process_auto_indent() 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 1640 def process_auto_indent return if not @check_new_auto_indent and @previous_line_index # move cursor up or down if @check_new_auto_indent and @previous_line_index and @previous_line_index > 0 and @line_index > @previous_line_index # Fix indent of a line when a newline is inserted to the next new_lines = whole_lines new_indent = @auto_indent_proc.(new_lines[0..-3].push(''), @line_index - 1, 0, true) md = @line.match(/\A */) prev_indent = md[0].count(' ') @line = ' ' * new_indent + @line.lstrip new_indent = nil result = @auto_indent_proc.(new_lines[0..-2], @line_index - 1, (new_lines[@line_index - 1].bytesize + 1), false) if result new_indent = result end if new_indent&.>= 0 @line = ' ' * new_indent + @line.lstrip end end new_lines = whole_lines new_indent = @auto_indent_proc.(new_lines, @line_index, @byte_pointer, @check_new_auto_indent) if new_indent&.>= 0 md = new_lines[@line_index].match(/\A */) prev_indent = md[0].count(' ') if @check_new_auto_indent line = @buffer_of_lines[@line_index] = ' ' * new_indent + @buffer_of_lines[@line_index].lstrip @cursor = new_indent @cursor_max = calculate_width(line) @byte_pointer = new_indent else @line = ' ' * new_indent + @line.lstrip @cursor += new_indent - prev_indent @cursor_max = calculate_width(@line) @byte_pointer += new_indent - prev_indent end end @check_new_auto_indent = false end
process_insert(force: false) 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 1913 def process_insert(force: false) return if @continuous_insertion_buffer.empty? or (@in_pasting and not force) width = Reline::Unicode.calculate_width(@continuous_insertion_buffer) bytesize = @continuous_insertion_buffer.bytesize if @cursor == @cursor_max @line += @continuous_insertion_buffer else @line = byteinsert(@line, @byte_pointer, @continuous_insertion_buffer) end @byte_pointer += bytesize @cursor += width @cursor_max += width @continuous_insertion_buffer.clear end
process_key(key, method_symbol) 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 1438 def process_key(key, method_symbol) if method_symbol and respond_to?(method_symbol, true) method_obj = method(method_symbol) else method_obj = nil end if method_symbol and key.is_a?(Symbol) if @vi_arg and argumentable?(method_obj) run_for_operators(key, method_symbol) do |with_operator| wrap_method_call(method_symbol, method_obj, key, with_operator) end else wrap_method_call(method_symbol, method_obj, key) if method_obj end @kill_ring.process if @vi_arg @rerender_al = true @vi_arg = nil end elsif @vi_arg if key.chr =~ /[0-9]/ ed_argument_digit(key) else if argumentable?(method_obj) run_for_operators(key, method_symbol) do |with_operator| wrap_method_call(method_symbol, method_obj, key, with_operator) end elsif @waiting_proc @waiting_proc.(key) elsif method_obj wrap_method_call(method_symbol, method_obj, key) else ed_insert(key) unless @config.editing_mode_is?(:vi_command) end @kill_ring.process if @vi_arg @rerender_all = true @vi_arg = nil end end elsif @waiting_proc @waiting_proc.(key) @kill_ring.process elsif method_obj if method_symbol == :ed_argument_digit wrap_method_call(method_symbol, method_obj, key) else run_for_operators(key, method_symbol) do |with_operator| wrap_method_call(method_symbol, method_obj, key, with_operator) end end @kill_ring.process else ed_insert(key) unless @config.editing_mode_is?(:vi_command) end end
range_subtract(base_ranges, subtract_ranges) 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 665 def range_subtract(base_ranges, subtract_ranges) indices = base_ranges.flat_map(&:to_a).uniq.sort - subtract_ranges.flat_map(&:to_a) chunks = indices.chunk_while { |a, b| a + 1 == b } chunks.map { |a| a.first...a.last + 1 } end
render_dialog(cursor_column) 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 649 def render_dialog(cursor_column) changes = @dialogs.map do |dialog| old_dialog = dialog.dup update_each_dialog(dialog, cursor_column) [old_dialog, dialog] end render_dialog_changes(changes, cursor_column) end
render_dialog_changes(changes, cursor_column) 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 677 def render_dialog_changes(changes, cursor_column) # Collect x-coordinate range and content of previous and current dialogs for each line old_dialog_ranges = {} new_dialog_ranges = {} new_dialog_contents = {} changes.each do |old_dialog, new_dialog| if old_dialog.contents x_range, y_range = dialog_range(old_dialog, @previous_rendered_dialog_y) y_range.each do |y| (old_dialog_ranges[y] ||= []) << x_range end end if new_dialog.contents x_range, y_range = dialog_range(new_dialog, @first_line_started_from + @started_from) y_range.each do |y| (new_dialog_ranges[y] ||= []) << x_range (new_dialog_contents[y] ||= []) << [x_range, new_dialog.contents[y - y_range.begin]] end end end return if old_dialog_ranges.empty? && new_dialog_ranges.empty? # Calculate x-coordinate ranges to restore text that was hidden behind dialogs for each line ranges_to_restore = {} subtract_cache = {} old_dialog_ranges.each do |y, old_x_ranges| new_x_ranges = new_dialog_ranges[y] || [] ranges = subtract_cache[[old_x_ranges, new_x_ranges]] ||= range_subtract(old_x_ranges, new_x_ranges) ranges_to_restore[y] = ranges if ranges.any? end # Create visual_lines for restoring text hidden behind dialogs if ranges_to_restore.any? lines = whole_lines prompt, _prompt_width, prompt_list = check_multiline_prompt(lines, force_recalc: true) modified_lines = modify_lines(lines, force_recalc: true) visual_lines = [] modified_lines.each_with_index { |l, i| pr = prompt_list ? prompt_list[i] : prompt vl, = split_by_width(pr + l, @screen_size.last) vl.compact! visual_lines.concat(vl) } end # Clear and rerender all dialogs line by line Reline::IOGate.hide_cursor ymin, ymax = (ranges_to_restore.keys + new_dialog_ranges.keys).minmax scroll_partial_screen = @scroll_partial_screen || 0 screen_y_range = scroll_partial_screen..(scroll_partial_screen + @screen_height - 1) ymin = ymin.clamp(screen_y_range.begin, screen_y_range.end) ymax = ymax.clamp(screen_y_range.begin, screen_y_range.end) dialog_y = @first_line_started_from + @started_from cursor_y = dialog_y if @highest_in_all <= ymax scroll_down(ymax - cursor_y) move_cursor_up(ymax - cursor_y) end (ymin..ymax).each do |y| move_cursor_down(y - cursor_y) cursor_y = y new_x_ranges = new_dialog_ranges[y] restore_ranges = ranges_to_restore[y] # Restore text that was hidden behind dialogs if restore_ranges line = visual_lines[y] || '' restore_ranges.each do |range| col = range.begin width = range.end - range.begin s = padding_space_with_escape_sequences(Reline::Unicode.take_range(line, col, width), width) Reline::IOGate.move_cursor_column(col) @output.write "\e[0m#{s}\e[0m" end max_column = [calculate_width(line, true), new_x_ranges&.map(&:end)&.max || 0].max if max_column < restore_ranges.map(&:end).max Reline::IOGate.move_cursor_column(max_column) Reline::IOGate.erase_after_cursor end end # Render dialog contents new_dialog_contents[y]&.each do |x_range, content| Reline::IOGate.move_cursor_column(x_range.begin) @output.write "\e[0m#{content}\e[0m" end end move_cursor_up(cursor_y - dialog_y) Reline::IOGate.move_cursor_column(cursor_column) Reline::IOGate.show_cursor @previous_rendered_dialog_y = dialog_y end
render_partial(prompt, prompt_width, line_to_render, this_started_from, with_control: true) 按一下以切換原始碼
# File lib/reline/line_editor.rb, line 1085 def render_partial(prompt, prompt_width, line_to_render, this_started_from, with_control: true) visual_lines, height = split_by_width(line_to_render.nil? ? prompt : prompt + line_to_render, @screen_size.last) cursor_up_from_last_line = 0 if @scroll_partial_screen last_visual_line = this_started_from + (height - 1) last_screen_line = @scroll_partial_screen + (@screen_height - 1) if (@scroll_partial_screen - this_started_from) >= height # Render nothing because this line is before the screen. visual_lines = [] elsif this_started_from > last_screen_line # Render nothing because this line is after the screen. visual_lines = [] else deleted_lines_before_screen = [] if @scroll_partial_screen > this_started_from and last_visual_line >= @scroll_partial_screen # A part of visual lines are before the screen. deleted_lines_before_screen = visual_lines.shift((@scroll_partial_screen - this_started_from) * 2) deleted_lines_before_screen.compact! end if this_started_from <= last_screen_line and last_screen_line < last_visual_line # A part of visual lines are after the screen. visual_lines.pop((last_visual_line - last_screen_line) * 2) end move_cursor_up(deleted_lines_before_screen.size - @started_from) cursor_up_from_last_line = @started_from - deleted_lines_before_screen.size end end if with_control if height > @highest_in_this diff = height - @highest_in_this scroll_down(diff) @highest_in_all += diff @highest_in_this = height move_cursor_up(diff) elsif height < @highest_in_this diff = @highest_in_this - height @highest_in_all -= diff @highest_in_this = height end move_cursor_up(@started_from) @started_from = calculate_height_by_width(prompt_width + @cursor) - 1 cursor_up_from_last_line = height - 1 - @started_from end if Reline::Unicode::CSI_REGEXP.match?(prompt + line_to_render) @output.write "\e[0m" # clear character decorations end visual_lines.each_with_index do |line, index| Reline::IOGate.move_cursor_column(0) if line.nil? if calculate_width(visual_lines[index - 1], true) == Reline::IOGate.get_screen_size.last # reaches the end of line if Reline::IOGate.win? and Reline::IOGate.win_legacy_console? # A newline is automatically inserted if a character is rendered at # eol on command prompt. else # When the cursor is at the end of the line and erases characters # after the cursor, some terminals delete the character at the # cursor position. move_cursor_down(1) Reline::IOGate.move_cursor_column(0) end else Reline::IOGate.erase_after_cursor move_cursor_down(1) Reline::IOGate.move_cursor_column(0) end next end @output.write line if Reline::IOGate.win? and Reline::IOGate.win_legacy_console? and calculate_width(line, true) == Reline::IOGate.get_screen_size.last # A newline is automatically inserted if a character is rendered at eol on command prompt. @rest_height -= 1 if @rest_height > 0 end @output.flush if @first_prompt @first_prompt = false @pre_input_hook&.call end end unless visual_lines.empty? Reline::IOGate.erase_after_cursor Reline::IOGate.move_cursor_column(0) end if with_control # Just after rendring, so the cursor is on the last line. if finished? Reline::IOGate.move_cursor_column(0) else # Moves up from bottom of lines to the cursor position. move_cursor_up(cursor_up_from_last_line) # This logic is buggy if a fullwidth char is wrapped because there is only one halfwidth at end of a line. Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) end end height end
render_whole_lines(lines, prompt, prompt_width) 按一下以切換來源
# File lib/reline/line_editor.rb, line 1059 def render_whole_lines(lines, prompt, prompt_width) rendered_height = 0 modify_lines(lines).each_with_index do |line, index| if prompt.is_a?(Array) line_prompt = prompt[index] prompt_width = calculate_width(line_prompt, true) else line_prompt = prompt end height = render_partial(line_prompt, prompt_width, line, rendered_height, with_control: false) if index < (lines.size - 1) if @scroll_partial_screen if (@scroll_partial_screen - height) < rendered_height and (@scroll_partial_screen + @screen_height - 1) >= (rendered_height + height) move_cursor_down(1) end else scroll_down(1) end rendered_height += height else rendered_height += height - 1 end end rendered_height end
rerender_added_newline(prompt, prompt_width, prompt_list) 按一下以切換來源
# File lib/reline/line_editor.rb, line 908 def rerender_added_newline(prompt, prompt_width, prompt_list) @buffer_of_lines[@previous_line_index] = @line @line = @buffer_of_lines[@line_index] @previous_line_index = nil if @in_pasting scroll_down(1) else lines = whole_lines prev_line_prompt = @prompt_proc ? prompt_list[@line_index - 1] : prompt prev_line_prompt_width = @prompt_proc ? calculate_width(prev_line_prompt, true) : prompt_width prev_line = modify_lines(lines)[@line_index - 1] move_cursor_up(@started_from) render_partial(prev_line_prompt, prev_line_prompt_width, prev_line, @first_line_started_from + @started_from, with_control: false) scroll_down(1) render_partial(prompt, prompt_width, @line, @first_line_started_from + @started_from + 1, with_control: false) end @cursor = @cursor_max = calculate_width(@line) @byte_pointer = @line.bytesize @highest_in_all += @highest_in_this @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max) @first_line_started_from += @started_from + 1 @started_from = calculate_height_by_width(prompt_width + @cursor) - 1 end
rerender_all_lines() 按一下以切換來源
# File lib/reline/line_editor.rb, line 1004 def rerender_all_lines move_cursor_up(@first_line_started_from + @started_from) Reline::IOGate.move_cursor_column(0) back = 0 new_buffer = whole_lines prompt, prompt_width, prompt_list = check_multiline_prompt(new_buffer) new_buffer.each_with_index do |line, index| prompt_width = calculate_width(prompt_list[index], true) if @prompt_proc width = prompt_width + calculate_width(line) height = calculate_height_by_width(width) back += height end old_highest_in_all = @highest_in_all if @line_index.zero? new_first_line_started_from = 0 else new_first_line_started_from = calculate_height_by_lines(new_buffer[0..(@line_index - 1)], prompt_list || prompt) end new_started_from = calculate_height_by_width(prompt_width + @cursor) - 1 calculate_scroll_partial_screen(back, new_first_line_started_from + new_started_from) if @scroll_partial_screen move_cursor_up(@first_line_started_from + @started_from) scroll_down(@screen_height - 1) move_cursor_up(@screen_height) Reline::IOGate.move_cursor_column(0) elsif back > old_highest_in_all scroll_down(back - 1) move_cursor_up(back - 1) elsif back < old_highest_in_all scroll_down(back) Reline::IOGate.erase_after_cursor (old_highest_in_all - back - 1).times do scroll_down(1) Reline::IOGate.erase_after_cursor end move_cursor_up(old_highest_in_all - 1) end render_whole_lines(new_buffer, prompt_list || prompt, prompt_width) if @prompt_proc prompt = prompt_list[@line_index] prompt_width = calculate_width(prompt, true) end @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max) @highest_in_all = back @first_line_started_from = new_first_line_started_from @started_from = new_started_from if @scroll_partial_screen Reline::IOGate.move_cursor_up(@screen_height - (@first_line_started_from + @started_from - @scroll_partial_screen) - 1) Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) else move_cursor_down(@first_line_started_from + @started_from - back + 1) Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) end end
rerender_changed_current_line() 按一下以切換來源
# File lib/reline/line_editor.rb, line 960 def rerender_changed_current_line new_lines = whole_lines prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines) all_height = calculate_height_by_lines(new_lines, prompt_list || prompt) diff = all_height - @highest_in_all move_cursor_down(@highest_in_all - @first_line_started_from - @started_from - 1) if diff > 0 scroll_down(diff) move_cursor_up(all_height - 1) elsif diff < 0 (-diff).times do Reline::IOGate.move_cursor_column(0) Reline::IOGate.erase_after_cursor move_cursor_up(1) end move_cursor_up(all_height - 1) else move_cursor_up(all_height - 1) end @highest_in_all = all_height back = render_whole_lines(new_lines, prompt_list || prompt, prompt_width) move_cursor_up(back) if @previous_line_index @buffer_of_lines[@previous_line_index] = @line @line = @buffer_of_lines[@line_index] end @first_line_started_from = if @line_index.zero? 0 else calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt) end if @prompt_proc prompt = prompt_list[@line_index] prompt_width = calculate_width(prompt, true) end move_cursor_down(@first_line_started_from) calculate_nearest_cursor @started_from = calculate_height_by_width(prompt_width + @cursor) - 1 move_cursor_down(@started_from) Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last) @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max) end
run_for_operators(key, method_symbol, &block) 按一下以切換來源
# File lib/reline/line_editor.rb, line 1370 def run_for_operators(key, method_symbol, &block) if @waiting_operator_proc if VI_MOTIONS.include?(method_symbol) old_cursor, old_byte_pointer = @cursor, @byte_pointer @vi_arg = @waiting_operator_vi_arg if @waiting_operator_vi_arg&.> 1 block.(true) unless @waiting_proc cursor_diff, byte_pointer_diff = @cursor - old_cursor, @byte_pointer - old_byte_pointer @cursor, @byte_pointer = old_cursor, old_byte_pointer @waiting_operator_proc.(cursor_diff, byte_pointer_diff) else old_waiting_proc = @waiting_proc old_waiting_operator_proc = @waiting_operator_proc current_waiting_operator_proc = @waiting_operator_proc @waiting_proc = proc { |k| old_cursor, old_byte_pointer = @cursor, @byte_pointer old_waiting_proc.(k) cursor_diff, byte_pointer_diff = @cursor - old_cursor, @byte_pointer - old_byte_pointer @cursor, @byte_pointer = old_cursor, old_byte_pointer current_waiting_operator_proc.(cursor_diff, byte_pointer_diff) @waiting_operator_proc = old_waiting_operator_proc } end else # Ignores operator when not motion is given. block.(false) end @waiting_operator_proc = nil @waiting_operator_vi_arg = nil if @vi_arg @rerender_all = true @vi_arg = nil end else block.(false) end end
scroll_down(val) 按一下以切換來源
# File lib/reline/line_editor.rb, line 348 def scroll_down(val) if val <= @rest_height Reline::IOGate.move_cursor_down(val) @rest_height -= val else Reline::IOGate.move_cursor_down(@rest_height) Reline::IOGate.scroll_down(val - @rest_height) @rest_height = 0 end end
search_next_char(key, arg, need_prev_char: false, inclusive: false) 按一下以切換來源
# File lib/reline/line_editor.rb, line 3168 def search_next_char(key, arg, need_prev_char: false, inclusive: false) if key.instance_of?(String) inputed_char = key else inputed_char = key.chr end prev_total = nil total = nil found = false @line.byteslice(@byte_pointer..-1).grapheme_clusters.each do |mbchar| # total has [byte_size, cursor] unless total # skip cursor point width = Reline::Unicode.get_mbchar_width(mbchar) total = [mbchar.bytesize, width] else if inputed_char == mbchar arg -= 1 if arg.zero? found = true break end end width = Reline::Unicode.get_mbchar_width(mbchar) prev_total = total total = [total.first + mbchar.bytesize, total.last + width] end end if not need_prev_char and found and total byte_size, width = total @byte_pointer += byte_size @cursor += width elsif need_prev_char and found and prev_total byte_size, width = prev_total @byte_pointer += byte_size @cursor += width end if inclusive byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer) if byte_size > 0 c = @line.byteslice(@byte_pointer, byte_size) width = Reline::Unicode.get_mbchar_width(c) @byte_pointer += byte_size @cursor += width end end @waiting_proc = nil end
search_prev_char(key, arg, need_next_char = false) 按一下以切換來源
# File lib/reline/line_editor.rb, line 3225 def search_prev_char(key, arg, need_next_char = false) if key.instance_of?(String) inputed_char = key else inputed_char = key.chr end prev_total = nil total = nil found = false @line.byteslice(0..@byte_pointer).grapheme_clusters.reverse_each do |mbchar| # total has [byte_size, cursor] unless total # skip cursor point width = Reline::Unicode.get_mbchar_width(mbchar) total = [mbchar.bytesize, width] else if inputed_char == mbchar arg -= 1 if arg.zero? found = true break end end width = Reline::Unicode.get_mbchar_width(mbchar) prev_total = total total = [total.first + mbchar.bytesize, total.last + width] end end if not need_next_char and found and total byte_size, width = total @byte_pointer -= byte_size @cursor -= width elsif need_next_char and found and prev_total byte_size, width = prev_total @byte_pointer -= byte_size @cursor -= width end @waiting_proc = nil end
split_by_width(str, max_width) 按一下以切換來源
# File lib/reline/line_editor.rb, line 344 def split_by_width(str, max_width) Reline::Unicode.split_by_width(str, max_width, @encoding) end
update_each_dialog(dialog, cursor_column) 按一下以切換來源
# File lib/reline/line_editor.rb, line 769 def update_each_dialog(dialog, cursor_column) if @in_pasting dialog.contents = nil dialog.trap_key = nil return end dialog.set_cursor_pos(cursor_column, @first_line_started_from + @started_from) dialog_render_info = dialog.call(@last_key) if dialog_render_info.nil? or dialog_render_info.contents.nil? or dialog_render_info.contents.empty? dialog.contents = nil dialog.trap_key = nil return end contents = dialog_render_info.contents pointer = dialog.pointer if dialog_render_info.width dialog.width = dialog_render_info.width else dialog.width = contents.map { |l| calculate_width(l, true) }.max end height = dialog_render_info.height || DIALOG_DEFAULT_HEIGHT height = contents.size if contents.size < height if contents.size > height if dialog.pointer if dialog.pointer < 0 dialog.scroll_top = 0 elsif (dialog.pointer - dialog.scroll_top) >= (height - 1) dialog.scroll_top = dialog.pointer - (height - 1) elsif (dialog.pointer - dialog.scroll_top) < 0 dialog.scroll_top = dialog.pointer end pointer = dialog.pointer - dialog.scroll_top else dialog.scroll_top = 0 end contents = contents[dialog.scroll_top, height] end if dialog_render_info.scrollbar and dialog_render_info.contents.size > height bar_max_height = height * 2 moving_distance = (dialog_render_info.contents.size - height) * 2 position_ratio = dialog.scroll_top.zero? ? 0.0 : ((dialog.scroll_top * 2).to_f / moving_distance) bar_height = (bar_max_height * ((contents.size * 2).to_f / (dialog_render_info.contents.size * 2))).floor.to_i bar_height = MINIMUM_SCROLLBAR_HEIGHT if bar_height < MINIMUM_SCROLLBAR_HEIGHT scrollbar_pos = ((bar_max_height - bar_height) * position_ratio).floor.to_i else scrollbar_pos = nil end upper_space = @first_line_started_from - @started_from dialog.column = dialog_render_info.pos.x dialog.width += @block_elem_width if scrollbar_pos diff = (dialog.column + dialog.width) - (@screen_size.last) if diff > 0 dialog.column -= diff end if (@rest_height - dialog_render_info.pos.y) >= height dialog.vertical_offset = dialog_render_info.pos.y + 1 elsif upper_space >= height dialog.vertical_offset = dialog_render_info.pos.y - height else dialog.vertical_offset = dialog_render_info.pos.y + 1 end if dialog.column < 0 dialog.column = 0 dialog.width = @screen_size.last end face = Reline::Face[dialog_render_info.face || :default] scrollbar_sgr = face[:scrollbar] default_sgr = face[:default] enhanced_sgr = face[:enhanced] dialog.contents = contents.map.with_index do |item, i| line_sgr = i == pointer ? enhanced_sgr : default_sgr str_width = dialog.width - (scrollbar_pos.nil? ? 0 : @block_elem_width) str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, str_width), str_width) colored_content = "#{line_sgr}#{str}" if scrollbar_pos if scrollbar_pos <= (i * 2) and (i * 2 + 1) < (scrollbar_pos + bar_height) colored_content + scrollbar_sgr + @full_block elsif scrollbar_pos <= (i * 2) and (i * 2) < (scrollbar_pos + bar_height) colored_content + scrollbar_sgr + @upper_half_block elsif scrollbar_pos <= (i * 2 + 1) and (i * 2) < (scrollbar_pos + bar_height) colored_content + scrollbar_sgr + @lower_half_block else colored_content + scrollbar_sgr + ' ' * @block_elem_width end else colored_content end end end
vi_add(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2811 def vi_add(key) @config.editing_mode = :vi_insert ed_next_char(key) end
vi_add_at_eol(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2925 def vi_add_at_eol(key) ed_move_to_end(key) @config.editing_mode = :vi_insert end
vi_change_meta(key, arg: 1) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2951 def vi_change_meta(key, arg: 1) @drop_terminate_spaces = true @waiting_operator_proc = proc { |cursor_diff, byte_pointer_diff| if byte_pointer_diff > 0 @line, cut = byteslice!(@line, @byte_pointer, byte_pointer_diff) elsif byte_pointer_diff < 0 @line, cut = byteslice!(@line, @byte_pointer + byte_pointer_diff, -byte_pointer_diff) end copy_for_vi(cut) @cursor += cursor_diff if cursor_diff < 0 @cursor_max -= cursor_diff.abs @byte_pointer += byte_pointer_diff if byte_pointer_diff < 0 @config.editing_mode = :vi_insert @drop_terminate_spaces = false } @waiting_operator_vi_arg = arg end
vi_command_mode(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2816 def vi_command_mode(key) ed_prev_char(key) @config.editing_mode = :vi_command end
別名為: vi_movement_mode
vi_delete_meta(key, arg: 1) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2969 def vi_delete_meta(key, arg: 1) @waiting_operator_proc = proc { |cursor_diff, byte_pointer_diff| if byte_pointer_diff > 0 @line, cut = byteslice!(@line, @byte_pointer, byte_pointer_diff) elsif byte_pointer_diff < 0 @line, cut = byteslice!(@line, @byte_pointer + byte_pointer_diff, -byte_pointer_diff) end copy_for_vi(cut) @cursor += cursor_diff if cursor_diff < 0 @cursor_max -= cursor_diff.abs @byte_pointer += byte_pointer_diff if byte_pointer_diff < 0 } @waiting_operator_vi_arg = arg end
vi_delete_prev_char(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2900 def vi_delete_prev_char(key) if @is_multiline and @cursor == 0 and @line_index > 0 @buffer_of_lines[@line_index] = @line @cursor = calculate_width(@buffer_of_lines[@line_index - 1]) @byte_pointer = @buffer_of_lines[@line_index - 1].bytesize @buffer_of_lines[@line_index - 1] += @buffer_of_lines.delete_at(@line_index) @line_index -= 1 @line = @buffer_of_lines[@line_index] @cursor_max = calculate_width(@line) @rerender_all = true elsif @cursor > 0 byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer) @byte_pointer -= byte_size @line, mbchar = byteslice!(@line, @byte_pointer, byte_size) width = Reline::Unicode.get_mbchar_width(mbchar) @cursor -= width @cursor_max -= width end end
vi_end_big_word(key, arg: 1, inclusive: false) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2881 def vi_end_big_word(key, arg: 1, inclusive: false) if @line.bytesize > @byte_pointer byte_size, width = Reline::Unicode.vi_big_forward_end_word(@line, @byte_pointer) @byte_pointer += byte_size @cursor += width end arg -= 1 if inclusive and arg.zero? byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer) if byte_size > 0 c = @line.byteslice(@byte_pointer, byte_size) width = Reline::Unicode.get_mbchar_width(c) @byte_pointer += byte_size @cursor += width end end vi_end_big_word(key, arg: arg) if arg > 0 end
vi_end_word(key, arg: 1, inclusive: false) 按一下切換來源
# File lib/reline/line_editor.rb, line 2842 def vi_end_word(key, arg: 1, inclusive: false) if @line.bytesize > @byte_pointer byte_size, width = Reline::Unicode.vi_forward_end_word(@line, @byte_pointer) @byte_pointer += byte_size @cursor += width end arg -= 1 if inclusive and arg.zero? byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer) if byte_size > 0 c = @line.byteslice(@byte_pointer, byte_size) width = Reline::Unicode.get_mbchar_width(c) @byte_pointer += byte_size @cursor += width end end vi_end_word(key, arg: arg) if arg > 0 end
vi_first_print(key) 按一下切換來源
# File lib/reline/line_editor.rb, line 2050 def vi_first_print(key) @byte_pointer, @cursor = Reline::Unicode.vi_first_print(@line) end
vi_histedit(key) 按一下切換來源
# File lib/reline/line_editor.rb, line 3054 def vi_histedit(key) path = Tempfile.open { |fp| if @is_multiline fp.write whole_lines.join("\n") else fp.write @line end fp.path } system("#{ENV['EDITOR']} #{path}") if @is_multiline @buffer_of_lines = File.read(path).split("\n") @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty? @line_index = 0 @line = @buffer_of_lines[@line_index] @rerender_all = true else @line = File.read(path) end finish end
vi_insert(key) 按一下切換來源
# File lib/reline/line_editor.rb, line 2807 def vi_insert(key) @config.editing_mode = :vi_insert end
vi_insert_at_bol(key) 按一下切換來源
# File lib/reline/line_editor.rb, line 2920 def vi_insert_at_bol(key) ed_move_to_beg(key) @config.editing_mode = :vi_insert end
vi_join_lines(key, arg: 1) 按一下切換來源
# File lib/reline/line_editor.rb, line 3265 def vi_join_lines(key, arg: 1) if @is_multiline and @buffer_of_lines.size > @line_index + 1 @cursor = calculate_width(@line) @byte_pointer = @line.bytesize @line += ' ' + @buffer_of_lines.delete_at(@line_index + 1).lstrip @cursor_max = calculate_width(@line) @buffer_of_lines[@line_index] = @line @rerender_all = true @rest_height += 1 end arg -= 1 vi_join_lines(key, arg: arg) if arg > 0 end
vi_kill_line_prev(key) 按一下切換來源
- Editline
-
vi-kill-line-prev
(vi:Ctrl-U
) 刪除編輯緩衝區開頭到游標之間的字串,並將其儲存到剪下緩衝區。 - GNU
Readline
-
unix-line-discard
(C-u
) 從游標往後刪除到目前行的開頭。
# File lib/reline/line_editor.rb, line 2571 def vi_kill_line_prev(key) if @byte_pointer > 0 @line, deleted = byteslice!(@line, 0, @byte_pointer) @byte_pointer = 0 @kill_ring.append(deleted, true) @cursor_max = calculate_width(@line) @cursor = 0 end end
別名為: unix_line_discard
vi_list_or_eof(key) 按一下切換來源
# File lib/reline/line_editor.rb, line 2996 def vi_list_or_eof(key) if (not @is_multiline and @line.empty?) or (@is_multiline and @line.empty? and @buffer_of_lines.size == 1) @line = nil if @buffer_of_lines.size > 1 scroll_down(@highest_in_all - @first_line_started_from) end Reline::IOGate.move_cursor_column(0) @eof = true finish else ed_newline(key) end end
vi_next_big_word(key, arg: 1) 按一下切換來源
# File lib/reline/line_editor.rb, line 2861 def vi_next_big_word(key, arg: 1) if @line.bytesize > @byte_pointer byte_size, width = Reline::Unicode.vi_big_forward_word(@line, @byte_pointer) @byte_pointer += byte_size @cursor += width end arg -= 1 vi_next_big_word(key, arg: arg) if arg > 0 end
vi_next_char(key, arg: 1, inclusive: false) 按一下切換來源
# File lib/reline/line_editor.rb, line 3160 def vi_next_char(key, arg: 1, inclusive: false) @waiting_proc = ->(key_for_proc) { search_next_char(key_for_proc, arg, inclusive: inclusive) } end
vi_next_word(key, arg: 1) 按一下切換來源
# File lib/reline/line_editor.rb, line 2822 def vi_next_word(key, arg: 1) if @line.bytesize > @byte_pointer byte_size, width = Reline::Unicode.vi_forward_word(@line, @byte_pointer, @drop_terminate_spaces) @byte_pointer += byte_size @cursor += width end arg -= 1 vi_next_word(key, arg: arg) if arg > 0 end
vi_paste_next(key, arg: 1) 按一下切換來源
# File lib/reline/line_editor.rb, line 3088 def vi_paste_next(key, arg: 1) if @vi_clipboard.size > 0 byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer) @line = byteinsert(@line, @byte_pointer + byte_size, @vi_clipboard) @cursor_max += calculate_width(@vi_clipboard) @cursor += calculate_width(@vi_clipboard) @byte_pointer += @vi_clipboard.bytesize end arg -= 1 vi_paste_next(key, arg: arg) if arg > 0 end
vi_paste_prev(key, arg: 1) 按一下切換來源
# File lib/reline/line_editor.rb, line 3076 def vi_paste_prev(key, arg: 1) if @vi_clipboard.size > 0 @line = byteinsert(@line, @byte_pointer, @vi_clipboard) @cursor_max += calculate_width(@vi_clipboard) cursor_point = @vi_clipboard.grapheme_clusters[0..-2].join @cursor += calculate_width(cursor_point) @byte_pointer += cursor_point.bytesize end arg -= 1 vi_paste_prev(key, arg: arg) if arg > 0 end
vi_prev_big_word(key, arg: 1) 按一下切換來源
# File lib/reline/line_editor.rb, line 2871 def vi_prev_big_word(key, arg: 1) if @byte_pointer > 0 byte_size, width = Reline::Unicode.vi_big_backward_word(@line, @byte_pointer) @byte_pointer -= byte_size @cursor -= width end arg -= 1 vi_prev_big_word(key, arg: arg) if arg > 0 end
vi_prev_char(key, arg: 1) 按一下切換來源
# File lib/reline/line_editor.rb, line 3217 def vi_prev_char(key, arg: 1) @waiting_proc = ->(key_for_proc) { search_prev_char(key_for_proc, arg) } end
vi_prev_word(key, arg: 1) 按一下切換來源
# File lib/reline/line_editor.rb, line 2832 def vi_prev_word(key, arg: 1) if @byte_pointer > 0 byte_size, width = Reline::Unicode.vi_backward_word(@line, @byte_pointer) @byte_pointer -= byte_size @cursor -= width end arg -= 1 vi_prev_word(key, arg: arg) if arg > 0 end
vi_replace_char(key, arg: 1) 按一下切換來源
# File lib/reline/line_editor.rb, line 3132 def vi_replace_char(key, arg: 1) @waiting_proc = ->(k) { if arg == 1 byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer) before = @line.byteslice(0, @byte_pointer) remaining_point = @byte_pointer + byte_size after = @line.byteslice(remaining_point, @line.bytesize - remaining_point) @line = before + k.chr + after @cursor_max = calculate_width(@line) @waiting_proc = nil elsif arg > 1 byte_size = 0 arg.times do byte_size += Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer + byte_size) end before = @line.byteslice(0, @byte_pointer) remaining_point = @byte_pointer + byte_size after = @line.byteslice(remaining_point, @line.bytesize - remaining_point) replaced = k.chr * arg @line = before + replaced + after @byte_pointer += replaced.bytesize @cursor += calculate_width(replaced) @cursor_max = calculate_width(@line) @waiting_proc = nil end } end
vi_search_next(key) 按一下切換來源
# File lib/reline/line_editor.rb, line 2284 def vi_search_next(key) incremental_search_history(key) end
vi_search_prev(key) 按一下切換來源
# File lib/reline/line_editor.rb, line 2279 def vi_search_prev(key) incremental_search_history(key) end
vi_to_column(key, arg: 0) 按一下以切換來源
# File lib/reline/line_editor.rb, line 3117 def vi_to_column(key, arg: 0) @byte_pointer, @cursor = @line.grapheme_clusters.inject([0, 0]) { |total, gc| # total has [byte_size, cursor] mbchar_width = Reline::Unicode.get_mbchar_width(gc) if (total.last + mbchar_width) >= arg break total elsif (total.last + mbchar_width) >= @cursor_max break total else total = [total.first + gc.bytesize, total.last + mbchar_width] total end } end
vi_to_history_line(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 3031 def vi_to_history_line(key) if Reline::HISTORY.empty? return end if @history_pointer.nil? @history_pointer = 0 @line_backup_in_history = @line @line = Reline::HISTORY[@history_pointer] @cursor_max = calculate_width(@line) @cursor = 0 @byte_pointer = 0 elsif @history_pointer.zero? return else Reline::HISTORY[@history_pointer] = @line @history_pointer = 0 @line = Reline::HISTORY[@history_pointer] @cursor_max = calculate_width(@line) @cursor = 0 @byte_pointer = 0 end end
vi_to_next_char(key, arg: 1, inclusive: false) 按一下以切換來源
# File lib/reline/line_editor.rb, line 3164 def vi_to_next_char(key, arg: 1, inclusive: false) @waiting_proc = ->(key_for_proc) { search_next_char(key_for_proc, arg, need_prev_char: true, inclusive: inclusive) } end
vi_to_prev_char(key, arg: 1) 按一下以切換來源
# File lib/reline/line_editor.rb, line 3221 def vi_to_prev_char(key, arg: 1) @waiting_proc = ->(key_for_proc) { search_prev_char(key_for_proc, arg, true) } end
vi_yank(key, arg: 1) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2984 def vi_yank(key, arg: 1) @waiting_operator_proc = proc { |cursor_diff, byte_pointer_diff| if byte_pointer_diff > 0 cut = @line.byteslice(@byte_pointer, byte_pointer_diff) elsif byte_pointer_diff < 0 cut = @line.byteslice(@byte_pointer + byte_pointer_diff, -byte_pointer_diff) end copy_for_vi(cut) } @waiting_operator_vi_arg = arg end
vi_zero(key) 按一下以切換來源
# File lib/reline/line_editor.rb, line 2946 def vi_zero(key) @byte_pointer = 0 @cursor = 0 end