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
@@ -1,97 +0,0 @@
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
-
48
- namespace :update do
49
- desc "Update the gemspec based on add-on specific dependnecies"
50
- task :gemspec do
51
- require 'bundler'
52
- runtime_deps = []
53
- development_deps = []
54
- root_dir = File.dirname(__FILE__) + "/../.."
55
- gemfiles = Dir[root_dir + "/addons/**/**/Gemfile"]
56
- gemfiles.each do |gemfile|
57
- bd = Bundler::Definition.build(gemfile, nil, nil)
58
- runtime_deps.push *bd.dependencies.select{ |dep| dep.type == :runtime }
59
- development_deps.push *bd.dependencies.select{ |dep| dep.type == :development }
60
- end
61
-
62
- runtime_h = Hash.new{ |h,name| h[name] = Gem::Dependency.new(name) }
63
- runtime_deps.each { |dep| runtime_h[dep.name] = runtime_h[dep.name].merge(dep) }
64
-
65
- dev_h = Hash.new{ |h,name| h[name] = Gem::Dependency.new(name) }
66
- development_deps.each { |dep| dev_h[dep.name] = dev_h[dep.name].merge(dep) }
67
-
68
- deps_str = ""
69
- deps_str << runtime_h.map do |name, dep|
70
- if dep.requirement.none?
71
- %| spec.add_dependency "#{dep.name}"|
72
- else
73
- %| spec.add_dependency "#{dep.name}", "#{dep.requirement.as_list.first}"|
74
- end
75
- end.join("\n")
76
-
77
- deps_str << dev_h.map do |name, dep|
78
- if dep.requirement.none?
79
- %| spec.add_development_dependency "#{dep.name}"|
80
- else
81
- %| spec.add_development_dependency "#{dep.name}", "#{dep.requirement.as_list.first}"|
82
- end
83
- end.join("\n")
84
-
85
- gemspec = Dir[root_dir + "/*.gemspec"].first || raise("No gemspec found in directory: #{root_dir}")
86
- gemspec = File.expand_path(gemspec)
87
- contents = File.read(gemspec)
88
- new_contents = contents.sub(/(\#--BEGIN_ADDON_GEM_DEPENDENCIES--\#)\s*.*(^.*\#--END_ADDON_GEM_DEPENDENCIES--\#)/mx) do
89
- "#{$1}\n#{deps_str}\n#{$2}"
90
- end
91
-
92
- File.write(gemspec, new_contents)
93
- puts "Updated #{gemspec}"
94
- puts new_contents
95
- end
96
- end
97
- end
@@ -1,181 +0,0 @@
1
- require 'pathname'
2
-
3
- module Yap
4
- class World
5
- module UserAddons
6
- end
7
-
8
- module AddonMethods
9
- module ClassMethods
10
- def load_addon
11
- # no-op, override in subclass if you need to do anything special
12
- # when your addon is first loaded when the shell starts
13
- end
14
-
15
- def addon_name
16
- @addon_name ||= self.name.split(/::/).last.scan(/[A-Z][^A-Z]+/).map(&:downcase).reject{ |f| f == "addon" }.join("_").to_sym
17
- end
18
-
19
- def debug_log(msg)
20
- Treefell['addons'].puts "addon=#{addon_name} #{msg}"
21
- end
22
-
23
- def require(name)
24
- Treefell['shell'].puts "addon is requiring: #{name}"
25
- directory = File.dirname caller[0].split(':').first
26
- lib_path = File.join directory, "lib"
27
- support_file = File.join lib_path, "#{name}.rb"
28
- namespace = self.name.split('::').reduce(Object) do |context,n|
29
- o = context.const_get(n)
30
- break o if o.is_a?(Namespace)
31
- o
32
- end
33
- if File.exists?(support_file) && namespace
34
- Treefell['shell'].puts "#{name} is found in addon, loading #{support_file} in context of #{namespace}"
35
- namespace.module_eval IO.read(support_file), support_file, lineno=1
36
- else
37
- Treefell['shell'].puts "#{name} not found in addon, falling back to super"
38
- super(name)
39
- end
40
- end
41
- end
42
-
43
- module InstanceMethods
44
- def addon_name
45
- @addon_name ||= self.class.addon_name
46
- end
47
-
48
- def debug_log(msg)
49
- self.class.debug_log(msg)
50
- end
51
- end
52
- end
53
-
54
- module Namespace
55
- end
56
-
57
- class Addon
58
- extend AddonMethods::ClassMethods
59
- include AddonMethods::InstanceMethods
60
- end
61
-
62
- module Addons
63
- def self.syntax_ok?(file)
64
- `ruby -c #{file}`
65
- ($?.exitstatus == 0).tap do |result|
66
- Treefell['shell'].puts "is syntax ok?(#{file.inspect}) #{result}"
67
- end
68
- end
69
-
70
- def self.load_rcfiles(files)
71
- Treefell['shell'].puts %|searching for rcfiles:\n * #{files.join("\n * ")}|
72
- files.map do |file|
73
- if File.exists?(file)
74
- Treefell['shell'].puts "rcfile #{file} found, loading."
75
- RcFile.new file
76
- else
77
- Treefell['shell'].puts "rcfile #{file} not found, skipping."
78
- end
79
- end.flatten.compact
80
- end
81
-
82
- def self.load_directories(search_paths)
83
- Treefell['shell'].puts %|searching for addons in:\n * #{search_paths.join("\n * ")}|
84
- search_paths.map do |directory|
85
- Dir["#{directory}/*"].map do |d|
86
- if File.directory?(d)
87
- Treefell['shell'].puts %|addon found: #{d}|
88
- load_directory(d).map(&:new)
89
- else
90
- Treefell['shell'].puts %|file found in add-on search path, skipping.|
91
- nil
92
- end
93
- end
94
- end.flatten.compact
95
- end
96
-
97
- class RcFile < Addon
98
- attr_reader :file
99
-
100
- def initialize(file)
101
- @file = File.expand_path(file)
102
- end
103
-
104
- def initialize_world(world)
105
- Treefell['shell'].puts "initializing rcfile: #{file}"
106
- world.instance_eval File.read(@file), @file
107
- end
108
- end
109
-
110
- def self.load_directory(directory)
111
- directory = File.expand_path(directory)
112
- Treefell['shell'].puts "loading addon from directory: #{directory}"
113
- namespace = File.basename(directory).
114
- split(/[_-]/).
115
- map(&:capitalize).join
116
- namespace = "#{namespace}Addon"
117
-
118
- if Yap::World::UserAddons.const_defined?(namespace)
119
- raise LoadError, "#{namespace} is already defined! Failed loading #{file}"
120
- end
121
-
122
- # Create a wrapper module for every add-on. This is to eliminate
123
- # namespace collision.
124
- addon_module = Module.new do
125
- extend Namespace
126
- extend AddonMethods::ClassMethods
127
- const_set :Addon, Addon
128
- end
129
-
130
- Yap::World::UserAddons.const_set namespace, addon_module
131
- Treefell['shell'].puts "creating addon namespace: Yap::World::UserAddons::#{namespace}"
132
-
133
- lib_path = File.join directory, "lib"
134
- Treefell['shell'].puts "prepending addon path to $LOAD_PATH: #{lib_path}"
135
- $LOAD_PATH.unshift lib_path
136
-
137
- gemfiles = Dir["#{directory}/Gemfile"]
138
- Treefell['shell'].puts "looking for Gemfile in #{namespace} addon directory: #{directory}"
139
- if gemfiles.any?
140
- gemfiles.each do |gemfile|
141
- Treefell['shell'].puts "loading #{gemfile} for addon"
142
- eval File.read(gemfile)
143
- end
144
- else
145
- Treefell['shell'].puts "No Gemfile found for #{namespace} addon"
146
- end
147
-
148
- Dir["#{directory}/*.rb"].map do |addon_file|
149
- load_file(addon_file, namespace:namespace, dir:directory, addon_module:addon_module)
150
- end
151
- ensure
152
- if lib_path
153
- Treefell['shell'].puts "Removing addon #{lib_path} path from $LOAD_PATH"
154
- $LOAD_PATH.delete(lib_path)
155
- end
156
- end
157
-
158
- def self.load_file(file, dir:, namespace:, addon_module:)
159
- Treefell['shell'].puts "loading #{namespace} addon file: #{file}"
160
- klass_name = file.sub(dir, "").
161
- sub(/^#{Regexp.escape(File::Separator)}/, "").
162
- sub(File.extname(file.to_s), "").
163
- split(File::Separator).
164
- map{ |m| m.split(/[_-]/).map(&:capitalize).join }.
165
- join("::")
166
-
167
- addon_module.module_eval IO.read(file), file, lineno=1
168
-
169
- klass_name.split("::").reduce(addon_module) do |ns,name|
170
- if ns.const_defined?(name)
171
- ns.const_get(name)
172
- else
173
- raise("Did not find #{klass_name} in #{file}")
174
- end
175
- end.tap do |loaded_addon|
176
- Treefell['shell'].puts "loaded #{File.dirname(file)} as #{loaded_addon.inspect}"
177
- end
178
- end
179
- end
180
- end
181
- end