diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ed05f2..2b21f69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Added * Add to line the ability to find a word to complete before the cursor * Add ability to complete words +* Add support for adding a custom suffix to suggested word completion * Add :history_size keyword to allow configuration of maximum history size * Add the ability to replace a current line in the history buffer * Add support for preserving edits to lines stored in history diff --git a/lib/tty/reader.rb b/lib/tty/reader.rb index 3d1957e..6b6b1cc 100644 --- a/lib/tty/reader.rb +++ b/lib/tty/reader.rb @@ -62,6 +62,11 @@ def self.windows? # @api public attr_accessor :completion_handler + # The suffix to add to suggested word completion + # + # @api public + attr_accessor :completion_suffix + attr_reader :console attr_reader :cursor @@ -86,6 +91,8 @@ def self.windows? # exclude lines from history, by default all lines are stored # @param [Proc] completion_handler # the hanlder for finding word completion suggestions + # @param [String] completion_suffix + # the suffix to add to suggested word completion # # @api public def initialize(input: $stdin, output: $stdout, interrupt: :error, @@ -93,7 +100,7 @@ def initialize(input: $stdin, output: $stdout, interrupt: :error, history_exclude: History::DEFAULT_EXCLUDE, history_size: History::DEFAULT_SIZE, history_duplicates: false, - completion_handler: nil) + completion_handler: nil, completion_suffix: "") @input = input @output = output @interrupt = interrupt @@ -104,7 +111,8 @@ def initialize(input: $stdin, output: $stdout, interrupt: :error, @history_duplicates = history_duplicates @history_size = history_size @completion_handler = completion_handler - @completer = Completer.new(handler: completion_handler) + @completer = Completer.new(handler: completion_handler, + suffix: completion_suffix) @console = select_console(input) @history = History.new(history_size) do |h| diff --git a/lib/tty/reader/completer.rb b/lib/tty/reader/completer.rb index 59f1eb1..b8dd57b 100644 --- a/lib/tty/reader/completer.rb +++ b/lib/tty/reader/completer.rb @@ -14,14 +14,18 @@ class Completer # The handler for finding word completion suggestions attr_reader :handler + # The suffix to add to suggested word completion + attr_reader :suffix + # The word to complete attr_reader :word # Create a Completer instance # # @api private - def initialize(handler: nil) + def initialize(handler: nil, suffix: "") @handler = handler + @suffix = suffix @completions = Completions.new @show_initial = false @word = "" @@ -60,7 +64,7 @@ def complete_initial(line) completed_word = completions.get line.remove(word.length) - line.insert(completed_word) + line.insert(completed_word + suffix) completed_word end @@ -90,8 +94,11 @@ def complete_next(line) completed_word = completions.get end - line.remove(previous_suggestion.length) - line.insert(completed_word) + length_to_remove = previous_suggestion.length + length_to_remove += suffix.length if previous_suggestion != word + + line.remove(length_to_remove) + line.insert("#{completed_word}#{suffix unless @show_initial}") completed_word end diff --git a/spec/unit/complete_word_spec.rb b/spec/unit/complete_word_spec.rb index 68ae55c..7235fa6 100644 --- a/spec/unit/complete_word_spec.rb +++ b/spec/unit/complete_word_spec.rb @@ -139,4 +139,52 @@ expect(answer).to eq(%W[aa\n ab]) end + + it "adds space suffix to suggested word completion on the first tab" do + @completions = %w[aa ab ac] + options[:completion_suffix] = " " + reader = described_class.new(**options) + input << "x " << "a" << "\t" << "\n" + input.rewind + + answer = reader.read_line + + expect(answer).to eq("x aa \n") + end + + it "adds space suffix to suggested word completion on the second tab" do + @completions = %w[aa ab ac] + options[:completion_suffix] = " " + reader = described_class.new(**options) + input << "x " << "a" << "\t" << "\t" << "\n" + input.rewind + + answer = reader.read_line + + expect(answer).to eq("x ab \n") + end + + it "skips adding space suffix to the original word" do + @completions = %w[aa ab ac] + options[:completion_suffix] = " " + reader = described_class.new(**options) + input << "x " << "a" << "\t" << "\t" << "\t" << "\t" << "\n" + input.rewind + + answer = reader.read_line + + expect(answer).to eq("x a\n") + end + + it "adds two chars suffix to suggested word completion" do + @completions = %w[aa ab ac] + options[:completion_suffix] = "??" + reader = described_class.new(**options) + input << "x " << "a" << "\t" << "\t" << "\n" + input.rewind + + answer = reader.read_line + + expect(answer).to eq("x ab??\n") + end end