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,65 @@
1
+ module Yap
2
+ module Cli
3
+ class Options::Addon::List
4
+ include OptionsLoader
5
+
6
+ attr_reader :command, :options
7
+
8
+ def initialize(options:)
9
+ @options = options
10
+ end
11
+
12
+ def parse(args)
13
+ option_parser.order!(args)
14
+ end
15
+
16
+ def command
17
+ @command ||= load_command('addon/list').new
18
+ end
19
+
20
+ def help_message
21
+ option_parser.to_s
22
+ end
23
+
24
+ private
25
+
26
+ def option_parser
27
+ OptionParser.new do |opts|
28
+ opts.banner = <<-TEXT.gsub(/^\s*\|/, '')
29
+ |Usage: #{opts.program_name} addon list [options]
30
+ |
31
+ |#{Term::ANSIColor.cyan('yap addon list')} can be used to list yap addons.
32
+ |
33
+ |Addon list options:
34
+ TEXT
35
+
36
+ opts.on('-h', '--help', 'Prints this help') do
37
+ puts opts
38
+ puts
39
+ puts <<-TEXT.gsub(/^\s*\|/, '')
40
+ |Example: Listing all addons
41
+ |
42
+ | #{opts.program_name} addon list
43
+ |
44
+ |Example: Listing disabled addons only
45
+ |
46
+ | #{opts.program_name} addon list --disabled
47
+ |
48
+ |Example: Listing enabled addons only
49
+ |
50
+ | #{opts.program_name} addon list --enabled
51
+ |
52
+ TEXT
53
+ exit 0
54
+ end
55
+ opts.on('--enabled', 'Lists yap addons that are enabled') do
56
+ command.filter = :enabled
57
+ end
58
+ opts.on('--disabled', 'Lists yap addons that are disabled') do
59
+ command.filter = :disabled
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,76 @@
1
+ module Yap
2
+ module Cli
3
+ class Options::Addon::Search
4
+ include OptionsLoader
5
+
6
+ attr_reader :command, :options
7
+
8
+ def initialize(options:)
9
+ @options = options
10
+ end
11
+
12
+ def parse(args)
13
+ search_terms = []
14
+ while args.any?
15
+ option_parser.order!(args)
16
+ search_terms << args.shift
17
+ end
18
+ command.search_term = search_terms.shift
19
+ end
20
+
21
+ def command
22
+ @command ||= load_command('addon/search').new
23
+ end
24
+
25
+ def help_message
26
+ option_parser.to_s
27
+ end
28
+
29
+ private
30
+
31
+ def option_parser
32
+ OptionParser.new do |opts|
33
+ opts.banner = <<-TEXT.gsub(/^\s*\|/, '')
34
+ |Usage: #{opts.program_name} addon search [options] [addon-name]
35
+ |
36
+ |#{Term::ANSIColor.cyan('yap addon search')} can be used to search for yap addons.
37
+ |
38
+ |Addon search options:
39
+ TEXT
40
+
41
+ opts.on('-h', '--help', 'Prints this help') do
42
+ puts opts
43
+ puts
44
+ puts <<-TEXT.gsub(/^\s*\|/, '')
45
+ |Example: Search for an addon
46
+ |
47
+ | #{opts.program_name} addon search --local foo
48
+ |
49
+ |Example: Search for an addon locally (no network access)
50
+ |
51
+ | #{opts.program_name} addon search foo
52
+ |
53
+ TEXT
54
+ exit 0
55
+ end
56
+ opts.on('--local', 'Search locally, no network access') do
57
+ command.local = true
58
+ end
59
+ opts.on('-a', '--all', 'Display all addon versions') do
60
+ command.all = true
61
+ end
62
+ opts.on('--prerelease', 'Display prerelease versions') do
63
+ command.prerelease = true
64
+ end
65
+ opts.on('--gem-name', 'Display rubygem name instead of shortened yap addon name') do
66
+ command.show_gem_name = true
67
+ end
68
+ opts.on('-v', '--version VERSION', 'Specify version of addon to search') do |version|
69
+ command.version = version
70
+ end
71
+
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,59 @@
1
+ module Yap
2
+ module Cli
3
+ class Options::Generate
4
+ include OptionsLoader
5
+
6
+ attr_reader :command, :options
7
+
8
+ def initialize(options:)
9
+ @options = options
10
+ @exit_status = 0
11
+ end
12
+
13
+ def parse(args)
14
+ if args.empty?
15
+ args.unshift '--help'
16
+ STDERR.puts "generate must be called with a component type!"
17
+ @exit_status = 1
18
+ puts
19
+ end
20
+
21
+ option_parser.order!(args)
22
+ end
23
+
24
+ def command
25
+ @command ||= load_command('generate').new
26
+ end
27
+
28
+ private
29
+
30
+ def option_parser
31
+ OptionParser.new do |opts|
32
+ opts.banner = <<-TEXT.gsub(/^\s*\|/, '')
33
+ |Usage: #{opts.program_name} generate [component-type] [options]
34
+ |
35
+ |#{Term::ANSIColor.cyan('yap generate')} can be used to generate yap components, like an addon.
36
+ |
37
+ |Generate commands:
38
+ |
39
+ | #{Term::ANSIColor.yellow('addon')} - generates a yap addon skeleton
40
+ |
41
+ |Generate options:
42
+ TEXT
43
+
44
+ opts.on('-h', '--help', 'Prints this help') do
45
+ puts opts
46
+ puts
47
+ puts <<-TEXT.gsub(/^\s*\|/, '')
48
+ |Example: Generating an addon
49
+ |
50
+ | #{opts.program_name} generate addon magical-key-bindings
51
+ |
52
+ TEXT
53
+ exit @exit_status
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,63 @@
1
+ module Yap
2
+ module Cli
3
+ class Options::Generate::Addon
4
+ include OptionsLoader
5
+
6
+ attr_reader :command, :options
7
+
8
+ def initialize(options:)
9
+ @options = options
10
+ @exit_status = 0
11
+ end
12
+
13
+ def parse(args)
14
+ @addon_name = args.shift unless args.first =~ /^-/
15
+ unless @addon_name
16
+ args.unshift '--help'
17
+ STDERR.puts "Missing addon-name!"
18
+ @exit_status = 1
19
+ puts
20
+ end
21
+ option_parser.order!(args)
22
+ end
23
+
24
+ def command
25
+ @command ||= load_command('generate/addon').new(@addon_name)
26
+ end
27
+
28
+ def help_message
29
+ option_parser.to_s
30
+ end
31
+
32
+ private
33
+
34
+ def option_parser
35
+ OptionParser.new do |opts|
36
+ opts.banner = <<-TEXT.gsub(/^\s*\|/, '')
37
+ |Usage: #{opts.program_name} generate addon [addon-name] [options]
38
+ |
39
+ |#{Term::ANSIColor.cyan('yap addon')} can be used to generate a yap addon skeleton provided an addon name.
40
+ |
41
+ |Generate addon options:
42
+ TEXT
43
+
44
+ opts.on('-h', '--help', 'Prints this help') do
45
+ puts opts
46
+ puts
47
+ puts <<-TEXT.gsub(/^\s*\|/, '')
48
+ |Example: Generating an addon
49
+ |
50
+ | #{opts.program_name} generate addon magical-key-bindings
51
+ |
52
+ TEXT
53
+ exit @exit_status
54
+ end
55
+
56
+ opts.on('--skip-git', 'Skip git initialization') do
57
+ command.use_git = false
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -10,6 +10,8 @@ module Yap
10
10
  class Configuration
