yap-shell 0.4.11 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ee4c5a9db5dfeed5f41bd1290156f31f8ca44e4b
4
- data.tar.gz: 1ed5589d2dcdca412258a4f6fdda94a0fdb07d5c
3
+ metadata.gz: 0dd93a58914bed99609652e05c82c3f90fb11af3
4
+ data.tar.gz: 685276b3f2f829e8252c82490c30cb443bde61b9
5
5
  SHA512:
6
- metadata.gz: 169bcecab87f1ad1f7e96faa6609659272952d08e75a055ad207bd7bf806b85a0607115800733b2ee8ddb9a3271b550b363b1c1f4a7036969d41dd6447cb0a28
7
- data.tar.gz: 6204437dd12169220a819d23528f8f0b77eb87133157da2211a5a65af9514230913b66e6f2d9ef0d6bed14db64542fdba567e82a694523bd88e228c7bd9f0a6a
6
+ metadata.gz: 580220fe950fbc8cb393f1b783315a2af677177907951851b0d9c44ef7d9e7dd05f6dc0fea2aec3b436e2f187d0e27ca96a3b28449781c99a92689d405b90108
7
+ data.tar.gz: d037e820050e596a596891133b1bf18736ea9953850978d736505f6f32eee67e1b6e017d529a2dd9860ca69373b7b4006faa09aa953c18fd72816a4d80b4265e
data/Gemfile CHANGED
@@ -2,7 +2,8 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in yap.gemspec
4
4
  gemspec
5
+ # gem 'terminal-layout', path: "../terminal-layout"
5
6
  # gem 'yap-shell-parser', path: "../yap-shell-parser"
6
7
  # gem 'yap-shell-parser', git: 'git@github.com:zdennis/yap-shell-parser.git'
