yap-shell 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.travis.lock +104 -0
- data/bin/yap +6 -0
- data/bin/yap-dev +37 -0
- data/lib/yap.rb +29 -39
- data/lib/yap/addon.rb +24 -0
- data/lib/yap/addon/base.rb +52 -0
- data/lib/yap/addon/export_as.rb +12 -0
- data/lib/yap/addon/loader.rb +84 -0
- data/lib/yap/addon/path.rb +56 -0
- data/lib/yap/addon/rc_file.rb +21 -0
- data/lib/yap/addon/reference.rb +22 -0
- data/lib/yap/cli.rb +4 -0
- data/lib/yap/cli/commands.rb +6 -0
- data/lib/yap/cli/commands/addon.rb +14 -0
- data/lib/yap/cli/commands/addon/disable.rb +35 -0
- data/lib/yap/cli/commands/addon/enable.rb +35 -0
- data/lib/yap/cli/commands/addon/list.rb +37 -0
- data/lib/yap/cli/commands/addon/search.rb +99 -0
- data/lib/yap/cli/commands/generate.rb +13 -0
- data/lib/yap/cli/commands/generate/addon.rb +258 -0
- data/lib/yap/cli/commands/generate/addonrb.template +22 -0
- data/lib/yap/cli/commands/generate/gemspec.template +25 -0
- data/lib/yap/cli/commands/generate/license.template +21 -0
- data/lib/yap/cli/commands/generate/rakefile.template +6 -0
- data/lib/yap/cli/commands/generate/readme.template +40 -0
- data/lib/yap/cli/options.rb +162 -0
- data/lib/yap/cli/options/addon.rb +64 -0
- data/lib/yap/cli/options/addon/disable.rb +62 -0
- data/lib/yap/cli/options/addon/enable.rb +63 -0
- data/lib/yap/cli/options/addon/list.rb +65 -0
- data/lib/yap/cli/options/addon/search.rb +76 -0
- data/lib/yap/cli/options/generate.rb +59 -0
- data/lib/yap/cli/options/generate/addon.rb +63 -0
- data/lib/yap/configuration.rb +10 -3
- data/lib/yap/gem_helper.rb +195 -0
- data/lib/yap/gem_tasks.rb +6 -0
- data/lib/yap/shell.rb +1 -1
- data/lib/yap/shell/repl.rb +1 -1
- data/lib/yap/shell/version.rb +1 -1
- data/lib/yap/world.rb +45 -7
- data/rcfiles/yaprc +90 -10
- data/spec/features/addons/generating_an_addon_spec.rb +55 -0
- data/spec/features/addons/using_an_addon_spec.rb +182 -0
- data/spec/features/aliases_spec.rb +6 -6
- data/spec/features/grouping_spec.rb +18 -18
- data/spec/features/line_editing_spec.rb +9 -1
- data/spec/features/redirection_spec.rb +12 -3
- data/spec/spec_helper.rb +21 -11
- data/spec/support/matchers/have_printed.rb +38 -0
- data/spec/support/yap_spec_dsl.rb +24 -6
- data/yap-shell.gemspec +6 -11
- metadata +51 -45
- data/addons/history/README.md +0 -16
- data/addons/history/history.rb +0 -58
- data/addons/history_search/history_search.rb +0 -197
- data/addons/keyboard_macros/keyboard_macros.rb +0 -425
- data/addons/keyboard_macros/lib/keyboard_macros/cycle.rb +0 -38
- data/addons/prompt/Gemfile +0 -1
- data/addons/prompt/right_prompt.rb +0 -17
- data/addons/prompt_updates/prompt_updates.rb +0 -28
- data/addons/tab_completion/Gemfile +0 -0
- data/addons/tab_completion/lib/tab_completion/basic_completion.rb +0 -151
- data/addons/tab_completion/lib/tab_completion/completer.rb +0 -62
- data/addons/tab_completion/lib/tab_completion/custom_completion.rb +0 -33
- data/addons/tab_completion/lib/tab_completion/dsl_methods.rb +0 -7
- data/addons/tab_completion/tab_completion.rb +0 -174
- data/lib/tasks/addons.rake +0 -97
- data/lib/yap/world/addons.rb +0 -181
@@ -1,38 +0,0 @@
|
|
1
|
-
class KeyboardMacros
|
2
|
-
class Cycle
|
3
|
-
def initialize(cycle_proc:, on_cycle_proc: nil)
|
4
|
-
@cycle_proc = cycle_proc
|
5
|
-
@on_cycle_proc = on_cycle_proc
|
6
|
-
@previous_result = nil
|
7
|
-
reset
|
8
|
-
end
|
9
|
-
|
10
|
-
def next
|
11
|
-
@index = -1 if @index >= cycle_values.length - 1
|
12
|
-
on_cycle cycle_values[@index += 1]
|
13
|
-
end
|
14
|
-
|
15
|
-
def previous
|
16
|
-
@index = cycle_values.length if @index < 0
|
17
|
-
on_cycle cycle_values[@index -= 1]
|
18
|
-
end
|
19
|
-
|
20
|
-
def reset
|
21
|
-
@index = -1
|
22
|
-
@previous_result = nil
|
23
|
-
@cycle_values = nil
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def cycle_values
|
29
|
-
@cycle_values ||= @cycle_proc.call
|
30
|
-
end
|
31
|
-
|
32
|
-
def on_cycle(new_value)
|
33
|
-
@on_cycle_proc.call(@previous_result, new_value) if @on_cycle_proc
|
34
|
-
@previous_result = new_value
|
35
|
-
new_value
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
data/addons/prompt/Gemfile
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
gem "chronic", "~> 0.10.2"
|
@@ -1,17 +0,0 @@
|
|
1
|
-
class RightPrompt < Addon
|
2
|
-
def self.load_addon
|
3
|
-
@instance ||= new
|
4
|
-
end
|
5
|
-
|
6
|
-
def initialize_world(world)
|
7
|
-
@world = world
|
8
|
-
|
9
|
-
# @world.subscribe(:refresh_right_prompt) do |event|
|
10
|
-
# @world.right_prompt_text = Time.now.strftime("%H:%M:%S")
|
11
|
-
# end
|
12
|
-
#
|
13
|
-
# @world.events.recur(
|
14
|
-
# name: "refresh_right_prompt", source: self, interval_in_ms: 1_000
|
15
|
-
# )
|
16
|
-
end
|
17
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
class PromptUpdates < Addon
|
2
|
-
attr_reader :world
|
3
|
-
|
4
|
-
def initialize_world(world)
|
5
|
-
current_branch = determine_branch
|
6
|
-
|
7
|
-
@world = world
|
8
|
-
@world.events.recur(
|
9
|
-
name: 'prompt_updates',
|
10
|
-
source: self,
|
11
|
-
interval_in_ms: 100
|
12
|
-
) do
|
13
|
-
new_branch = determine_branch
|
14
|
-
if current_branch != new_branch
|
15
|
-
current_branch = new_branch
|
16
|
-
@world.refresh_prompt
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def determine_branch
|
25
|
-
`git branch 2>/dev/null`.scan(/\*\s*(.*)$/).flatten.first
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
File without changes
|
@@ -1,151 +0,0 @@
|
|
1
|
-
class TabCompletion
|
2
|
-
class BasicCompletion
|
3
|
-
class << self
|
4
|
-
attr_accessor :priority
|
5
|
-
end
|
6
|
-
self.priority = 1
|
7
|
-
|
8
|
-
attr_reader :world
|
9
|
-
|
10
|
-
def initialize(world:, word_break_characters:, path:nil)
|
11
|
-
@world = world
|
12
|
-
@word_break_characters = word_break_characters
|
13
|
-
path ||= @world.env["PATH"]
|
14
|
-
@paths = path.split(":")
|
15
|
-
end
|
16
|
-
|
17
|
-
def completions_for(word, words, word_index)
|
18
|
-
completions_by_name = {}
|
19
|
-
if looking_for_command?(word, words, word_index)
|
20
|
-
# Lowest Priority
|
21
|
-
completions_by_name.merge! command_completion_matches_for(word, words)
|
22
|
-
|
23
|
-
# Low Priority
|
24
|
-
completions_by_name.merge! builtin_completion_matches_for(word, words)
|
25
|
-
|
26
|
-
# Medium Priority
|
27
|
-
completions_by_name.merge! executable_filename_completion_matches_for(word, words)
|
28
|
-
|
29
|
-
# High Priority
|
30
|
-
completions_by_name.merge! shell_command_completion_matches_for(word, words)
|
31
|
-
|
32
|
-
# Highest Priority
|
33
|
-
completions_by_name.merge! alias_completion_matches_for(word, words)
|
34
|
-
else
|
35
|
-
completions_by_name.merge! filename_completion_matches_for(word, words)
|
36
|
-
end
|
37
|
-
completions_by_name.merge! environment_variable_completions_for(word, words)
|
38
|
-
completions_by_name.values
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
def looking_for_command?(word, words, word_index)
|
44
|
-
return false unless word_index
|
45
|
-
return true if word_index == 0
|
46
|
-
return true if words[word_index - 1] =~ /[;&]/
|
47
|
-
false
|
48
|
-
end
|
49
|
-
|
50
|
-
def alias_completion_matches_for(word, words)
|
51
|
-
@world.aliases.names.each_with_object({}) do |name, result|
|
52
|
-
if name =~ /^#{Regexp.escape(word)}/
|
53
|
-
result[name] ||= CompletionResult.new(
|
54
|
-
type: :alias,
|
55
|
-
text: name
|
56
|
-
)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def builtin_completion_matches_for(word, words)
|
62
|
-
@world.builtins.each_with_object({}) do |builtin, result|
|
63
|
-
if builtin =~ /^#{Regexp.escape(word)}/
|
64
|
-
result[builtin] ||= CompletionResult.new(
|
65
|
-
type: :builtin,
|
66
|
-
text: builtin
|
67
|
-
)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def command_completion_matches_for(word, words)
|
73
|
-
@paths.each_with_object({}) do |path, matches|
|
74
|
-
glob = File.join(path, "#{word}*")
|
75
|
-
arr = Dir[glob].select { |path| File.executable?(path) && File.file?(path) }
|
76
|
-
arr.map { |path| File.basename(path) }.uniq.each do |command|
|
77
|
-
matches[command] = CompletionResult.new(type: :command, text: command)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def environment_variable_completions_for(word, words)
|
83
|
-
return {} unless word =~ /^\$/
|
84
|
-
prefix, word_sans_prefix = word[0], word[1..-1]
|
85
|
-
@world.env.keys.each_with_object({}) do |env_var, result|
|
86
|
-
if env_var =~ /^#{Regexp.escape(word_sans_prefix)}/
|
87
|
-
result[env_var] ||= CompletionResult.new(
|
88
|
-
type: :env_var,
|
89
|
-
text: prefix + env_var
|
90
|
-
)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def executable_filename_completion_matches_for(word, words)
|
96
|
-
glob = "#{word}*"
|
97
|
-
glob.gsub!("~", world.env["HOME"])
|
98
|
-
Dir.glob(glob, File::FNM_CASEFOLD).each_with_object({}) do |path, result|
|
99
|
-
text = path.gsub(filtered_work_break_characters_rgx, '\\\\\1')
|
100
|
-
descriptive_text = File.basename(text)
|
101
|
-
if !File.directory?(path) && File.executable?(path)
|
102
|
-
result[path] = CompletionResult.new(
|
103
|
-
type: :command,
|
104
|
-
text: text,
|
105
|
-
descriptive_text: descriptive_text
|
106
|
-
)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
def shell_command_completion_matches_for(word, words)
|
112
|
-
@world.shell_commands.each_with_object({}) do |shell_command, result|
|
113
|
-
if shell_command =~ /^#{Regexp.escape(word)}/
|
114
|
-
result[shell_command] ||= CompletionResult.new(
|
115
|
-
type: :shell_command,
|
116
|
-
text: shell_command
|
117
|
-
)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
def filename_completion_matches_for(word, line)
|
123
|
-
glob = "#{word}*"
|
124
|
-
glob.gsub!("~", world.env["HOME"])
|
125
|
-
Dir.glob(glob, File::FNM_CASEFOLD).each_with_object({}) do |path, result|
|
126
|
-
text = path.gsub(filtered_work_break_characters_rgx, '\\\\\1')
|
127
|
-
descriptive_text = File.basename(text)
|
128
|
-
result[path] = if File.directory?(path)
|
129
|
-
CompletionResult.new(type: :directory, text: text, descriptive_text: descriptive_text)
|
130
|
-
elsif File.symlink?(path)
|
131
|
-
CompletionResult.new(type: :symlink, text: text, descriptive_text: descriptive_text)
|
132
|
-
elsif File.file?(path) && File.executable?(path)
|
133
|
-
CompletionResult.new(type: :command, text: text, descriptive_text: descriptive_text)
|
134
|
-
else
|
135
|
-
CompletionResult.new(type: :file, text: text, descriptive_text: descriptive_text)
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
# Remove file separator and the back-slash from word break characters when determining
|
141
|
-
# the pre-word-context
|
142
|
-
def filtered_word_break_characters
|
143
|
-
@word_break_characters.sub(File::Separator, "").sub('\\', '')
|
144
|
-
end
|
145
|
-
|
146
|
-
def filtered_work_break_characters_rgx
|
147
|
-
/([#{Regexp.escape(filtered_word_break_characters)}])/
|
148
|
-
end
|
149
|
-
|
150
|
-
end
|
151
|
-
end
|
@@ -1,62 +0,0 @@
|
|
1
|
-
class TabCompletion
|
2
|
-
|
3
|
-
class Completer
|
4
|
-
def initialize(char:, line:, completion:, completion_found:, completion_not_found:, done:)
|
5
|
-
@completion_char = char
|
6
|
-
@line = line
|
7
|
-
@completion_proc = completion
|
8
|
-
@completion_found_proc = completion_found
|
9
|
-
@completion_not_found_proc = completion_not_found
|
10
|
-
@done_proc = done
|
11
|
-
|
12
|
-
@completion_matches = HistoryBuffer.new(0) do |h|
|
13
|
-
h.duplicates = false
|
14
|
-
h.cycle = true
|
15
|
-
end
|
16
|
-
@completion_matches.empty
|
17
|
-
|
18
|
-
@first_time = true
|
19
|
-
@word_start = @line.word[:start]
|
20
|
-
end
|
21
|
-
|
22
|
-
def read_bytes(bytes)
|
23
|
-
return unless bytes.any?
|
24
|
-
|
25
|
-
if bytes.map(&:ord) != @completion_char
|
26
|
-
@done_proc.call(bytes)
|
27
|
-
elsif @first_time
|
28
|
-
matches = @completion_proc.call(sub_word) unless !@completion_proc || @completion_proc == []
|
29
|
-
matches = matches.to_a.compact.sort.reverse
|
30
|
-
|
31
|
-
if matches.any?
|
32
|
-
@completion_matches.resize(matches.length)
|
33
|
-
matches.each { |w| @completion_matches << w }
|
34
|
-
|
35
|
-
# Get first match
|
36
|
-
@completion_matches.back
|
37
|
-
match = @completion_matches.get
|
38
|
-
|
39
|
-
# completion matches is a history implementation and its in reverse order from what
|
40
|
-
# a user would expect
|
41
|
-
@completion_found_proc.call(completion: match, possible_completions: @completion_matches.reverse)
|
42
|
-
else
|
43
|
-
@completion_not_found_proc.call
|
44
|
-
@done_proc.call
|
45
|
-
end
|
46
|
-
@first_time = false
|
47
|
-
else
|
48
|
-
@completion_matches.back
|
49
|
-
match = @completion_matches.get
|
50
|
-
|
51
|
-
@completion_found_proc.call(completion: match, possible_completions: @completion_matches.reverse)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
def sub_word
|
58
|
-
@line.text[@line.word[:start]..@line.position-1] || ""
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
class TabCompletion
|
2
|
-
class CustomCompletion
|
3
|
-
PRIORITY = 2
|
4
|
-
|
5
|
-
attr_reader :name, :pattern, :priority
|
6
|
-
|
7
|
-
def initialize(world:, name:nil, pattern:nil, priority:PRIORITY, &blk)
|
8
|
-
@world = world
|
9
|
-
@name = name
|
10
|
-
@pattern = pattern
|
11
|
-
@priority = priority
|
12
|
-
@blk = blk
|
13
|
-
end
|
14
|
-
|
15
|
-
def new(world:)
|
16
|
-
@world = world
|
17
|
-
self
|
18
|
-
end
|
19
|
-
|
20
|
-
def completions_for(word, line)
|
21
|
-
# TODO
|
22
|
-
return []
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def match_rgx
|
28
|
-
return // if pattern.nil?
|
29
|
-
return pattern if pattern.is_a?(Regexp)
|
30
|
-
/^#{Regexp.escape(pattern.to_s)}\s/
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,174 +0,0 @@
|
|
1
|
-
require 'term/ansicolor'
|
2
|
-
|
3
|
-
class TabCompletion < Addon
|
4
|
-
require 'tab_completion/completer'
|
5
|
-
require 'tab_completion/dsl_methods'
|
6
|
-
require 'tab_completion/custom_completion'
|
7
|
-
require 'tab_completion/basic_completion'
|
8
|
-
|
9
|
-
class CompletionResult
|
10
|
-
attr_accessor :text, :type, :descriptive_text
|
11
|
-
|
12
|
-
def initialize(text:, type:, descriptive_text: nil)
|
13
|
-
@descriptive_text = descriptive_text || text
|
14
|
-
@text = text
|
15
|
-
@type = type
|
16
|
-
end
|
17
|
-
|
18
|
-
def ==(other)
|
19
|
-
other.is_a?(self.class) && @text == other.text && @type == other.type
|
20
|
-
end
|
21
|
-
|
22
|
-
def <=>(other)
|
23
|
-
@text <=> other.text
|
24
|
-
end
|
25
|
-
|
26
|
-
def to_s
|
27
|
-
@text.to_s
|
28
|
-
end
|
29
|
-
alias_method :to_str, :to_s
|
30
|
-
alias_method :inspect, :to_s
|
31
|
-
end
|
32
|
-
|
33
|
-
COMPLETIONS = [ BasicCompletion ]
|
34
|
-
|
35
|
-
Color = Term::ANSIColor
|
36
|
-
|
37
|
-
DISPLAY_PROCS = Hash.new{ |h,k| h[k] = ->(text){ text } }.merge(
|
38
|
-
directory: -> (text){ text + "/" }
|
39
|
-
)
|
40
|
-
|
41
|
-
STYLE_PROCS = Hash.new{ |h,k| h[k] = ->(text){ text } }.merge(
|
42
|
-
alias: -> (text){ Color.bold(Color.color("#ff00d7"){ text } ) },
|
43
|
-
builtin: -> (text){ Color.bold(Color.color("#d7af00"){ text } ) },
|
44
|
-
directory: -> (text){ Color.bold(Color.red(text)) },
|
45
|
-
command: -> (text){ Color.bold(Color.green(text)) },
|
46
|
-
shell_command: -> (text){ Color.bold(Color.color("#ffafff"){ text } ) },
|
47
|
-
symlink: -> (text){ Color.bold(Color.cyan(text)) },
|
48
|
-
selected: -> (text){ Color.negative(text) }
|
49
|
-
)
|
50
|
-
|
51
|
-
DECORATION_PROCS = Hash.new{ |h,k| h[k] = ->(text){ text } }.merge(
|
52
|
-
directory: -> (text){ text + "/" },
|
53
|
-
command: -> (text){ text + "@" },
|
54
|
-
shell_command: -> (text) { text + "🐚" }
|
55
|
-
)
|
56
|
-
|
57
|
-
attr_reader :editor, :world
|
58
|
-
|
59
|
-
def initialize_world(world)
|
60
|
-
@world = world
|
61
|
-
@world.extend TabCompletion::DslMethods
|
62
|
-
@editor = @world.editor
|
63
|
-
@editor.completion_proc = -> (word, line, word_index){
|
64
|
-
complete(word, line, word_index)
|
65
|
-
}
|
66
|
-
@editor.bind(:tab){ @editor.complete }
|
67
|
-
@completions = COMPLETIONS.dup
|
68
|
-
|
69
|
-
@style_procs = STYLE_PROCS.dup
|
70
|
-
@decoration_procs = DECORATION_PROCS.dup
|
71
|
-
@display_procs = DISPLAY_PROCS.dup
|
72
|
-
|
73
|
-
editor.on_word_complete do |event|
|
74
|
-
debug_log "on_word_complete event: #{event}"
|
75
|
-
|
76
|
-
sub_word = event[:payload][:sub_word]
|
77
|
-
word = event[:payload][:word]
|
78
|
-
actual_completion = event[:payload][:completion]
|
79
|
-
possible_completions = event[:payload][:possible_completions]
|
80
|
-
|
81
|
-
semi_formatted_possibilities = possible_completions.map.with_index do |completion, i|
|
82
|
-
if completion == actual_completion
|
83
|
-
style_text_for_selected_match(completion) + "\e[0m"
|
84
|
-
else
|
85
|
-
style_text_for_nonselected_match(completion) + "\e[0m"
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
max_width = @editor.terminal_width
|
90
|
-
max_item_width = semi_formatted_possibilities.map(&:length).max + 2
|
91
|
-
most_per_line = max_width / max_item_width
|
92
|
-
padding_at_the_end = max_width % max_item_width
|
93
|
-
|
94
|
-
formatted_possibilities = semi_formatted_possibilities.map.with_index do |completion, i|
|
95
|
-
spaces_to_pad = max_item_width - completion.length
|
96
|
-
completion + (" " * spaces_to_pad)
|
97
|
-
end
|
98
|
-
|
99
|
-
editor.content_box.children = formatted_possibilities.map do |str|
|
100
|
-
TerminalLayout::Box.new(content: str, style: { display: :float, float: :left, height: 1, width: max_item_width })
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
editor.on_word_complete_no_match do |event|
|
105
|
-
debug_log "on_word_complete_no_match event: #{event}"
|
106
|
-
|
107
|
-
sub_word = event[:payload][:sub_word]
|
108
|
-
word = event[:payload][:word]
|
109
|
-
editor.content_box.children = []
|
110
|
-
# editor.content_box.content = "Failed to find a match to complete #{sub_word} portion of #{word}"
|
111
|
-
end
|
112
|
-
|
113
|
-
editor.on_word_complete_done do |event|
|
114
|
-
debug_log "on_word_complete_done event: #{event}"
|
115
|
-
|
116
|
-
# TODO: add a better way to clear content
|
117
|
-
editor.content_box.children = []
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
def add_completion(name, pattern, &blk)
|
122
|
-
raise ArgumentError, "Must supply block!" unless block_given?
|
123
|
-
debug_log "NO-OP add_completion for name=#{name.inspect} pattern=#{pattern.inspect} block?=#{block_given?}"
|
124
|
-
# @completions.push CustomCompletion.new(name:name, pattern:pattern, world:world, &blk)
|
125
|
-
end
|
126
|
-
|
127
|
-
def set_decoration(type, &blk)
|
128
|
-
raise ArgumentError, "Must supply block!" unless block_given?
|
129
|
-
debug_log "set_decoration for type=#{name.inspect}"
|
130
|
-
@style_procs[type] = blk
|
131
|
-
end
|
132
|
-
|
133
|
-
def complete(word, words, word_index)
|
134
|
-
debug_log "complete word=#{word.inspect} words=#{words.inspect} word_index=#{word_index.inspect}"
|
135
|
-
|
136
|
-
matches = @completions.sort_by(&:priority).reverse.map do |completion|
|
137
|
-
if completion.respond_to?(:call)
|
138
|
-
completion.call
|
139
|
-
else
|
140
|
-
completions = completion.new(
|
141
|
-
world: @world,
|
142
|
-
word_break_characters: editor.word_break_characters
|
143
|
-
).completions_for(word, words, word_index)
|
144
|
-
completions.each do |completion|
|
145
|
-
completion.text = display_text_for_match(completion)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end.flatten
|
149
|
-
|
150
|
-
debug_log "complete possible matches are #{matches.inspect}"
|
151
|
-
matches
|
152
|
-
end
|
153
|
-
|
154
|
-
private
|
155
|
-
|
156
|
-
def display_text_for_match(match)
|
157
|
-
ANSIString.new @display_procs[match.type].call(match.text.dup)
|
158
|
-
end
|
159
|
-
|
160
|
-
def style_text_for_selected_match(match)
|
161
|
-
styled_text = @style_procs[match.type].call(match.descriptive_text.dup).to_s
|
162
|
-
styled_text = @decoration_procs[match.type].call(styled_text).to_s
|
163
|
-
uncolored_text = Color.uncolored(styled_text)
|
164
|
-
ANSIString.new @style_procs[:selected].call(uncolored_text)
|
165
|
-
end
|
166
|
-
|
167
|
-
def style_text_for_nonselected_match(match)
|
168
|
-
str = @decoration_procs[match.type].call(
|
169
|
-
@style_procs[match.type].call(match.descriptive_text.dup)
|
170
|
-
)
|
171
|
-
ANSIString.new str
|
172
|
-
end
|
173
|
-
|
174
|
-
end
|