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.
- checksums.yaml +4 -4
- data/Gemfile.travis.lock +104 -0
- data/bin/yap +6 -0
- data/bin/yap-dev +37 -0
- data/lib/yap.rb +29 -39
- data/lib/yap/addon.rb +24 -0
- data/lib/yap/addon/base.rb +52 -0
- data/lib/yap/addon/export_as.rb +12 -0
- data/lib/yap/addon/loader.rb +84 -0
- data/lib/yap/addon/path.rb +56 -0
- data/lib/yap/addon/rc_file.rb +21 -0
- data/lib/yap/addon/reference.rb +22 -0
- data/lib/yap/cli.rb +4 -0
- data/lib/yap/cli/commands.rb +6 -0
- data/lib/yap/cli/commands/addon.rb +14 -0
- data/lib/yap/cli/commands/addon/disable.rb +35 -0
- data/lib/yap/cli/commands/addon/enable.rb +35 -0
- data/lib/yap/cli/commands/addon/list.rb +37 -0
- data/lib/yap/cli/commands/addon/search.rb +99 -0
- data/lib/yap/cli/commands/generate.rb +13 -0
- data/lib/yap/cli/commands/generate/addon.rb +258 -0
- data/lib/yap/cli/commands/generate/addonrb.template +22 -0
- data/lib/yap/cli/commands/generate/gemspec.template +25 -0
- data/lib/yap/cli/commands/generate/license.template +21 -0
- data/lib/yap/cli/commands/generate/rakefile.template +6 -0
- data/lib/yap/cli/commands/generate/readme.template +40 -0
- data/lib/yap/cli/options.rb +162 -0
- data/lib/yap/cli/options/addon.rb +64 -0
- data/lib/yap/cli/options/addon/disable.rb +62 -0
- data/lib/yap/cli/options/addon/enable.rb +63 -0
- data/lib/yap/cli/options/addon/list.rb +65 -0
- data/lib/yap/cli/options/addon/search.rb +76 -0
- data/lib/yap/cli/options/generate.rb +59 -0
- data/lib/yap/cli/options/generate/addon.rb +63 -0
- data/lib/yap/configuration.rb +10 -3
- data/lib/yap/gem_helper.rb +195 -0
- data/lib/yap/gem_tasks.rb +6 -0
- data/lib/yap/shell.rb +1 -1
- data/lib/yap/shell/repl.rb +1 -1
- data/lib/yap/shell/version.rb +1 -1
- data/lib/yap/world.rb +45 -7
- data/rcfiles/yaprc +90 -10
- data/spec/features/addons/generating_an_addon_spec.rb +55 -0
- data/spec/features/addons/using_an_addon_spec.rb +182 -0
- data/spec/features/aliases_spec.rb +6 -6
- data/spec/features/grouping_spec.rb +18 -18
- data/spec/features/line_editing_spec.rb +9 -1
- data/spec/features/redirection_spec.rb +12 -3
- data/spec/spec_helper.rb +21 -11
- data/spec/support/matchers/have_printed.rb +38 -0
- data/spec/support/yap_spec_dsl.rb +24 -6
- data/yap-shell.gemspec +6 -11
- metadata +51 -45
- data/addons/history/README.md +0 -16
- data/addons/history/history.rb +0 -58
- data/addons/history_search/history_search.rb +0 -197
- data/addons/keyboard_macros/keyboard_macros.rb +0 -425
- data/addons/keyboard_macros/lib/keyboard_macros/cycle.rb +0 -38
- data/addons/prompt/Gemfile +0 -1
- data/addons/prompt/right_prompt.rb +0 -17
- data/addons/prompt_updates/prompt_updates.rb +0 -28
- data/addons/tab_completion/Gemfile +0 -0
- data/addons/tab_completion/lib/tab_completion/basic_completion.rb +0 -151
- data/addons/tab_completion/lib/tab_completion/completer.rb +0 -62
- data/addons/tab_completion/lib/tab_completion/custom_completion.rb +0 -33
- data/addons/tab_completion/lib/tab_completion/dsl_methods.rb +0 -7
- data/addons/tab_completion/tab_completion.rb +0 -174
- data/lib/tasks/addons.rake +0 -97
- data/lib/yap/world/addons.rb +0 -181
data/lib/tasks/addons.rake
DELETED
@@ -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
|
data/lib/yap/world/addons.rb
DELETED
@@ -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
|