7
- # gem "rawline", git: 'git@github.com:zdennis/rawline.git', branch: 'issues/input-issues'
8
- # gem "rawline", path: '/Users/zdennis/source/opensource_projects/rawline'
8
+ # gem "yap-rawline", path: '/Users/zdennis/source/opensource_projects/rawline'
9
+ # gem "terminal-layout", path: '/Users/zdennis/source/playground/terminal-layout'
@@ -0,0 +1,193 @@
1
+ class HistorySearch < Addon
2
+ attr_reader :editor
3
+
4
+ def initialize_world(world)
5
+ @editor = world.editor
6
+ end
7
+
8
+ def prompt_user_to_search
9
+ label_text = "(reverse-search): "
10
+ search_label = ::TerminalLayout::Box.new(
11
+ content: label_text,
12
+ style: {
13
+ display: :inline,
14
+ height: 1
15
+ }
16
+ )
17
+ search_box = ::TerminalLayout::InputBox.new(
18
+ content: "",
19
+ style: {
20
+ display: :inline,
21
+ height: 1
22
+ }
23
+ )
24
+ search_box.name = "focused-input-box"
25
+
26
+ Treefell['shell'].puts "editor.content_box.children: #{editor.content_box.children.inspect}"
27
+ history_search_env = editor.new_env
28
+ history_search = Search.new(editor.history,
29
+ line: ::RawLine::LineEditor.new(::RawLine::Line.new, sync_with: -> { search_box }),
30
+ keys: history_search_env.keys,
31
+ search: -> (term:, result:){
32
+ # when there is no match, result will be nil, #to_s clears out the content
33
+ editor.input_box.content = result.to_s
34
+ },
35
+ done: -> (execute:, result:){
36
+ editor.content_box.children = []
37
+ editor.pop_env
38
+ editor.focus_input_box(editor.input_box)
39
+ editor.overwrite_line(result.to_s)
40
+ editor.process_line if execute
41
+ }
42
+ )
43
+
44
+ editor.push_env history_search_env
45
+ editor.push_keyboard_input_processor(history_search)
46
+
47
+ editor.content_box.children = [search_label, search_box]
48
+ editor.focus_input_box(search_box)
49
+ end
50
+
51
+ class Search
52
+ attr_reader :keys
53
+
54
+ def initialize(history, keys:, line:, search:, done:)
55
+ @history = history
56
+ @keys = keys
57
+ @line = line
58
+ @search_proc = search || -> {}
59
+ @done_proc = done || -> {}
60
+
61
+ initialize_key_bindings
62
+ end
63
+
64
+ def initialize_key_bindings
65
+ @keys.bind(:return){ execute }
66
+ @keys.bind(:ctrl_j){ accept }
67
+ @keys.bind(:ctrl_r){ search_again_backward }
68
+ @keys.bind(:ctrl_n){ search_again_forward }
69
+ @keys.bind(:ctrl_a){ @line.move_to_beginning_of_input }
70
+ @keys.bind(:ctrl_e){ @line.move_to_end_of_input }
71
+ @keys.bind(:backspace) do
72
+ @line.delete_left_character
73
+ perform_search(type: @last_search_was)
74
+ end
75
+ @keys.bind(:escape){ cancel }
76
+ @keys.bind(:ctrl_c){ cancel }
77
+ end
78
+
79
+ def read_bytes(bytes)
80
+ if bytes.any?
81
+ Treefell['shell'].puts "history search found bytes: #{bytes.inspect}"
82
+
83
+ # [1,2,3] => try 1,2,3 first ,then 1,2, then 1, then move on
84
+ nbytes = bytes.dup
85
+ search_bytes = []
86
+ loop do
87
+ if nbytes.empty?
88
+ break
89
+ elsif @keys[nbytes]
90
+ Treefell['shell'].puts "history search found key-binding for bytes=#{nbytes.inspect}"
91
+ @keys[nbytes].call
92
+ nbytes = search_bytes
93
+ search_bytes = []
94
+ else
95
+ search_bytes.unshift nbytes[-1]
96
+ nbytes = nbytes[0..-2]
97
+ end
98
+ end
99
+
100
+ if search_bytes.any?
101
+ Treefell['shell'].puts "history searching with bytes=#{bytes.inspect}"
102
+ search_with_bytes(bytes)
103
+ end
104
+ end
105
+ end
106
+
107
+ private
108
+
109
+ def accept
110
+ @done_proc.call(execute: false, result: result)
111
+ end
112
+
113
+ def cancel
114
+ @done_proc.call(execute: false, result: result)
115
+ end
116
+
117
+ def execute
118
+ @done_proc.call(execute: true, result: result)
119
+ end
120
+
121
+ def found_match(result:)
122
+ @search_proc.call(term: @line.text, result: result)
123
+ end
124
+
125
+ def no_match_found
126
+ @last_match_index = nil
127
+ @search_proc.call(term: @line.text, result: result)
128
+ end
129
+
130
+ def result
131
+ @history2search[@last_match_index] if @last_match_index
132
+ end
133
+
134
+ def search_again_backward
135
+ Treefell['shell'].puts "history searching again backward"
136
+ if @last_search_was == :forward
137
+ @last_match_index = @history.length - @last_match_index - 1
138
+ @history2search = @history.reverse
139
+ end
140
+ perform_search(starting_index: @last_match_index, type: :backward)
141
+ end
142
+
143
+ def search_again_forward
144
+ Treefell['shell'].puts "history searching again forward"
145
+ if @last_search_was == :backward
146
+ @last_match_index = @history.length - @last_match_index - 1
147
+ @history2search = @history
148
+ end
149
+ perform_search(starting_index: @last_match_index, type: :forward)
150
+ end
151
+
152
+ def search_with_bytes(bytes)
153
+ part = bytes.map(&:chr).join
154
+ @line.write(part.scan(/[[:print:]]/).join)
155
+ @history2search = @history.reverse
156
+ perform_search(type: :backward)
157
+ end
158
+
159
+ def perform_search(starting_index: -1, type:)
160
+ if @line.text.empty?
161
+ no_match_found
162
+ return
163
+ end
164
+
165
+ # fuzzy search
166
+ characters = @line.text.split('').map { |ch| Regexp.escape(ch) }
167
+ fuzzy_search_regex = /#{characters.join('.*?')}/
168
+
169
+ # non-fuzzy-search
170
+ # fuzzy_search_regex = /#{Regexp.escape(@line.text)}/
171
+
172
+ Treefell['shell'].puts "history search matching on regex=#{fuzzy_search_regex.inspect} starting_index=#{starting_index}"
173
+ @last_search_was = type
174
+
175
+ match = @history2search.detect.with_index do |item, i|
176
+ next if i <= starting_index
177
+
178
+ # Treefell['shell'].puts "history search matching #{(item + @line.text).inspect} =~ #{fuzzy_search_regex}"
179
+ md = (item + @line.text).match(fuzzy_search_regex)
180
+ if md && md.end(0) <= item.length
181
+ # Treefell['shell'].puts "history search match #{item} at #{i}"
182
+ @last_match_index = i
183
+ end
184
+ end
185
+
186
+ if match
187
+ found_match(result: match)
188
+ else
189
+ no_match_found
190
+ end
191
+ end
192
+ end
193
+ end
@@ -89,7 +89,7 @@ class KeyboardMacros < Addon
89
89
  configuration.start.call if configuration.start
90
90
 
