sbraford-go 0.1

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.
@@ -0,0 +1,6 @@
1
+ === 0.1 / 2008-10-04
2
+
3
+ * 1 major enhancement
4
+
5
+ * Rough draft of the initial concept
6
+
@@ -0,0 +1,20 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/go
6
+ lib/go.rb
7
+ go.gemspec
8
+ lib/go/application.rb
9
+ lib/go/extensions.rb
10
+ lib/go/installer.rb
11
+ lib/go/plugin.rb
12
+ lib/go/recursive_http_fetcher.rb
13
+ lib/plugins/hello.rb
14
+ test/fixtures/plugins/hello.rb
15
+ test/fixtures/plugins/palace/party_palace.rb
16
+ test/fixtures/plugins/panda.rb
17
+ test/fixtures/plugins/panda_party.rb
18
+ test/fixtures/plugins/todo.rb
19
+ test/fixtures/reserved/commands.rb
20
+ test/test_go.rb
@@ -0,0 +1,64 @@
1
+ = go
2
+
3
+ * Extensible command-line tool for ninjas, pirates & pandas. (http://github.com/sbraford/go/tree)
4
+
5
+ == DESCRIPTION:
6
+
7
+ Provides a command-line tool "go" which can then be extended by adding plugins that others
8
+ have created, or that you have made yourself.
9
+
10
+ Usage:
11
+
12
+ go <command> <options>
13
+
14
+ Example:
15
+
16
+ go twitter "tinkering with the Go gem"
17
+ go locate files containing "panda party"
18
+ go order dominos --size=large
19
+
20
+ == FEATURES/PROBLEMS:
21
+
22
+ * Go is still in an early alpha development stage
23
+
24
+ == TODO
25
+
26
+ * Figure out how to easily create/distribute go commands (plugins)
27
+ * Figure out the best way to share a go config across multiple machines (via git somehow, perhaps)
28
+
29
+ == REQUIREMENTS:
30
+
31
+ * none other than the gem dependencies for the go gem
32
+
33
+ == INSTALL:
34
+
35
+ First add GitHub as a source if you haven't already:
36
+ * gem sources -a http://gems.github.com
37
+
38
+ Install the gem via the GitHub gem repository:
39
+ * sudo gem install sbraford-go
40
+
41
+ == LICENSE:
42
+
43
+ (The MIT License)
44
+
45
+ Copyright (c) 2008 Shanti A. Braford
46
+
47
+ Permission is hereby granted, free of charge, to any person obtaining
48
+ a copy of this software and associated documentation files (the
49
+ 'Software'), to deal in the Software without restriction, including
50
+ without limitation the rights to use, copy, modify, merge, publish,
51
+ distribute, sublicense, and/or sell copies of the Software, and to
52
+ permit persons to whom the Software is furnished to do so, subject to
53
+ the following conditions:
54
+
55
+ The above copyright notice and this permission notice shall be
56
+ included in all copies or substantial portions of the Software.
57
+
58
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
59
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
60
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
61
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
62
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
63
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
64
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,16 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/go.rb'
6
+
7
+ Hoe.new('go', Go::VERSION) do |p|
8
+ # p.rubyforge_name = 'gox' # if different than lowercase project name
9
+ p.summary = 'Extensible command-line tool for ninjas, pirates & pandas'
10
+ p.url = 'http://github.com/sbraford/go/tree'
11
+ p.developer('Shanti A. Braford', 'shantibraford@gmail.com')
12
+ p.remote_rdoc_dir = ''
13
+ p.extra_deps << ['cooloptions', '>= 1.1.1']
14
+ end
15
+
16
+ # vim: syntax=Ruby
data/bin/go ADDED
@@ -0,0 +1,8 @@
1
+ require File.dirname(__FILE__) + '/../lib/go.rb'
2
+ begin
3
+ require 'go'
4
+ rescue LoadError
5
+ require 'rubygems'
6
+ require 'go'
7
+ end
8
+ Go.application.run
@@ -0,0 +1,31 @@
1
+ $:.unshift(File.dirname(__FILE__) + "/go/")
2
+
3
+ # System gems
4
+ require 'rubygems'
5
+ require 'cooloptions'
6
+
7
+ # Go Core classes
8
+ require 'application'
9
+ require 'plugin'
10
+ require 'installer'
11
+ require 'extensions'
12
+ require 'recursive_http_fetcher'
13
+
14
+ # Ruby libs
15
+ require 'open-uri'
16
+ require 'uri'
17
+
18
+ module Go
19
+ VERSION = '0.1' unless defined?(VERSION)
20
+
21
+ # Current Rake Application
22
+ def self.application
23
+ @application ||= Go::Application.new(ARGV)
24
+ end
25
+
26
+ # Set the current Rake application object.
27
+ def self.application=(app)
28
+ @application = app
29
+ end
30
+ end
31
+
@@ -0,0 +1,281 @@
1
+ module Go
2
+
3
+ class Application
4
+ # class << self
5
+ # end
6
+ attr_reader :args, :plugin_commands, :sorted_plugins, :options
7
+ attr_accessor :plugin_path
8
+
9
+ ReservedCommands = %w(commands edit generate help list setup install plugin)
10
+
11
+ # Initializes a new Go::Application object - should always be called via a Singleton, e.g.
12
+ # Go.application.run
13
+ def initialize(args = ARGV)
14
+ @args = args
15
+ @options = OpenStruct.new
16
+ end
17
+
18
+ # Main Go Application entry point.
19
+ # * Parses command-line options and calls methods accordingly
20
+ def run
21
+ @options = CoolOptions.parse!("[options] (commands|edit|generate|help|list|setup)") do |o|
22
+ o.desc "Go - the Extensible command-line tool for ninjas, pirates & pandas"
23
+ o.on "(v)erbose", "Turn on verbose mode", false
24
+ o.on "(f)orce", "Force (the action)", false
25
+ o.after do |r|
26
+ r.config_path = self.default_config_path
27
+ if !File.exist?(r.config_path)
28
+ setup
29
+ exit
30
+ end
31
+ r.full_command = @args.join(' ')
32
+ r.params = @args.slice(1, @args.size)
33
+ r.action = @args.empty? ? 'commands' : @args[0]
34
+ end
35
+ end
36
+
37
+ case @options.action
38
+ when 'commands', 'list'
39
+ list_commands
40
+ when 'install'
41
+ install_plugin
42
+ when 'plugin'
43
+ case @options.params.first
44
+ when 'list'
45
+ list_commands
46
+ when 'install'
47
+ @option.params.shift
48
+ install_plugin
49
+ else
50
+ puts "Invalid command. Call go without any params for a list of valid commands."
51
+ list_commands
52
+ end
53
+ when 'generate'
54
+ generate
55
+ when 'setup'
56
+ setup
57
+ when 'edit'
58
+ edit
59
+ when 'help'
60
+ help
61
+ else
62
+ run_plugin_command
63
+ end
64
+
65
+ end
66
+
67
+ def install_plugin
68
+ if @options.params.empty?
69
+ raise "Please specify a URL from which to install the plugin, e.g.: go install http://gist.github.com/14933"
70
+ end
71
+ installer = Installer.new(@options.params.first, self)
72
+ installer.install
73
+ end
74
+
75
+ def run_plugin_command
76
+ init_plugins
77
+ plugin_pair = nil
78
+ # They may have passed "panda party palace", "panda party", or "panda"
79
+ # We want to give the plugin with the most words -> highest priority
80
+ @args.size.downto(1) do |i|
81
+ cmd = @args.slice(0, i).join(' ')
82
+ plugin_pair = @sorted_plugins.detect {|pair| pair.first == cmd}
83
+ break if plugin_pair
84
+ end
85
+ if plugin_pair
86
+ klass = plugin_pair[1]
87
+ plugin = klass.new(@options)
88
+ plugin.run
89
+ else
90
+ puts "No command found for action: #{@options.action}" unless test_env?
91
+ end
92
+ plugin_pair
93
+ end
94
+
95
+ def list_commands
96
+ justify = 40
97
+ init_plugins
98
+ puts "\n Builtin Go commands\n\n"
99
+ show_command('install', "install <plugin_url>")
100
+ show_command('list', "list")
101
+ show_command('setup', "setup")
102
+ puts "\n Plugin commands\n "
103
+ @sorted_plugins.each do |pair|
104
+ command, klass = *pair
105
+ usage = klass.usage_raw ? klass.usage_raw : command
106
+ show_command(command, usage)
107
+ end
108
+ puts "\n"
109
+ end
110
+
111
+ def generate
112
+ puts "TODO: generate a skeleton plugin via this method"
113
+ end
114
+
115
+ # Creates the default config file in: ~/.goconfig
116
+ def setup
117
+ File.open(self.default_config_path, 'w') do |f|
118
+ f.puts self.sample_config
119
+ end
120
+
121
+ FileUtils.mkdir_p(self.go_dir) if !File.exist?(self.go_dir)
122
+
123
+ install_default_plugins
124
+
125
+ puts setup_txt
126
+ end
127
+
128
+ # Edit the config file (using the system editor)
129
+ def edit
130
+ editor = ENV['editor'] || 'vi'
131
+ system "#{editor} #{self.default_config_path}"
132
+ end
133
+
134
+ # Displays the help text
135
+ def help
136
+ puts help_txt
137
+ end
138
+
139
+ def init_plugins!
140
+ init_plugins
141
+ end
142
+
143
+ def clear_plugins!
144
+ @plugin_commands, @sorted_plugins = nil, nil
145
+ end
146
+
147
+ def go_dir
148
+ @plugin_path || File.join(ENV['HOME'], '.go')
149
+ end
150
+
151
+ protected
152
+
153
+ def show_command(command_name, usage, justify = 40)
154
+ puts " #{command_name.ljust(justify)}\t# go #{usage}"
155
+ end
156
+
157
+ def init_plugins
158
+ contains = Dir.new(go_dir).entries
159
+ contains.delete("."); contains.delete("..")
160
+ contains.each do |entry|
161
+ path = File.join(go_dir, entry)
162
+ if File.directory?(path)
163
+ # Require all .rb files in this dir
164
+ subfiles = Dir.new(path).entries
165
+ subfiles.delete("."); subfiles.delete("..")
166
+ subfiles.each do |sub|
167
+ sub_path = File.join(path, sub)
168
+ if !File.directory?(sub_path) && File.extname(sub_path) == '.rb'
169
+ require sub_path
170
+ end
171
+ end
172
+ elsif File.extname(path) == '.rb'
173
+ # Require it if it's a ruby file
174
+ require path
175
+ end
176
+ end
177
+ init_plugin_commands
178
+ end
179
+
180
+ def init_plugin_commands
181
+ plugins = Go::Plugin.subclasses
182
+ puts "\n plugin classes = #{plugins.inspect}" if @options.verbose
183
+ @plugin_commands = {}
184
+ plugins.each do |p|
185
+ command = p.command.to_s
186
+ puts " Plugin: #{p} :: #{command}" if @options.verbose
187
+ if ReservedCommands.include?(command)
188
+ puts "WARNING: #{p} attempted to init plugin with reserved command '#{command}' (plugin *not* loaded)" unless test_env?
189
+ else
190
+ @plugin_commands[command] = p
191
+ end
192
+ end
193
+ @sorted_plugins = sort_plugins(@plugin_commands)
194
+ end
195
+
196
+ def sort_plugins(plugin_commands)
197
+ # Now sort 'em - alphabetically first, thgen with higher priority (more words in the command string)
198
+ # plugins coming next.
199
+ sorted_plugins = []
200
+ plugin_commands.each do |command, klass|
201
+ sorted_plugins << [command, klass]
202
+ end
203
+ sorted_plugins.sort! do |x,y|
204
+ cmd_x, cmd_y = x.first, y.first
205
+ cmd_x_size = cmd_x.split(' ').size
206
+ cmd_y_size = cmd_y.split(' ').size
207
+ if (cmd_x_size == cmd_y_size) && cmd_x_size == 1
208
+ # Single word command (both), simply sort alphabetically
209
+ (cmd_x <=> cmd_y)
210
+ else
211
+ # One of the commands has multiple words, install the mutli-word command ahead of the other one
212
+ # if there is a sub-match
213
+ sub_cmd_x = cmd_x.split(' ')[0]
214
+ sub_cmd_y = cmd_y.split(' ')[0]
215
+ if sub_cmd_x == sub_cmd_y
216
+ # e.g. 'panda' and 'panda party'
217
+ cmd_y_size <=> cmd_x_size
218
+ else
219
+ # Otherwise sort alphabetically
220
+ cmd_x <=> cmd_y
221
+ end
222
+ end
223
+ end
224
+ sorted_plugins
225
+ end
226
+
227
+ def default_config_path
228
+ File.join(ENV['HOME'], '.goconfig')
229
+ end
230
+
231
+ def install_default_plugins
232
+ gem_plugin_path = File.join(File.dirname(__FILE__), '..', 'plugins')
233
+ cmd = "cp -R #{gem_plugin_path}/* #{go_dir}"
234
+ system(cmd)
235
+ end
236
+
237
+ def help_txt
238
+ txt = <<EOF
239
+ To setup the initial config file, execute:
240
+
241
+ go setup
242
+
243
+ Edit go config using your system edtior:
244
+
245
+ go edit
246
+
247
+ EOF
248
+ end
249
+
250
+ def setup_txt
251
+ txt = <<EOF
252
+
253
+ Default config file has been created in:
254
+
255
+ ~/.goconfig
256
+
257
+ This will be the primary entry-point for editing any config options required by Go plugins.
258
+
259
+ Default plugins have been placed in the go plugin directory:
260
+
261
+ ~/.go
262
+
263
+ To see a list of available go commands, run go without any arguments:
264
+
265
+ go
266
+
267
+ EOF
268
+ end
269
+
270
+ def sample_config
271
+ "name: Change Me"
272
+ end
273
+
274
+ # Suppress noise when testing
275
+ def test_env?
276
+ defined?(Test::Unit::TestCase)
277
+ end
278
+
279
+ end
280
+
281
+ end
@@ -0,0 +1,29 @@
1
+ class Time
2
+ # Prints the date like: Monday, June 10 of 2006 at 10:57AM
3
+ def pretty_print
4
+ return self.strftime("%A, %B %d of %Y at %I:%M %p")
5
+ end
6
+ end
7
+
8
+ class String
9
+ def to_underscore #(klass)
10
+ self.dup.gsub(/::/, '/').
11
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
12
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
13
+ tr("-", "_").
14
+ downcase
15
+ end
16
+ end
17
+
18
+
19
+ class Module
20
+ def subclasses
21
+ classes = []
22
+ ObjectSpace.each_object do |klass|
23
+ next unless Module === klass
24
+ classes << klass if self > klass
25
+ end
26
+ classes
27
+ end
28
+ end
29
+
@@ -0,0 +1,90 @@
1
+ module Go
2
+
3
+ # Base class for Go plugins
4
+ class Installer
5
+
6
+ def initialize(url, app)
7
+ @url = raw_url(url)
8
+ @app = app
9
+ end
10
+
11
+ def install
12
+ begin
13
+ content = open(@url).read
14
+ rescue
15
+ raise "Could not read via open-uri from remote URL: #{@url}"
16
+ end
17
+ klass_name = nil
18
+ # uglier than regexes? rather this than "2 problrems"-style regex
19
+ klass_name = content.split('class ')[1].split(' ')[0] rescue nil
20
+ if klass_name
21
+ install_single(klass_name, content)
22
+ else
23
+ install_dir
24
+ end
25
+ end
26
+
27
+ protected
28
+
29
+ def install_single(klass_name, content)
30
+ puts "Installing plugin: #{klass_name}"
31
+ filename = "#{klass_name.to_underscore}.rb"
32
+ filepath = File.join(@app.go_dir, filename)
33
+ if File.exist?(filepath) && !@app.options.force
34
+ puts "File already exists: #{filepath}"
35
+ puts "Epic FAIL: Cannot install new plugin #{klass_name} from url: #{@url}"; return
36
+ else klass_name
37
+ File.open(filepath, 'w') { |f| f.puts(content) }
38
+ end
39
+ if File.exist?(filepath)
40
+ puts "#{klass_name} Plugin installed to: #{filepath}"
41
+ end
42
+ end
43
+
44
+ def install_dir
45
+ guess_name(@url)
46
+ puts "Installing plugin: #{@name}"
47
+ # CASE: directory tree to install
48
+ plugin_path = File.join(@app.go_dir, @name)
49
+ FileUtils.mkdir_p(plugin_path)
50
+ Dir.chdir(plugin_path) do
51
+ puts "fetching from '#{@url}'"
52
+ fetcher = RecursiveHTTPFetcher.new(@url, -1)
53
+ #fetcher.quiet = true unless @app.options.verbose
54
+ fetcher.fetch
55
+ end
56
+ puts "#{@name} Plugin installed to: #{plugin_path}"
57
+ end
58
+
59
+ # This method's code (c) Ryan Tomayko from the railties gem
60
+ def guess_name(url)
61
+ @name = File.basename(url)
62
+ if @name == 'trunk' || @name.empty?
63
+ @name = File.basename(File.dirname(url))
64
+ end
65
+ @name.gsub!(/\.git$/, '') if @name =~ /\.git$/
66
+ end
67
+
68
+ def raw_url(url)
69
+ uri = URI.parse(url)
70
+ case uri.host
71
+ when 'gist.github.com'
72
+ # We want the raw URL unless that was passed, e.g. :
73
+ # http://gist.github.com/raw/14933/8b960e3a0474ed8e72df2516dfd6066a73d75a1c
74
+ return url if url.include?('/raw/')
75
+ content = open(url).read rescue "Could not read: #{url}"
76
+ begin
77
+ "http://gist.github.com/raw/" + content.split("href=\"/raw/")[1].split('"')[0]
78
+ rescue
79
+ nil
80
+ end
81
+ when 'pastie.org', 'www.pastie.org'
82
+ return url if url.include?('.txt')
83
+ return "#{url}.txt"
84
+ else
85
+ url
86
+ end
87
+ end
88
+ end
89
+
90
+ end
@@ -0,0 +1,49 @@
1
+ module Go
2
+
3
+ # Base class for Go plugins
4
+ class Plugin
5
+
6
+ class << self
7
+ attr_accessor :plugin_list
8
+ attr_accessor :command, :usage
9
+
10
+ def call_with(command)
11
+ @command = command
12
+ end
13
+
14
+ def usage_raw
15
+ @usage
16
+ end
17
+
18
+ # Ugly hack. Allows usage to be set or called via the same method, without
19
+ # 0 for 1 argument errors.
20
+ def usage(usage = nil)
21
+ if usage.nil?
22
+ "Usage: go #{@usage}"
23
+ else
24
+ @usage = usage
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ attr_accessor :options #, :command
31
+
32
+ # Initializes a new Go::Plugin class
33
+ # * Expects an OpenStruct returned from a CoolOptions.parse!(...) call
34
+ def initialize(options)
35
+ @options = options
36
+ # @config_file = options.config_path
37
+ # @verbose = options.verbose || false
38
+ #
39
+ # yml = File.open(@config_file)
40
+ # @config = YAML.load(yml)
41
+
42
+ end
43
+
44
+ protected
45
+
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,72 @@
1
+ # Source via Rails (railties) - included here to avoid adding an extra dependency of railties to the gem.
2
+ #
3
+ # This is Free Software, copyright 2005 by Ryan Tomayko (rtomayko@gmail.com)
4
+ # and is licensed MIT: (http://www.opensource.org/licenses/mit-license.php)
5
+
6
+ class RecursiveHTTPFetcher
7
+ attr_accessor :quiet
8
+ def initialize(urls_to_fetch, level = 1, cwd = ".")
9
+ @level = level
10
+ @cwd = cwd
11
+ @urls_to_fetch = RUBY_VERSION >= '1.9' ? urls_to_fetch.lines : urls_to_fetch.to_a
12
+ @quiet = false
13
+ end
14
+
15
+ def ls
16
+ @urls_to_fetch.collect do |url|
17
+ if url =~ /^svn(\+ssh)?:\/\/.*/
18
+ `svn ls #{url}`.split("\n").map {|entry| "/#{entry}"} rescue nil
19
+ else
20
+ open(url) do |stream|
21
+ links("", stream.read)
22
+ end rescue nil
23
+ end
24
+ end.flatten
25
+ end
26
+
27
+ def push_d(dir)
28
+ @cwd = File.join(@cwd, dir)
29
+ FileUtils.mkdir_p(@cwd)
30
+ end
31
+
32
+ def pop_d
33
+ @cwd = File.dirname(@cwd)
34
+ end
35
+
36
+ def links(base_url, contents)
37
+ links = []
38
+ contents.scan(/href\s*=\s*\"*[^\">]*/i) do |link|
39
+ link = link.sub(/href="/i, "")
40
+ next if link =~ /svnindex.xsl$/
41
+ next if link =~ /^(\w*:|)\/\// || link =~ /^\./
42
+ links << File.join(base_url, link)
43
+ end
44
+ links
45
+ end
46
+
47
+ def download(link)
48
+ puts "+ #{File.join(@cwd, File.basename(link))}" unless @quiet
49
+ open(link) do |stream|
50
+ File.open(File.join(@cwd, File.basename(link)), "wb") do |file|
51
+ file.write(stream.read)
52
+ end
53
+ end
54
+ end
55
+
56
+ def fetch(links = @urls_to_fetch)
57
+ links.each do |l|
58
+ (l =~ /\/$/ || links == @urls_to_fetch) ? fetch_dir(l) : download(l)
59
+ end
60
+ end
61
+
62
+ def fetch_dir(url)
63
+ @level += 1
64
+ push_d(File.basename(url)) if @level > 0
65
+ open(url) do |stream|
66
+ contents = stream.read
67
+ fetch(links(url, contents))
68
+ end
69
+ pop_d if @level > 0
70
+ @level -= 1
71
+ end
72
+ end
@@ -0,0 +1,9 @@
1
+ class Hello < Go::Plugin
2
+ call_with 'hello'
3
+ usage 'hello'
4
+
5
+ def run
6
+ puts "hello, world!"
7
+ end
8
+
9
+ end
@@ -0,0 +1,8 @@
1
+ class Hello < Go::Plugin
2
+ call_with 'hello'
3
+
4
+ def run
5
+ puts "hello, world!"
6
+ end
7
+
8
+ end
@@ -0,0 +1,7 @@
1
+ class PartyPalace < Go::Plugin
2
+ call_with 'panda party palace'
3
+
4
+ def run
5
+ puts "It's Party-Time!"
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ class Panda < Go::Plugin
2
+ call_with :panda
3
+ usage 'panda "some text to say"'
4
+
5
+ def run
6
+ if @options.params.empty?
7
+ puts "Panda is speechless."
8
+ else
9
+ puts "Panda says, \"#{@options.params.first}\""
10
+ system("say #{@options.params.first}")
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,40 @@
1
+ class PandaParty < Go::Plugin
2
+ call_with 'panda party'
3
+
4
+ def run
5
+ puts pandas
6
+ end
7
+
8
+ def pandas
9
+ p = <<EOF
10
+
11
+ ooo
12
+ o$$$$$$ o$$$$$o ooo
13
+ $$$$$$"""""""""$o$$$$$$$$oo"""""""o o$$$$$$o
14
+ ""$ $$$$$" $$$$$$$$$
15
+ $ $ $$$$$$$
16
+ o ooooo "$$$"
17
+ o $$$o$$ o$$o o" ooo "$
18
+ $ """ "$ o$$ o o$" $ $$"$$$
19
+ o ooo ""$" o"$$" "$$$$$ $
20
+ oo$$$"" "o "$"" " o """ oo"
21
+ o$$$$o """"oo$$$$oo"$ $"$" o o"$$$$
22
+ o$$$$$$$$"$$$$$$$$$$$$$$$$$ $$$o$"""" "$$$
23
+ $$$$$$$$$o$$$$$$$$$$$$$$$$$o$$$$$$$o $$$$
24
+ $$$$$$$$$$$$$$$$$$$$$$$$$$ $$$$$$$$$$o oo$$$$$$$$o
25
+ o$$$$$$$$$$$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$oo$$$$$$$$$$$$
26
+ o$$$$$o"$$$$" "$$$"" $$$$$$$$$$$$$$o"$$$$$$$$$""o
27
+ o$$$$$$$ "$$$$$$$$$$$$$$o"$$$$$" $$o ooo
28
+ $$$$$$$$ $ "$$$$$$$$$$$$ $$$$$o$$$$$
29
+ $$$$$$$$o ooo$$$$$$$ """""""$" $$$$$$$$$$$"
30
+ $$$$$$$$ o$$$$$$$$$$$$$$$$$$$$o oo$$$$$$$$$o o$$$$$ $$$$$$$$$$$
31
+ $$$$$$$"o$$$$$$$$$$$$$$$$$$$$$$$oo$$$$$$$$$$$$$$$$$$$$$$$$$o$$$$$$$$"
32
+ o$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"$$$$$
33
+ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"""
34
+ $$$$$$$$ $$$$$$$$$$$$$$$$$$$$$$$$" "$$$$$$$$$$$$$$$$$$$$$$$$$$$$
35
+ "$$$$"" $$$$$$$$"""$$$$$$"""" "$$$$$$$$$$$$$$$$$""$$$$$"
36
+ $$$$$" """"$$$$$""
37
+
38
+ EOF
39
+ end
40
+ end
@@ -0,0 +1,18 @@
1
+ class Todo < Go::Plugin
2
+ call_with :todo
3
+ usage 'todo <path>'
4
+
5
+ def run
6
+ if @options.params.empty?
7
+ puts self.class.usage; return
8
+ end
9
+ path = @options.params.first
10
+ if !File.exist?(path)
11
+ puts "Path does not exist: #{path}"; return
12
+ end
13
+ cmd = "find #{path} -name \"*\" | xargs grep -C1 'TODO'"
14
+ r = IO.popen(cmd)
15
+ puts r.read
16
+ end
17
+
18
+ end
@@ -0,0 +1,9 @@
1
+ # This plugin should not get loaded -- it's attempting to register a command over a reserved Go command
2
+ class Commands < Go::Plugin
3
+ call_with :commands
4
+
5
+ def run
6
+ puts "OOOPS - I should never be run, because I conflict with a builtin go command."
7
+ end
8
+
9
+ end
@@ -0,0 +1,48 @@
1
+ require(File.join(File.dirname(__FILE__), '..', 'lib', 'go'))
2
+ require 'test/unit'
3
+ require 'set'
4
+
5
+ class TestGo < Test::Unit::TestCase
6
+
7
+ def test_fixture_plugins_loaded_as_subclasses
8
+ @app = Go::Application.new(['hello'])
9
+ @app.plugin_path = File.join(File.dirname(__FILE__), 'fixtures', 'plugins')
10
+ @app.instance_eval('init_plugins')
11
+ assert_equal [Hello, Panda, PandaParty, PartyPalace, Todo].to_set, Go::Plugin.subclasses.to_set
12
+ end
13
+
14
+ def test_plugin_with_reserved_command_should_not_get_included_in_command_tree
15
+ @app = Go::Application.new([])
16
+ @app.plugin_path = File.join(File.dirname(__FILE__), 'fixtures', 'reserved')
17
+ @app.instance_eval('init_plugins')
18
+ assert !@app.plugin_commands.keys.include?('commands')
19
+ end
20
+
21
+ def test_command_with_most_required_params_has_highest_priority
22
+ @app = Go::Application.new(['panda party palace'])
23
+ @app.plugin_path = File.join(File.dirname(__FILE__), 'fixtures', 'plugins')
24
+ @app.instance_eval('init_plugins')
25
+ assert_equal ["panda party palace", PartyPalace], @app.run
26
+ end
27
+
28
+ def test_command_with_next_most_params_has_next_highest_priority
29
+ @app = Go::Application.new(['panda party'])
30
+ @app.plugin_path = File.join(File.dirname(__FILE__), 'fixtures', 'plugins')
31
+ assert_equal ["panda party", PandaParty], @app.run
32
+ end
33
+
34
+ def pending_test_single_word_command_with_params
35
+ @app = Go::Application.new(['panda', 'this app makes me feel sexy'])
36
+ @app.plugin_path = File.join(File.dirname(__FILE__), 'fixtures', 'plugins')
37
+ @app.init_plugins!
38
+ assert_equal ["panda", Panda], @app.run
39
+ end
40
+
41
+ ## Installer tests
42
+ def test_installer_parse_pastie_txt
43
+ app = Go::Application.new([])
44
+ app.plugin_path = File.join(File.dirname(__FILE__), 'fixtures', 'reserved')
45
+ inst = Go::Installer.new('http://pastie.org/285599.txt', app)
46
+ assert_equal 'http://pastie.org/285599.txt', inst.instance_eval('@url') #inst.send(:url)
47
+ end
48
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sbraford-go
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Shanti A. Braford
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-10-05 00:00:00 -07:00
13
+ default_executable: go
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: cooloptions
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.1.1
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: hoe
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: 1.7.0
32
+ version:
33
+ description: Provides a command-line tool "go" which can then be extended by adding plugins that others have created, or that you have made yourself.
34
+ email:
35
+ - shantibraford@gmail.com
36
+ executables:
37
+ - go
38
+ extensions: []
39
+
40
+ extra_rdoc_files:
41
+ - History.txt
42
+ - Manifest.txt
43
+ - README.txt
44
+ files:
45
+ - History.txt
46
+ - Manifest.txt
47
+ - README.txt
48
+ - Rakefile
49
+ - bin/go
50
+ - lib/go.rb
51
+ - lib/go/application.rb
52
+ - lib/go/extensions.rb
53
+ - lib/go/installer.rb
54
+ - lib/go/plugin.rb
55
+ - lib/go/recursive_http_fetcher.rb
56
+ - test/test_go.rb
57
+ - test/fixtures/plugins/hello.rb
58
+ - test/fixtures/plugins/panda.rb
59
+ - test/fixtures/plugins/panda_party.rb
60
+ - test/fixtures/plugins/todo.rb
61
+ - test/fixtures/plugins/palace/party_palace.rb
62
+ - test/fixtures/reserved/commands.rb
63
+ - lib/plugins/hello.rb
64
+ has_rdoc: true
65
+ homepage: http://github.com/sbraford/go/tree
66
+ post_install_message:
67
+ rdoc_options:
68
+ - --main
69
+ - README.txt
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ version:
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: "0"
83
+ version:
84
+ requirements: []
85
+
86
+ rubyforge_project: go
87
+ rubygems_version: 1.2.0
88
+ signing_key:
89
+ specification_version: 2
90
+ summary: Extensible command-line tool for ninjas, pirates & pandas
91
+ test_files:
92
+ - test/test_go.rb
93
+ - test/fixtures/plugins/hello.rb
94
+ - test/fixtures/plugins/panda.rb
95
+ - test/fixtures/plugins/panda_party.rb
96
+ - test/fixtures/plugins/todo.rb
97
+ - test/fixtures/plugins/palace/party_palace.rb
98
+ - test/fixtures/reserved/commands.rb