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.
- 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
|