91
91
  debug_log "taking over keyboard input processing from editor"
92
- world.editor.keyboard_input_processors.push(self)
92
+ world.editor.push_keyboard_input_processor(self)
93
93
 
94
94
  wait_timeout_in_seconds = 0.1
95
95
  world.editor.input.wait_timeout_in_seconds = wait_timeout_in_seconds
@@ -195,9 +195,9 @@ class KeyboardMacros < Addon
195
195
  definition.configuration.stop.call if definition.configuration.stop
196
196
  end
197
197
  @stack.clear
198
- if world.editor.keyboard_input_processors.last == self
198
+ if world.editor.keyboard_input_processor == self
199
199
  debug_log "giving keyboard input processing control back"
200
- world.editor.keyboard_input_processors.pop
200
+ world.editor.pop_keyboard_input_processor
201
201
 
202
202
  debug_log "restoring default editor input timeout"
203
203
  world.editor.input.restore_default_timeout
@@ -6,12 +6,14 @@ class RightPrompt < Addon
6
6
  def initialize_world(world)
7
7
  @world = world
8
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
- # )
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",
15
+ interval_in_ms: 1_000,
16
+ source: self
17
+ )
16
18
  end
17
19
  end
@@ -1,28 +1,29 @@
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
1
 
20
- end
21
2
 
22
- private
3
+ class PromptUpdates < Addon
4
+ def initialize_world(world)
5
+ @world = world
6
+
7
+ current_branch = determine_branch
23
8
 
24
- def determine_branch
25
- `git branch 2>/dev/null`.scan(/\*\s*(.*)$/).flatten.first
26
- end
9
+ @world.events.recur(
10
+ name: 'prompt_updates',
11
+ source: self,
12
+ interval_in_ms: 100
13
+ ) do
14
+ new_branch = determine_branch
15
+ if current_branch != new_branch
16
+ current_branch = new_branch
17
+ @world.refresh_prompt
18
+ end
19
+ end
20
+
21
+ end
27
22
 
28
- end
23
+ private
24
+
25
+ def determine_branch
26
+ `git branch 2>/dev/null`.scan(/\*\s*(.*)$/).flatten.first
27
+ end
28
+
29
+ end
data/bin/yap CHANGED
@@ -1,20 +1,35 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- if ENV["YAP_SHELL"].nil?
3
+ if ENV['YAP_SHELL'] != 'active'
4
4
  # Start YAP with a pristine environment
5
5
  env2keep = {
6
- 'PATH' => ENV['PATH'],
6
+ # DISPLAY needs to be inherited in order to launch GUI apps
7
+ 'DISPLAY' => ENV['DISPLAY'],
7
8
  'HOME' => ENV['HOME'],
9
+ 'PATH' => ENV['PATH'],
10
+
11
+ # For Yap's sanity
8
12
  'RUBYOPT' => '-rubygems -EUTF-8',
9
- 'TREEFELL_OUT' => ENV['TREEFELL_OUT'],
13
+ 'YAP_SHELL' => 'active',
14
+
15
+ # Inherit the user's preferred shell
16
+ 'SHELL' => ENV['SHELL'],
17
+
18
+ # Necessary for ssh-agent
19
+ 'SSH_AUTH_SOCK' => ENV['SSH_AUTH_SOCK'],
20
+
21
+ # DEBUG/TREEFELL_OUT are for debuging yap itself
10
22
  'DEBUG' => ENV['DEBUG'],
11
- 'YAP_SHELL' => 'active'
23
+ 'TREEFELL_OUT' => ENV['TREEFELL_OUT']
12
24
  }
25
+
26
+ ENV.clear
13
27
  env_params = env2keep.each_with_object([]) do |(key,value),arr|
14
28
  next if value.nil?
15
29
  arr << %|#{key}="#{value}"|
16
30
  end.join(' ')
17
- cmd = %|env -i #{env_params} #{$0}|
31
+
32
+ cmd = %|env -i #{env_params} #{File.expand_path(__FILE__)}|
18
33
  exec cmd
19
34
  else
20
35
  file = __FILE__
@@ -30,18 +45,10 @@ else
30
45
  $LOAD_PATH.unshift File.dirname(file) + '/../lib'
31
46
 
32
47
  ENV['TERM'] ||= 'linux'
33
-
34
- # Delete all RBENV/RVM environment variables
35
- # Once we're booted, we don't want them being inherited
36
- # by other child processes since those children cannot
37
- # modify Yap's ENV, only their own child env.
38
- ENV.keys.each do |key|
39
- if key =~ /^(rbenv_|rvm_)/i
40
- ENV.delete(key)
41
- end
42
- end
48
+ ENV['YAP_SHELL'] = 'active'
43
49
 
