yap-shell 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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