11
11
  attr_accessor :addon_paths
12
12
  attr_accessor :rcfiles
13
+ attr_accessor :yap_addons_configuration_path
14
+ attr_accessor :yap_binpath
13
15
 
14
16
  def self.option(name, type=nil, default: nil)
15
17
  reader_method = name.to_s
@@ -31,16 +33,21 @@ module Yap
31
33
  end
32
34
  end
33
35
 
36
+ option :run_shell, :boolean, default: true
34
37
  option :skip_first_time, :boolean, default: false
35
38
  option :use_addons, :boolean, default: true
36
39
  option :use_history, :boolean, default: true
37
40
  option :use_rcfiles, :boolean, default: true
38
41
 
39
42
  def initialize
43
+ @yap_addons_configuration_path = yap_path.join('addons.yml')
44
+
40
45
  @addon_paths = [
41
- "#{File.dirname(__FILE__)}/../../addons",
42
- "#{ENV['HOME']}/.yap/addons"
43
- ]
46
+ # "#{File.dirname(__FILE__)}/../../addons",
47
+ # "#{ENV['HOME']}/.yap/addons"
48
+ ].concat(Gem.path.map { |gems_path| "#{gems_path}/gems" }).map do |path|
49
+ File.expand_path(path)
50
+ end
44
51
 