44
50
  require "term/ansicolor"
51
+ require "tins"
45
52
  require "byebug"
46
53
  require "pry"
47
54
  require "yap"
@@ -1,4 +1,50 @@
1
1
  namespace :addons do
2
+ task :new do
3
+ require 'highline'
4
+ require 'term/ansicolor'
5
+ require 'pathname'
6
+
7
+ extend Term::ANSIColor
8
+
9
+ yap_path = Pathname.new(File.dirname(__FILE__)).join('../..')
10
+ yap_lib_path = yap_path.join('lib')
11
+ yap_addons_path = yap_path.join('addons')
12
+
13
+ $LOAD_PATH.unshift yap_lib_path
14
+ require 'yap'
15
+
16
+ cli = HighLine.new
17
+ answer = cli.ask("Name for the addon? ")
18
+
19
+ addon_name = answer.downcase.gsub(/\W+/, '_')
20
+ addon_class_name = addon_name.split('_').map(&:capitalize).join
21
+ addon_path = yap_addons_path.join(addon_name)
22
+
23
+ loop do
24
+ answer = cli.ask("Create #{addon_class_name} addon in #{addon_path}? [Yn] ")
25
+ break if answer =~ /y/i
26
+ exit 1 if answer =~ /n/i
27
+ end
28
+ puts "Generating #{addon_class_name}"
29
+ puts
30
+
31
+ print " Creating #{addon_path} "
32
+ FileUtils.mkdir_p addon_path
33
+ puts green('done')
34
+
35
+ addon_file = addon_path.join("#{addon_name}.rb")
36
+ print " Creating #{addon_file} "
37
+ File.write addon_file, <<-FILE.gsub(/^\s*\|/, '')
38
+ |class #{addon_class_name} < Addon
39
+ | def initialize_world(world)
40
+ | # initialization code here
41
+ | end
42
+ |end
43
+ FILE
44
+ puts green('done')
45
+ puts
46
+ end
47
+
2
48
  namespace :update do
3
49
  desc "Update the gemspec based on add-on specific dependnecies"
4
50
  task :gemspec do
@@ -172,6 +172,7 @@ module Yap::Shell
172
172
  }
173
173
 
174
174
  if node.params.any?
175
+ Treefell['shell'].puts "block node params: #{node.params.inspect}"
175
176
  values.each_slice(node.params.length).each do |_slice|
176
177
  with_env do
177
178
  Hash[ node.params.zip(_slice) ].each_pair do |k,v|
@@ -44,6 +44,16 @@ module Yap::Shell::Execution
44
44
  begin
45
45
  before = ENV.to_h.dup
46
46
  ENV.replace(@world.env)
47
+ Treefell['shell'].puts <<-MSG.gsub(/^\s*\|/, '')
48
+ |forked child process
49
+ | pid=#{Process.pid} #{command.to_executable_str}
50
+ | stdin=#{stdin.inspect}
51
+ | stdout=#{stdout.inspect}
52
+ | stderr=#{stderr.inspect}
53
+ | $stdin=#{$stdin.inspect}
54
+ | $stdout=#{$stdout.inspect}
55
+ | $stderr=#{$stderr.inspect}
56
+ MSG
47
57
  Kernel.exec command.to_executable_str
48
58
  ensure
49
59
  ENV.replace(before)
