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.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.travis.lock +104 -0
  3. data/bin/yap +6 -0
  4. data/bin/yap-dev +37 -0
  5. data/lib/yap.rb +29 -39
  6. data/lib/yap/addon.rb +24 -0
  7. data/lib/yap/addon/base.rb +52 -0
  8. data/lib/yap/addon/export_as.rb +12 -0
  9. data/lib/yap/addon/loader.rb +84 -0
  10. data/lib/yap/addon/path.rb +56 -0
  11. data/lib/yap/addon/rc_file.rb +21 -0
  12. data/lib/yap/addon/reference.rb +22 -0
  13. data/lib/yap/cli.rb +4 -0
  14. data/lib/yap/cli/commands.rb +6 -0
  15. data/lib/yap/cli/commands/addon.rb +14 -0
  16. data/lib/yap/cli/commands/addon/disable.rb +35 -0
  17. data/lib/yap/cli/commands/addon/enable.rb +35 -0
  18. data/lib/yap/cli/commands/addon/list.rb +37 -0
  19. data/lib/yap/cli/commands/addon/search.rb +99 -0
  20. data/lib/yap/cli/commands/generate.rb +13 -0
  21. data/lib/yap/cli/commands/generate/addon.rb +258 -0
  22. data/lib/yap/cli/commands/generate/addonrb.template +22 -0
  23. data/lib/yap/cli/commands/generate/gemspec.template +25 -0
  24. data/lib/yap/cli/commands/generate/license.template +21 -0
  25. data/lib/yap/cli/commands/generate/rakefile.template +6 -0
  26. data/lib/yap/cli/commands/generate/readme.template +40 -0
  27. data/lib/yap/cli/options.rb +162 -0
  28. data/lib/yap/cli/options/addon.rb +64 -0
  29. data/lib/yap/cli/options/addon/disable.rb +62 -0
  30. data/lib/yap/cli/options/addon/enable.rb +63 -0
  31. data/lib/yap/cli/options/addon/list.rb +65 -0
  32. data/lib/yap/cli/options/addon/search.rb +76 -0
  33. data/lib/yap/cli/options/generate.rb +59 -0
  34. data/lib/yap/cli/options/generate/addon.rb +63 -0
  35. data/lib/yap/configuration.rb +10 -3
  36. data/lib/yap/gem_helper.rb +195 -0
  37. data/lib/yap/gem_tasks.rb +6 -0
  38. data/lib/yap/shell.rb +1 -1
  39. data/lib/yap/shell/repl.rb +1 -1
  40. data/lib/yap/shell/version.rb +1 -1
  41. data/lib/yap/world.rb +45 -7
  42. data/rcfiles/yaprc +90 -10
  43. data/spec/features/addons/generating_an_addon_spec.rb +55 -0
  44. data/spec/features/addons/using_an_addon_spec.rb +182 -0
  45. data/spec/features/aliases_spec.rb +6 -6
  46. data/spec/features/grouping_spec.rb +18 -18
  47. data/spec/features/line_editing_spec.rb +9 -1
  48. data/spec/features/redirection_spec.rb +12 -3
  49. data/spec/spec_helper.rb +21 -11
  50. data/spec/support/matchers/have_printed.rb +38 -0
  51. data/spec/support/yap_spec_dsl.rb +24 -6
  52. data/yap-shell.gemspec +6 -11
  53. metadata +51 -45
  54. data/addons/history/README.md +0 -16
  55. data/addons/history/history.rb +0 -58
  56. data/addons/history_search/history_search.rb +0 -197
  57. data/addons/keyboard_macros/keyboard_macros.rb +0 -425
  58. data/addons/keyboard_macros/lib/keyboard_macros/cycle.rb +0 -38
  59. data/addons/prompt/Gemfile +0 -1
  60. data/addons/prompt/right_prompt.rb +0 -17
  61. data/addons/prompt_updates/prompt_updates.rb +0 -28
  62. data/addons/tab_completion/Gemfile +0 -0
  63. data/addons/tab_completion/lib/tab_completion/basic_completion.rb +0 -151
  64. data/addons/tab_completion/lib/tab_completion/completer.rb +0 -62
  65. data/addons/tab_completion/lib/tab_completion/custom_completion.rb +0 -33
  66. data/addons/tab_completion/lib/tab_completion/dsl_methods.rb +0 -7
  67. data/addons/tab_completion/tab_completion.rb +0 -174
  68. data/lib/tasks/addons.rake +0 -97
  69. data/lib/yap/world/addons.rb +0 -181