45
52
  @rcfiles = [
46
53
  "#{ENV['HOME']}/.yaprc",
@@ -0,0 +1,195 @@
1
+ require 'bundler'
2
+ require 'term/ansicolor'
3
+ require 'yap/addon'
4
+
5
+ module Yap
6
+ class GemHelper
7
+ Color = Term::ANSIColor
8
+
9
+ include Rake::DSL if defined? Rake::DSL
10
+
11
+ class << self
12
+ # set when install'd.
13
+ attr_accessor :instance
14
+
15
+ def install_tasks(opts = {})
16
+ new(opts[:dir], opts[:name]).install
17
+ end
18
+ end
19
+
20
+ attr_reader :spec_path, :base, :gemspec
21
+
22
+ def initialize(base = nil, name = nil)
23
+ @base ||= Dir.pwd
24
+ gemspecs = name ? [File.join(@base, "#{name}.gemspec")] : Dir[File.join(@base, "{,*}.gemspec")]
25
+ raise "Unable to determine name from existing gemspec. Use :name => 'gemname' in #install_tasks to manually set it." unless gemspecs.size == 1
26
+ @spec_path = gemspecs.first
27
+ @gemspec = Bundler.load_gemspec(@spec_path)
28
+ @export_as = Yap::Addon.export_as_for_gemspec(@gemspec)
29
+ end
30
+
31
+ def install
32
+ built_gem_path = nil
33
+
34
+ desc "Build #{Color.yellow(@export_as)} yap addon as gem #{name}-#{version}.gem"
35
+ task "build" do
36
+ built_gem_path = build_gem
37
+ puts "Don't forget to run #{Term::ANSIColor.yellow('rake install && reload!')} to see your changes reflected in yap."
38
+ puts Term::ANSIColor.bright_black("P.S. You can skip this step if you always run 'rake install'")
39
+ end
40
+
41
+ desc "Build and install #{Color.yellow(@export_as)} yap addon as gem #{name}-#{version}.gem into system gems."
42
+ task "install" do
43
+ built_gem_path = build_gem
44
+ install_gem(built_gem_path)
45
+ puts "Don't forget to run #{Term::ANSIColor.yellow('reload!')} to see your changes reflected in yap."
46
+ end
47
+
48
+ desc "Build and install #{Color.yellow(@export_as)} yap addon as #{name}-#{version}.gem into system gems without network access."
49
+ task "install:local" => "build" do
50
+ install_gem(built_gem_path, :local)
51
+ end
52
+
53
+ desc "Create tag #{version_tag} and build and push #{Color.yellow(@export_as)} addon #{name}-#{version}.gem to Rubygems\n" \
54
+ "To prevent publishing in Rubygems use `gem_push=no rake release`"
55
+ task "release", [:remote] => ["build", "release:guard_clean",
56
+ "release:source_control_push", "release:rubygem_push"] do
57
+ end
58
+
59
+ task "release:guard_clean" do
60
+ guard_clean
61
+ end
62
+
63
+ task "release:source_control_push", [:remote] do |_, args|
64
+ tag_version { git_push(args[:remote]) } unless already_tagged?
65
+ end
66
+
67
+ task "release:rubygem_push" do
68
+ rubygem_push(built_gem_path) if gem_push?
69
+ end
70
+
71
+ GemHelper.instance = self
72
+ end
73
+
74
+ def build_gem
75
+ file_name = nil
76
+ sh("gem build -V '#{spec_path}'") do
77
+ file_name = File.basename(built_gem_path)
78
+ FileUtils.mkdir_p(File.join(base, 'pkg'))
79
+ FileUtils.mv(built_gem_path, 'pkg')
80
+ tell_user_success("#{name} #{version} built to pkg/#{file_name}.")
81
+ end
82
+ File.join(base, "pkg", file_name)
83
+ end
84
+
85
+ def install_gem(built_gem_path = nil, local = false)
86
+ built_gem_path ||= build_gem
87
+ out, _ = sh_with_code("gem install '#{built_gem_path}'#{" --local" if local}")
88
+ raise "Couldn't install gem, run `gem install #{built_gem_path}' for more detailed output" unless out[/Successfully installed/]
89
+ tell_user_success("#{name} (#{version}) installed.")
90
+ end
91
+
92
+ protected
93
+
94
+ def tell_user_success(msg)
95
+ puts Color.green(msg)
96
+ end
97
+
98
+ def tell_user_error(msg)
99
+ puts Color.red(msg)
100
+ end
101
+
102
+ def rubygem_push(path)
103
+ allowed_push_host = nil
104
+ gem_command = "gem push '#{path}'"
105
+ if @gemspec.respond_to?(:metadata)
106
+ allowed_push_host = @gemspec.metadata["allowed_push_host"]
107
+ gem_command += " --host #{allowed_push_host}" if allowed_push_host
108
+ end
109
+ unless allowed_push_host || Pathname.new("~/.gem/credentials").expand_path.file?
110
+ raise "Your rubygems.org credentials aren't set. Run `gem push` to set them."
111
+ end
112
+ sh(gem_command)
113
+ tell_user_success "Pushed #{name} #{version} to #{allowed_push_host ? allowed_push_host : "rubygems.org."}"
114
+ end
115
+
116
+ def built_gem_path
117
+ Dir[File.join(base, "#{name}-*.gem")].sort_by {|f| File.mtime(f) }.last
118
+ end
119
+
120
+ def git_push(remote = "")
121
+ perform_git_push remote
122
+ perform_git_push "#{remote} --tags"
123
+ tell_user_success "Pushed git commits and tags."
124
+ end
125
+
126
+ def perform_git_push(options = "")
127
+ cmd = "git push #{options}"
128
+ out, code = sh_with_code(cmd)
129
+ raise "Couldn't git push. `#{cmd}' failed with the following output:\n\n#{out}\n" unless code == 0
130
+ end
131
+
132
+ def already_tagged?
133
+ return false unless sh("git tag").split(/\n/).include?(version_tag)
134
+ tell_user_success "Tag #{version_tag} has already been created."
135
+ true
136
+ end
137
+
138
+ def guard_clean
139
+ clean? && committed? || raise("There are files that need to be committed first.")
140
+ end
141
+
142
+ def clean?
143
+ sh_with_code("git diff --exit-code")[1] == 0
144
+ end
145
+
146
+ def committed?
147
+ sh_with_code("git diff-index --quiet --cached HEAD")[1] == 0
148
+ end
149
+
150
+ def tag_version
151
+ sh "git tag -a -m \"Version #{version}\" #{version_tag}"
152
+ tell_user_success "Tagged #{version_tag}."
153
+ yield if block_given?
154
+ rescue
155
+ tell_user_error "Untagging #{version_tag} due to error."
156
+ sh_with_code "git tag -d #{version_tag}"
157
+ raise
158
+ end
159
+
160
+ def version
161
+ gemspec.version
162
+ end
163
+
164
+ def version_tag
165
+ "v#{version}"
166
+ end
167
+
168
+ def name
169
+ gemspec.name
170
+ end
171
+
172
+ def sh(cmd, &block)
173
+ out, code = sh_with_code(cmd, &block)
174
+ unless code.zero?
175
+ raise(out.empty? ? "Running `#{cmd}` failed. Run this command directly for more detailed output." : out)
176
+ end
177
+ out
178
+ end
179
+
180
+ def sh_with_code(cmd, &block)
181
+ cmd += " 2>&1"
182
+ outbuf = String.new
183
+ Dir.chdir(base) do
184
+ outbuf = `#{cmd}`
185
+ status = $?.exitstatus
186
+ block.call(outbuf) if status.zero? && block
187
+ [outbuf, status]
188
+ end
189
+ end
190
+
191
+ def gem_push?
192
+ ! %w(n no nil false off 0).include?(ENV["gem_push"].to_s.downcase)
193
+ end
194
+ end
195
+ end