@@ -6,7 +6,7 @@ module Yap::Shell::Execution
6
6
  possible_parameters = {
7
7
  command: command.str,
8
8
  args: command.args,
9
- stdin: @stdin,
9
+ stdin: (@stdin != $stdin ? @stdin : StringIO.new),
10
10
  stdout: @stdout,
11
11
  stderr: @stderr,
12
12
  world: @world,
@@ -19,10 +19,12 @@ module Yap::Shell::Execution
19
19
  h
20
20
  end
21
21
 
22
- Treefell['shell'].puts "shell command executing with params: #{params.inspect}"
23
- command_result = func.call(**params)
22
+ Treefell['shell'].puts "shell command executing with params: #{params.inspect} $stdout=#{$stdout.inspect} $stderr=#{$stderr.inspect}"
23
+ func.call(**params)
24
+
24
25
  @stdout.close if @stdout != $stdout && !@stdout.closed?
25
26
  @stderr.close if @stderr != $stderr && !@stderr.closed?
27
+ @stdin.close if @stdin != $stdin && !@stdin.closed?
26
28
  end
27
29
  end
28
30
  end
@@ -30,7 +30,6 @@ module Yap::Shell
30
30
  line = line_read << "\n"
31
31
  begin
32
32
  @blk.call(line)
33
- @world.editor.redraw_prompt
34
33
  rescue Yap::Shell::Parser::Lexer::NonterminatedString,
35
34
  Yap::Shell::Parser::Lexer::LineContinuationFound => ex
36
35
  Treefell['shell'].puts "rescued #{ex}, asking user for more input"
@@ -1,5 +1,5 @@
1
1
  module Yap
2
2
  module Shell
3
- VERSION = "0.4.11"
3
+ VERSION = "0.5.1"
4
4
  end
5
5
  end
@@ -98,12 +98,12 @@ module Yap
98
98
  attr_reader :file
99
99
 
100
100
  def initialize(file)
101
- @file = file
101
+ @file = File.expand_path(file)
102
102
  end
103
103
 
104
104
  def initialize_world(world)
105
105
  Treefell['shell'].puts "initializing rcfile: #{file}"
106
- world.instance_eval File.read(@file)
106
+ world.instance_eval File.read(@file), @file
107
107
  end
108
108
  end
109
109
 
data/lib/yap/world.rb CHANGED
@@ -129,7 +129,17 @@ module Yap
129
129
  evaluation.evaluate(statement) do |command, stdin, stdout, stderr, wait|
130
130
  context.clear_commands
131
131
  context.add_command_to_run command, stdin:stdin, stdout:stdout, stderr:stderr, wait:wait
132
- @last_result = context.execute(world:self)
132
+ @last_result = context.execute(world:self) || 0
133
+ if @last_result.is_a?(Integer)
134
+ Yap::Shell::Execution::Result.new(
135
+ status_code: @last_result,
136
+ directory: Dir.pwd,
137
+ n: 1,
138
+ of: 1
139
+ )
140
+ else
141
+ @last_result
142
+ end
133
143
  end
134
144
  end
135
145
 
@@ -224,6 +234,9 @@ module Yap
224
234
  dom.prompt_box = @prompt_box
225
235
  dom.input_box = @input_box
226
236
  dom.content_box = @content_box
237
+ @prompt_box.name = "prompt-box"
238
+ @input_box.name = "input-box"
239
+ @content_box.name = "content-box"
227
240
  end
228
241
  end
229
242
  end
data/rcfiles/yaprc CHANGED
@@ -155,6 +155,10 @@ world.editor.bind(:alt_down_arrow) do
155
155
  keyboard_macros.cycle(:recent_git_branches).previous
156
156
  end
157
157
 
158
+ world.editor.bind(:ctrl_r) do
159
+ world.addons[:history_search].prompt_user_to_search
160
+ end
161
+
158
162
  # Or, you can set the trigger key for a particular set of macros
159
163
  # by specifying it when you call .configure(...).
160
164
  world.addons[:keyboard_macros].configure(trigger_key: ?\C-g) do |macro|
data/yap-shell.gemspec CHANGED
@@ -65,11 +65,11 @@ Gem::Specification.new do |spec|
65
65
  spec.require_paths = ["lib"]
66
66
 
67
67
  spec.add_dependency "pry-byebug", "~> 3.3.0"
68
- spec.add_dependency "yap-shell-parser", "~> 0.6.1"
68
+ spec.add_dependency "yap-shell-parser", "~> 0.6.2"
69
69
  spec.add_dependency "term-ansicolor", "~> 1.3"
70
70
  spec.add_dependency "ruby-termios", "~> 0.9.6"
71
71
  spec.add_dependency "ruby-terminfo", "~> 0.1.1"
72
- spec.add_dependency "yap-rawline", "~> 0.3.5"
72
+ spec.add_dependency "yap-rawline", "~> 0.4.0"
73
73
  spec.add_dependency "treefell", "~> 0.2.3"
74
74
 
75
75
  spec.add_development_dependency "bundler", "~> 1.6"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yap-shell
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.11
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zach Dennis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-18 00:00:00.000000000 Z
11
+ date: 2016-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry-byebug
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.6.1
33
+ version: 0.6.2
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.6.1
40
+ version: 0.6.2
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: term-ansicolor
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 0.3.5
89
+ version: 0.4.0
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 0.3.5
96
+ version: 0.4.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: treefell
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -169,6 +169,7 @@ files:
169
169
  - WISHLIST.md
170
170
  - addons/history/README.md
171
171
  - addons/history/history.rb
172
+ - addons/history_search/history_search.rb
172
173
  - addons/keyboard_macros/keyboard_macros.rb
173
174
  - addons/keyboard_macros/lib/keyboard_macros/cycle.rb
174
175
  - addons/prompt/Gemfile