diff options
author | aycabta <aycabta@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2019-04-20 08:51:20 +0000 |
---|---|---|
committer | aycabta <aycabta@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2019-04-20 08:51:20 +0000 |
commit | 7f273ac6d0f05208b5b228da95205e20c0e8286c (patch) | |
tree | bfec81d78d487c6d8015f26fd6a5740cfef63d31 /lib/reline/key_stroke.rb | |
parent | 91faab7f1477c65f71aee8324cdeca7b6f19434a (diff) |
IRB is improved with Reline and RDoc
Reline is a readline stdlib compatible library. It also supports
multiline input. IRB is improved with Reline and supports multiline.
Besides, supports showing documents when completed.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67645 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/reline/key_stroke.rb')
-rw-r--r-- | lib/reline/key_stroke.rb | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/lib/reline/key_stroke.rb b/lib/reline/key_stroke.rb new file mode 100644 index 0000000000..ac0a820759 --- /dev/null +++ b/lib/reline/key_stroke.rb @@ -0,0 +1,74 @@ +class Reline::KeyStroke + using Module.new { + refine Array do + def start_with?(other) + other.size <= size && other == self.take(other.size) + end + + def bytes + self + end + end + } + + def initialize(config) + @config = config + @buffer = [] + end + + def input_to(bytes) + case match_status(bytes) + when :matching + nil + when :matched + expand(bytes) + when :unmatched + bytes + end + end + + def input_to!(bytes) + @buffer.concat Array(bytes) + input_to(@buffer)&.tap { clear } + end + + private + + def match_status(input) + key_mapping.keys.select { |lhs| + lhs.start_with? input + }.tap { |it| + return :matched if it.size == 1 && (it.max_by(&:size)&.size&.== input.size) + return :matching if it.size == 1 && (it.max_by(&:size)&.size&.!= input.size) + return :matched if it.max_by(&:size)&.size&.< input.size + return :matching if it.size > 1 + } + key_mapping.keys.select { |lhs| + input.start_with? lhs + }.tap { |it| + return it.size > 0 ? :matched : :unmatched + } + end + + def expand(input) + lhs = key_mapping.keys.select { |lhs| input.start_with? lhs }.sort_by(&:size).reverse.first + return input unless lhs + rhs = key_mapping[lhs] + + case rhs + when String + rhs_bytes = rhs.bytes + expand(expand(rhs_bytes) + expand(input.drop(lhs.size))) + when Symbol + [rhs] + expand(input.drop(lhs.size)) + end + end + + def key_mapping + @config[:key_mapping].transform_keys(&:bytes) + end + + def clear + @buffer = [] + end +end |