Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement dialog with autocomplete #318

Merged
merged 41 commits into from
Aug 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
1401d61
Implement dialog with autocomplete callback
aycabta Aug 17, 2021
5435c1a
Remove an unnecessary variable
aycabta Aug 18, 2021
74a6124
Suppress warning; unused variable
aycabta Aug 18, 2021
8f1db0a
Use background color instead of border frame
aycabta Aug 18, 2021
4406069
Add comments about where rerendering
aycabta Aug 18, 2021
5548550
Move cursor to rerender right margin of dialog correctly
aycabta Aug 21, 2021
4d7503c
Clear after cursor
aycabta Aug 21, 2021
2389d17
Remove debug code
aycabta Aug 21, 2021
a9050cf
Hide cursor when rendering dialog
aycabta Aug 21, 2021
0c87081
Support hide/show cursor on Windows
aycabta Aug 21, 2021
f1efa2b
Move dialog pos to left when goes beyond right edge
aycabta Aug 23, 2021
064d54f
Scroll properly to create margin
aycabta Aug 23, 2021
49f3392
Display autocomplete below original line if end point was wrapped
aycabta Aug 24, 2021
94f7027
Drop too much contents before processing
aycabta Aug 24, 2021
600b936
Combine vertical processing into @dialog_vertical_offset
aycabta Aug 24, 2021
8392824
Remove unnecessary metadata between lines
aycabta Aug 25, 2021
f31a76f
Show autocomplete correctly when starts from prev line
aycabta Aug 25, 2021
a39e2c8
Update dialog backup before clearing
aycabta Aug 25, 2021
14c8fad
Move cursor correctly when current line is auto wrapped
aycabta Aug 25, 2021
6370353
Fix typo
aycabta Aug 26, 2021
ccb70cc
Completion journey starts with one of candidates
aycabta Aug 26, 2021
07e911e
Remove unnecessary condition
aycabta Aug 26, 2021
e46437d
Implement dynamic selection of candidates
aycabta Aug 26, 2021
458cb8a
Remove @dialog_updown and @dialog_contents_width
aycabta Aug 26, 2021
46aa269
Cut out the autocomplete callback
aycabta Aug 26, 2021
f589fab
Support for multiple dialog rendering
aycabta Aug 27, 2021
063d9c7
Add the ability to handle context between dialogs
aycabta Aug 27, 2021
e97bbc4
Implement doc display dialog in conjunction with autocomplete
aycabta Aug 27, 2021
a505294
Show method or class doc correctly
aycabta Aug 27, 2021
52a40f2
Fix tests so that the completion journey starts on first C-n/C-p
aycabta Aug 27, 2021
cd0cbf5
Support custom bg color
aycabta Aug 27, 2021
b5f62c3
Suppress crashes on nil
aycabta Aug 27, 2021
7d1c75b
Use colored doc output with ANSI escape sequence
aycabta Aug 27, 2021
03716a4
Clear completion journey data when finished
aycabta Aug 27, 2021
f66a079
Clear dialog by C-c
aycabta Aug 27, 2021
5e67e6f
Use default dialog context to communicate others
aycabta Aug 29, 2021
9100ea2
Move constants of dialogs to under Reline
aycabta Aug 29, 2021
ac8fa84
Remove dialog_proc_list accessor of Reline
aycabta Aug 29, 2021
3b8cc5c
Remove an unnecessary variable
aycabta Aug 29, 2021
640102f
Delete show doc dialog to move it to IRB
aycabta Aug 29, 2021
d027dbe
Make autocomplete dialog is registered first
aycabta Aug 29, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions lib/reline.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class Core

def initialize
self.output = STDOUT
@dialog_proc_list = []
yield self
@completion_quote_character = nil
@bracketed_paste_finished = false
Expand Down Expand Up @@ -130,6 +131,12 @@ def dig_perfect_match_proc=(p)
@dig_perfect_match_proc = p
end

def add_dialog_proc(name_sym, p, context = nil)
raise ArgumentError unless p.respond_to?(:call) or p.nil?
raise ArgumentError unless name_sym.instance_of?(Symbol)
@dialog_proc_list << [name_sym, p, context]
end

def input=(val)
raise TypeError unless val.respond_to?(:getc) or val.nil?
if val.respond_to?(:getc)
Expand Down Expand Up @@ -171,6 +178,44 @@ def get_screen_size
Reline::IOGate.get_screen_size
end

Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE = ->() {
# autocomplete
if just_cursor_moving and completion_journey_data.nil?
# Auto complete starts only when edited
return nil
end
pre, target, post= retrieve_completion_block(true)
if target.nil? or target.empty?# or target.size <= 3
return nil
end
if completion_journey_data and completion_journey_data.list
result = completion_journey_data.list.dup
result.shift
pointer = completion_journey_data.pointer - 1
else
result = call_completion_proc_with_checking_args(pre, target, post)
pointer = nil
end
if result and result.size == 1 and result[0] == target
result = nil
end
target_width = Reline::Unicode.calculate_width(target)
x = cursor_pos.x - target_width
if x < 0
x = screen_width + x
y = -1
else
y = 0
end
cursor_pos_to_render = Reline::CursorPos.new(x, y)
if context and context.is_a?(Array)
context.clear
context.push(cursor_pos_to_render, result, pointer)
end
[cursor_pos_to_render, result, pointer, nil]
}
Reline::DEFAULT_DIALOG_CONTEXT = Array.new

def readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination)
unless confirm_multiline_termination
raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
Expand Down Expand Up @@ -230,6 +275,10 @@ def readline(prompt = '', add_hist = false)
line_editor.auto_indent_proc = auto_indent_proc
line_editor.dig_perfect_match_proc = dig_perfect_match_proc
line_editor.pre_input_hook = pre_input_hook
@dialog_proc_list.each do |d|
name_sym, dialog_proc, context = d
line_editor.add_dialog_proc(name_sym, dialog_proc, context)
end

unless config.test_mode
config.read
Expand Down Expand Up @@ -424,6 +473,7 @@ def self.insert_text(*args, &block)
def_single_delegators :core, :ambiguous_width
def_single_delegators :core, :last_incremental_search
def_single_delegators :core, :last_incremental_search=
def_single_delegators :core, :add_dialog_proc

def_single_delegators :core, :readmultiline
def_instance_delegators self, :readmultiline
Expand All @@ -445,6 +495,7 @@ def self.core
core.completer_quote_characters = '"\''
core.filename_quote_characters = ""
core.special_prefixes = ""
core.add_dialog_proc(:autocomplete, Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE, Reline::DEFAULT_DIALOG_CONTEXT)
}
end

Expand Down
16 changes: 16 additions & 0 deletions lib/reline/ansi.rb
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,22 @@ def self.move_cursor_down(x)
end
end

def self.hide_cursor
if Reline::Terminfo.enabled?
@@output.write Reline::Terminfo.tigetstr('civis')
else
# ignored
end
end

def self.show_cursor
if Reline::Terminfo.enabled?
@@output.write Reline::Terminfo.tigetstr('cnorm')
else
# ignored
end
end

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