@@ -0,0 +1,56 @@
1
+ module Yap
2
+ module Addon
3
+ class Path
4
+ def self.find_for_configuration(configuration)
5
+ addons_config_hsh = {}
6
+ if File.exists?(configuration.yap_addons_configuration_path)
7
+ addons_config_hsh = YAML.load_file(configuration.yap_addons_configuration_path)
8
+ end
9
+
10
+ new(configuration.addon_paths.flatten, addons_config_hsh).
11
+ references.sort_by(&:name)
12
+ end
13
+
14
+ attr_reader :references
15
+
16
+ def initialize(paths, addons_config_hsh={})
17
+ @paths = paths
18
+ @addons_config_hsh = addons_config_hsh
19
+ end
20
+
21
+ def references
22
+ @references ||= search_for_addons
23
+ end
24
+
25
+ private
26
+
27
+ def search_for_addons
28
+ @paths.each_with_object([]) do |path, results|
29
+ Dir["#{path}/*"].map do |directory|
30
+ next unless File.directory?(directory)
31
+
32
+ if File.basename(directory) =~ /(yap-shell-addon-(.*))-\d+\.\d+\.\d+/
33
+ require_as, name = $1, $2
34
+
35
+ addonrb_path = directory + "/lib/" + require_as + ".rb"
36
+ export_as = ExportAs.find_in_file(addonrb_path)
37
+ name = export_as if export_as
38
+ name = name.to_sym
39
+
40
+ enabled = !@addons_config_hsh.fetch(
41
+ name, { disabled: false }
42
+ )[:disabled]
43
+
44
+ results << Yap::Addon::Reference.new(
45
+ name: name,
46
+ require_as: require_as,
47
+ path: File.expand_path(directory),
48
+ enabled: enabled
49
+ )
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,21 @@
1
+ module Yap
2
+ module Addon
3
+ class RcFile < Yap::Addon::Base
4
+ attr_reader :file
5
+
6
+ def initialize(file)
7
+ super(enabled: true)
8
+ @file = File.expand_path(file)
9
+ end
10
+
11
+ def addon_name
12
+ @file
13
+ end
14
+
15
+ def initialize_world(world)
16
+ Treefell['shell'].puts "initializing rcfile: #{file}"
17
+ world.instance_eval File.read(@file), @file
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,22 @@
1
+ module Yap
2
+ module Addon
3
+ class Reference
4
+ attr_reader :name, :require_as, :path
5
+
6
+ def initialize(name:, require_as:, path:, enabled: true)
7
+ @name = name
8
+ @require_as = require_as
9
+ @path = path
10
+ @enabled = enabled
11
+ end
12
+
13
+ def disabled?
14
+ !@enabled
15
+ end
16
+
17
+ def enabled?
18
+ @enabled
19
+ end
20
+ end
21
+ end
22
+ end
data/lib/yap/cli.rb ADDED
@@ -0,0 +1,4 @@
1
+ module Yap
2
+ module Cli
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module Yap
2
+ module Cli
3
+ module Commands
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,14 @@
1
+ module Yap
2
+ module Cli
3
+ module Commands
4
+ class Addon
5
+ def initialize(addon_name)
6
+ @addon_name = addon_name
7
+ end
8
+
9
+ def process
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,35 @@
1
+ module Yap
2
+ module Cli
3
+ module Commands
4
+ class Addon::Disable
5
+ def initialize(addon_name)
6
+ @addon_name = addon_name
7
+ end
8
+
9
+ def process
10
+ configuration = Yap.configuration
11
+ addon_refs = Yap::Addon::Path.find_for_configuration(configuration)
12
+ addon_config_hsh = {}
13
+ found_addon_ref = nil
14
+ addon_refs.each do |addon_ref|
15
+ is_disabled = addon_ref.disabled?
16
+ if addon_ref.name.to_s == @addon_name.to_s
17
+ is_disabled = true
18
+ found_addon_ref = addon_ref
19
+ end
20
+ addon_config_hsh[addon_ref.name] = { disabled: is_disabled }
21
+ end
22
+
23
+ if found_addon_ref
24
+ destination = configuration.yap_addons_configuration_path.to_s
25
+ FileUtils.mkdir_p File.dirname(destination)
26
+ File.write destination, addon_config_hsh.to_yaml
27
+ puts "Addon #{found_addon_ref.name} has been disabled"
28
+ else
29
+ puts "Could not find addon with name #{@addon_name}"
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ module Yap
2
+ module Cli
3
+ module Commands
4
+ class Addon::Enable
5
+ def initialize(addon_name)
6
+ @addon_name = addon_name
7
+ end
8
+
9
+ def process
10
+ configuration = Yap.configuration
11
+ addon_refs = Yap::Addon::Path.find_for_configuration(configuration)
12
+ addon_config_hsh = {}
13
+ found_addon_ref = nil
14
+ addon_refs.each do |addon_ref|
15
+ is_disabled = addon_ref.disabled?
16
+ if addon_ref.name.to_s == @addon_name.to_s
17
+ is_disabled = false
18
+ found_addon_ref = addon_ref
19
+ end
20
+ addon_config_hsh[addon_ref.name] = { disabled: is_disabled }
21
+ end
22
+
23
+ if found_addon_ref
24
+ destination = configuration.yap_addons_configuration_path.to_s
25
+ FileUtils.mkdir_p File.dirname(destination)
26
+ File.write destination, addon_config_hsh.to_yaml
27
+ puts "Addon #{found_addon_ref.name} has been enabled"
28
+ else
29
+ puts "Could not find addon with name #{@addon_name}"
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,37 @@
1
+ module Yap
2
+ module Cli
3
+ module Commands
4
+ class Addon::List
5
+ def filter=(filter_kind)
6
+ @filter = filter_kind
7
+ end
8
+
9
+ def process
10
+ configuration = Yap.configuration
11
+
12
+ addon_refs = ::Yap::Addon::Path.
13
+ find_for_configuration(configuration)
14
+ if addon_refs.empty?
15
+ puts <<-MSG.strip_heredoc
16
+ |No addons found searching paths:
17
+ | - #{configuration.addon_paths.join("\n -")}
18
+ MSG
19
+ elsif @filter == :enabled
20
+ addon_refs.select(&:enabled?).each do |addon_ref|
21
+ puts "#{addon_ref.name}"
22
+ end
23
+ elsif @filter == :disabled
24
+ addon_refs.select(&:disabled?).each do |addon_ref|
25
+ puts "#{addon_ref.name}"
26
+ end
27
+ else
28
+ addon_refs.each do |addon_ref|
29
+ enabled_or_disabled = addon_ref.enabled? ? 'enabled' : 'disabled'
30
+ puts "#{addon_ref.name} (#{enabled_or_disabled})"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,99 @@
1
+ module Yap
2
+ module Cli
3
+ module Commands
4
+ class Addon::Search
5
+ attr_accessor :all, :local, :prerelease, :search_term, :version
6
+ attr_accessor :show_gem_name
7
+
8
+ def process
9
+ options = []
10
+
11
+ if search_term.nil?
12
+ puts "No addons found. Please provide a search term."
13
+ end
14
+
15
+ options << '--all' if all
16
+ options << '--local' if local
17
+ options << '--prerelease' if prerelease
18
+ options << "--version #{version}" if version
19
+
20
+ print_addons gem_search(options)
21
+ end
22
+
23
+ def extract_gem_names_from_search(search_results)
24
+ search_results.lines.map(&:chomp).map do |line|
25
+ results = line.scan(/^(yap-shell-addon-(\S+))\s*\((\d+\.\d+\.\d+)\)/)
26
+ gem_name, _, _ = results.flatten
27
+ gem_name
28
+ end.compact
29
+ end
30
+
31
+ def gem_search(options)
32
+ search_results = `gem search #{options.join(' ')} yap-shell | grep #{search_term}`
33
+ gem_names = extract_gem_names_from_search search_results
34
+ gem_specs_for_gems gem_names
35
+ end
36
+
37
+ def gem_specs_for_gems(gem_names)
38
+ options = []
39
+ options << (local ? '-l' : '-r')
40
+ options << "--version #{version}" if version
41
+ gem_names.map do |gem_name|
42
+ YAML.load `gem spec #{options.join(' ')} #{gem_name}`
43
+ end
44
+ end
45
+
46
+ def print_addons(gemspecs)
47
+ headers = {
48
+ name: (show_gem_name ? "Rubygem" : "Addon Name"),
49
+ version: "Version",
50
+ date: "Date Released",
51
+ author: "Author",
52
+ summary: "Summary"
53
+ }
54
+ value_for = {
55
+ name: -> (s) {
56
+ if show_gem_name
57
+ s.name
58
+ else
59
+ s.name.scan(/^yap-shell-addon-(\S+)/).flatten.first
60
+ end
61
+ },
62
+ version: -> (s) { s.version.to_s },
63
+ date: -> (s) { s.date.to_date.to_s },
64
+ author: -> (s) { s.author },
65
+ summary: -> (s) { s.summary }
66
+ }
67
+
68
+ longest = {
69
+ name: gemspecs.map{ |s| value_for[:name].call(s) }.concat(Array(headers[:name])).map(&:length).max,
70
+ version: gemspecs.map{ |s| value_for[:version].call(s) }.concat(Array(headers[:version])).map(&:length).max,
71
+ date: gemspecs.map{ |s| value_for[:date].call(s) }.concat(Array(headers[:date])).map(&:length).max,
72
+ author: gemspecs.map{ |s| value_for[:author].call(s) }.concat(Array(headers[:author])).map(&:length).max,
73
+ summary: gemspecs.map{ |s| value_for[:summary].call(s) }.concat(Array(headers[:summary])).map(&:length).max
74
+ }
75
+
76
+ spacing = " "
77
+ format_string = longest.reduce([]) do |str, (key, maxlength)|
78
+ str << "%-#{maxlength}s"
79
+ end.join(spacing)
80
+
81
+ output = gemspecs.map do |gemspec|
82
+ values = longest.keys.map { |key| value_for[key].call(gemspec) }
83
+ sprintf "#{format_string}", *values
84
+ end
85
+ output = output.join("\n")
86
+
87
+ highlighted_output = output.gsub(/(#{Regexp.escape(search_term)})/) do
88
+ Term::ANSIColor.cyan($1)
89
+ end
90
+
91
+ puts Term::ANSIColor.bright_black(
92
+ sprintf("#{format_string}", *longest.keys.map { |key| headers[key] })
93
+ )
94
+ puts highlighted_output
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,13 @@
1
+ require 'fileutils'
2
+ require 'term/ansicolor'
3
+
4
+ module Yap
5
+ module Cli
6
+ module Commands
7
+ class Generate
8
+ def process
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,258 @@
1
+ require 'fileutils'
2
+ require 'term/ansicolor'
3
+
4
+ module Yap
5
+ module Cli
6
+ module Commands
7
+ class Generate::Addon
8
+ attr_accessor :addon_name, :version, :use_git
9
+
10
+ def initialize(addon_name)
11
+ @addon_name = addon_name.gsub(/[^\w\-_]+/, '-').downcase
12
+ @version = '0.1.0'
13
+ @use_git = true
14
+ end
15
+
16
+ def doing(text, &block)
17
+ print "#{text}"
18
+ block.call
19
+ puts " #{Term::ANSIColor.green('done')}"
20
+ end
21
+
22
+ def process
23
+ puts "Creating addon #{Term::ANSIColor.yellow(addon_name)} in #{addon_dir}/"
24
+ puts
25
+
26
+ mkdir addon_dir
27
+ Dir.chdir addon_dir do
28
+ mkdir lib_path
29
+ write_file 'Gemfile', gemfile_contents
30
+ write_file gemspec_name, gemspec_contents
31
+ write_file 'LICENSE.txt', license_contents
32
+ write_file 'Rakefile', rakefile_contents
33
+ write_file 'README.md', readme_contents
34
+ write_file addonrb_path, addonrb_contents
35
+ mkdir lib_addon_path
36
+ write_file version_path, version_contents
37
+
38
+ puts
39
+ if use_git && `which git` && $?.exitstatus == 0
40
+ write_file '.gitignore', gitignore_contents
41
+ doing "git init . && git add . && git commit -m 'initial commit of #{addon_name}'" do
42
+ `git init . && git add . && git commit -m 'initial commit of #{addon_name} addon for yap'`
43
+ end
44
+ else
45
+ puts "Git initialization #{Term::ANSIColor.cyan('skipped')}"
46
+ end
47
+ end
48
+
49
+ puts
50
+ puts "Yap addon generated! A few helpful things to note:"
51
+ puts
52
+ puts <<-TEXT.gsub(/^\s*\|/, '')
53
+ | * The #{Term::ANSIColor.yellow(addon_name)} addon has been generated in #{addon_dir}/
54
+ | * It is a standard rubygem, has its own gemspec, and is named #{Term::ANSIColor.yellow(gem_safe_addon_name)}
55
+ | * Yap loads the #{Term::ANSIColor.yellow(constant_name)}, found in #{addonrb_path} (start there)
56
+ | * Share your addon with others by building a gem and pushing it to rubygems
57
+ |
58
+ |For more information see https://github.com/zdennis/yap-shell/wiki/Addons
59
+ |
60
+ |Now, to get started:
61
+ |
62
+ | cd #{gem_safe_addon_name}
63
+ TEXT
64
+ puts
65
+ end
66
+
67
+ private
68
+
69
+ def mkdir(path)
70
+ doing("Create directory: #{path}"){ FileUtils.mkdir_p path }
71
+ end
72
+
73
+ def write_file(path, contents)
74
+ doing "Creating file: #{path}" do
75
+ File.write path, contents
76
+ end
77
+ end
78
+
79
+ def addon_dir
80
+ gem_safe_addon_name
81
+ end
82
+
83
+ def addonrb_path
84
+ File.join(lib_path, gem_safe_addon_name + '.rb')
85
+ end
86
+
87
+ def addonrb_contents
88
+ contents = File.read(File.dirname(__FILE__) + '/addonrb.template')
89
+ contents % addonrb_template_variables
90
+ end
91
+
92
+ def addonrb_template_variables
93
+ export_as = addon_name
94
+ export_as = "'#{addon_name}'" if addon_name =~ /-/
95
+ {
96
+ addon_dir: addon_dir,
97
+ constant_name: constant_name,
98
+ export_as: export_as
99
+ }
100
+ end
101
+
102
+ def bundler_version
103
+ require 'bundler/version'
104
+ Bundler::VERSION.scan(/\d+\.\d+/).first ||
105
+ fail('Cannot determine bundler version')
106
+ end
107
+
108
+ def constant_name
109
+ gem_safe_addon_name.split(/\W+/).map(&:capitalize).join
110
+ end
111
+
112
+ def gemfile_contents
113
+ <<-GEMFILE.gsub(/^\s*\|/, '')
114
+ |source 'https://rubygems.org'
115
+ |
116
+ |# Specify your gem's dependencies in #{gemspec_name}
117
+ |gemspec
118
+ GEMFILE
119
+ end
120
+
121
+ def gem_safe_addon_name
122
+ "yap-shell-addon-#{addon_name}"
123
+ end
124
+
125
+ def gemspec_name
126
+ "#{gem_safe_addon_name}.gemspec"
127
+ end
128
+
129
+ def gemspec_contents
130
+ contents = File.read(File.dirname(__FILE__) + '/gemspec.template')
131
+ contents % gemspec_template_variables
132
+ end
133
+
134
+ def gemspec_template_variables
135
+ {
136
+ addon_dir: addon_dir,
137
+ constant_name: constant_name,
138
+ summary: "#{addon_name} summary goes here.",
139
+ description: "#{addon_name} description goes here.",
140
+ license: 'MIT',
141
+ authors: [],
142
+ email: 'you@example.com',
143
+ homepage: '',
144
+ bundler_version: bundler_version,
145
+ rake_version: rake_version,
146
+ rspec_version: rspec_version,
147
+ yap_version: yap_version
148
+ }
149
+ end
150
+
151
+ def gitignore_contents
152
+ <<-TEXT.gsub(/^\s*/, '')
153
+ *.gem
154
+ *.rbc
155
+ .bundle
156
+ .config
157
+ .yardoc
158
+ Gemfile.lock
159
+ InstalledFiles
160
+ _yardoc
161
+ coverage
162
+ doc/
163
+ lib/bundler/man
164
+ pkg
165
+ rdoc
166
+ spec/reports
167
+ test/tmp
168
+ test/version_tmp
169
+ tmp
170
+ *.bundle
171
+ *.so
172
+ *.o
173
+ *.a
174
+ mkmf.log
175
+ wiki/
176
+ TEXT
177
+ end
178
+
179
+ def lib_path
180
+ File.join('lib')
181
+ end
182
+
183
+ def lib_addon_path
184
+ File.join(lib_path, addon_dir)
185
+ end
186
+
187
+ def license_contents
188
+ contents = File.read(File.dirname(__FILE__) + '/license.template')
189
+ contents % license_template_variables
190
+ end
191
+
192
+ def license_template_variables
193
+ username = (`git config user.name` rescue 'YOUR_NAME')
194
+ { username: username }
195
+ end
196
+
197
+ def rake_version
198
+ require 'rake/version'
199
+ version_string = if Rake.const_defined?(:VERSION)
200
+ Rake::VERSION
201
+ else
202
+ Rake::Version::NUMBERS.join('.')
203
+ end
204
+ version_string.scan(/\d+\.\d+/).first ||
205
+ fail('Cannot determine rake version')
206
+ end
207
+
208
+ def rakefile_contents
209
+ File.read(File.dirname(__FILE__) + '/rakefile.template')
210
+ end
211
+
212
+ def readme_contents
213
+ contents = File.read(File.dirname(__FILE__) + '/readme.template')
214
+ contents % readme_template_variables
215
+ end
216
+
217
+ def readme_template_variables
218
+ {
219
+ addon_name: addon_name,
220
+ gem_safe_addon_name: gem_safe_addon_name,
221
+ lib_addon_path: lib_addon_path,
222
+ addon_dir: addon_dir,
223
+ constant_name: constant_name,
224
+ summary: "#{addon_name} summary goes here.",
225
+ description: "#{addon_name} description goes here.",
226
+ license: 'MIT',
227
+ authors: [],
228
+ email: 'you@example.com',
229
+ homepage: ''
230
+ }
231
+ end
232
+
233
+ def rspec_version
234
+ require 'rspec/version'
235
+ RSpec::Version::STRING.scan(/\d+\.\d+/).first ||
236
+ fail('Cannot determine rspec version')
237
+ end
238
+
239
+ def version_path
240
+ File.join(lib_addon_path, 'version.rb')
241
+ end
242
+
243
+ def version_contents
244
+ <<-RUBY.gsub(/^\s*\|/, '')
245
+ |module #{constant_name}
246
+ | VERSION = '#{version}'
247
+ |end
248
+ RUBY
249
+ end
250
+
251
+ def yap_version
252
+ Yap::Shell::VERSION.scan(/\d+\.\d+/).first ||
253
+ fail('Cannot determine yap version')
254
+ end
255
+ end
256
+ end
257
+ end
258
+ end