jashmenn-git-style-binaries 0.1.3
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.
- data/README.markdown +259 -0
- data/Rakefile +64 -0
- data/VERSION.yml +4 -0
- data/lib/ext/colorize.rb +199 -0
- data/lib/ext/core.rb +16 -0
- data/lib/git-style-binary/autorunner.rb +21 -0
- data/lib/git-style-binary/command.rb +196 -0
- data/lib/git-style-binary/commands/help.rb +32 -0
- data/lib/git-style-binary/helpers/name_resolver.rb +78 -0
- data/lib/git-style-binary/helpers/pager.rb +37 -0
- data/lib/git-style-binary/parser.rb +204 -0
- data/lib/git-style-binary.rb +74 -0
- data/test/fixtures/flickr +4 -0
- data/test/fixtures/flickr-download +17 -0
- data/test/fixtures/wordpress +30 -0
- data/test/fixtures/wordpress-categories +17 -0
- data/test/fixtures/wordpress-list +18 -0
- data/test/fixtures/wordpress-post +26 -0
- data/test/git-style-binary/command_test.rb +16 -0
- data/test/git_style_binary_test.rb +21 -0
- data/test/running_binaries_test.rb +185 -0
- data/test/shoulda_macros/matching_stdio.rb +13 -0
- data/test/test_helper.rb +28 -0
- metadata +98 -0
@@ -0,0 +1,196 @@
|
|
1
|
+
require 'git-style-binary'
|
2
|
+
|
3
|
+
module GitStyleBinary
|
4
|
+
def self.command(&block)
|
5
|
+
returning Command.new(:constraints => [block]) do |c|
|
6
|
+
c.name ||= (GitStyleBinary.name_of_command_being_loaded || GitStyleBinary.current_command_name)
|
7
|
+
GitStyleBinary.known_commands[c.name] = c
|
8
|
+
|
9
|
+
if !GitStyleBinary.current_command || GitStyleBinary.current_command.is_primary?
|
10
|
+
GitStyleBinary.current_command = c
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.primary(&block)
|
16
|
+
returning Primary.new(:constraints => [block]) do |c|
|
17
|
+
c.name ||= (GitStyleBinary.name_of_command_being_loaded || GitStyleBinary.current_command_name)
|
18
|
+
GitStyleBinary.known_commands[c.name] = c
|
19
|
+
|
20
|
+
GitStyleBinary.primary_command = c unless GitStyleBinary.primary_command
|
21
|
+
GitStyleBinary.current_command = c unless GitStyleBinary.current_command
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Command
|
26
|
+
class << self
|
27
|
+
def defaults
|
28
|
+
lambda do
|
29
|
+
name_desc "#{command.full_name}\#{command.short_desc ? ' - ' + command.short_desc : ''}" # eval jit
|
30
|
+
version_string = defined?(VERSION) ? VERSION : "0.0.1"
|
31
|
+
version "#{version_string} (c) #{Time.now.year}"
|
32
|
+
banner <<-EOS
|
33
|
+
#{"SYNOPSIS".colorize(:red)}
|
34
|
+
#{command.full_name.colorize(:blue)} #{all_options_string}
|
35
|
+
|
36
|
+
#{"SUBCOMMANDS".colorize(:red)}
|
37
|
+
\#{GitStyleBinary.pretty_known_subcommands.join("\n ")}
|
38
|
+
|
39
|
+
See '#{command.full_name} help COMMAND' for more information on a specific command.
|
40
|
+
EOS
|
41
|
+
|
42
|
+
opt :verbose, "verbose", :default => false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
attr_reader :constraints
|
48
|
+
attr_reader :opts
|
49
|
+
attr_accessor :name
|
50
|
+
|
51
|
+
def initialize(o={})
|
52
|
+
o.each do |k,v|
|
53
|
+
eval "@#{k.to_s}= v"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def parser
|
58
|
+
@parser ||= begin
|
59
|
+
p = Parser.new
|
60
|
+
p.command = self
|
61
|
+
p
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def constraints
|
66
|
+
@constraints ||= []
|
67
|
+
end
|
68
|
+
|
69
|
+
def run
|
70
|
+
GitStyleBinary.load_primary unless is_primary?
|
71
|
+
GitStyleBinary.load_subcommand if is_primary? && running_subcommand?
|
72
|
+
load_all_parser_constraints
|
73
|
+
@opts = process_args_with_subcmd
|
74
|
+
call_parser_run_block
|
75
|
+
self
|
76
|
+
end
|
77
|
+
|
78
|
+
def running_subcommand?
|
79
|
+
GitStyleBinary.valid_subcommand?(GitStyleBinary.current_command_name)
|
80
|
+
end
|
81
|
+
|
82
|
+
def load_all_parser_constraints
|
83
|
+
@loaded_all_parser_constraints ||= begin
|
84
|
+
load_parser_default_constraints
|
85
|
+
load_parser_primary_constraints
|
86
|
+
load_parser_local_constraints
|
87
|
+
true
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def load_parser_default_constraints
|
92
|
+
parser.consume_all([self.class.defaults])
|
93
|
+
end
|
94
|
+
|
95
|
+
def load_parser_primary_constraints
|
96
|
+
parser.consume_all(GitStyleBinary.primary_command.constraints)
|
97
|
+
end
|
98
|
+
|
99
|
+
def load_parser_local_constraints
|
100
|
+
cur = GitStyleBinary.current_command # see, why isn't 'this' current_command?
|
101
|
+
|
102
|
+
unless self.is_primary? && cur == self
|
103
|
+
# TODO TODO - the key lies in this function. figure out when you hav emore engergy
|
104
|
+
# soo UGLY. see #process_parser! unify with that method
|
105
|
+
# parser.consume_all(constraints) rescue ArgumentError
|
106
|
+
parser.consume_all(cur.constraints)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def call_parser_run_block
|
111
|
+
runs = GitStyleBinary.current_command.parser.runs
|
112
|
+
parser.runs.last.call(self) # ... not too happy with this
|
113
|
+
end
|
114
|
+
|
115
|
+
def process_args_with_subcmd(args = ARGV, *a, &b)
|
116
|
+
cmd = GitStyleBinary.current_command_name
|
117
|
+
vals = process_args(args, *a, &b)
|
118
|
+
parser.leftovers.shift if parser.leftovers[0] == cmd
|
119
|
+
vals
|
120
|
+
end
|
121
|
+
|
122
|
+
# TOOooootally ugly! why? bc load_parser_local_constraints doesn't work
|
123
|
+
# when loading the indivdual commands because it depends on
|
124
|
+
# #current_command. This really sucks and is UGLY.
|
125
|
+
# the todo is to put in 'load_all_parser_constraints' and this works
|
126
|
+
def process_parser!
|
127
|
+
# load_all_parser_constraints
|
128
|
+
|
129
|
+
load_parser_default_constraints
|
130
|
+
load_parser_primary_constraints
|
131
|
+
# load_parser_local_constraints
|
132
|
+
parser.consume_all(constraints)
|
133
|
+
|
134
|
+
# hack
|
135
|
+
parser.consume {
|
136
|
+
opt :version, "Print version and exit" if @version unless @specs[:version] || @long["version"]
|
137
|
+
opt :help, "Show this message" unless @specs[:help] || @long["help"]
|
138
|
+
resolve_default_short_options
|
139
|
+
} # hack
|
140
|
+
end
|
141
|
+
|
142
|
+
def process_args(args = ARGV, *a, &b)
|
143
|
+
p = parser
|
144
|
+
begin
|
145
|
+
vals = p.parse args
|
146
|
+
args.clear
|
147
|
+
p.leftovers.each { |l| args << l }
|
148
|
+
vals # ugly todo
|
149
|
+
rescue Trollop::CommandlineError => e
|
150
|
+
$stderr.puts "Error: #{e.message}."
|
151
|
+
$stderr.puts "Try --help for help."
|
152
|
+
exit(-1)
|
153
|
+
rescue Trollop::HelpNeeded
|
154
|
+
p.educate
|
155
|
+
exit
|
156
|
+
rescue Trollop::VersionNeeded
|
157
|
+
puts p.version
|
158
|
+
exit
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def is_primary?
|
163
|
+
false
|
164
|
+
end
|
165
|
+
|
166
|
+
def argv
|
167
|
+
parser.leftovers
|
168
|
+
end
|
169
|
+
|
170
|
+
def short_desc
|
171
|
+
parser.short_desc
|
172
|
+
end
|
173
|
+
|
174
|
+
def full_name
|
175
|
+
# ugly, should be is_primary?
|
176
|
+
GitStyleBinary.primary_name == name ? GitStyleBinary.primary_name : GitStyleBinary.primary_name + "-" + name
|
177
|
+
end
|
178
|
+
|
179
|
+
def die arg, msg=nil
|
180
|
+
p = parser # create local copy
|
181
|
+
Trollop.instance_eval { @p = p }
|
182
|
+
Trollop::die(arg, msg)
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
187
|
+
class Primary < Command
|
188
|
+
def is_primary?
|
189
|
+
true
|
190
|
+
end
|
191
|
+
def primary
|
192
|
+
self
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module GitStyleBinary
|
2
|
+
module Commands
|
3
|
+
class Help
|
4
|
+
# not loving this syntax, but works for now
|
5
|
+
GitStyleBinary.command do
|
6
|
+
short_desc "get help for a specific command"
|
7
|
+
run do |command|
|
8
|
+
|
9
|
+
# this is slightly ugly b/c it has to muck around in the internals to
|
10
|
+
# get information about commands other than itself. This isn't a
|
11
|
+
# typical case
|
12
|
+
def educate_about_command(name)
|
13
|
+
load_all_commands
|
14
|
+
if GitStyleBinary.known_commands.has_key?(name)
|
15
|
+
cmd = GitStyleBinary.known_commands[name]
|
16
|
+
cmd.process_parser!
|
17
|
+
cmd.parser.educate
|
18
|
+
else
|
19
|
+
puts "Unknown command '#{name}'"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
if command.argv.size > 0
|
24
|
+
command.argv.first == "help" ? educate : educate_about_command(command.argv.first)
|
25
|
+
else
|
26
|
+
educate
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module GitStyleBinary
|
2
|
+
module Helpers
|
3
|
+
module NameResolver
|
4
|
+
|
5
|
+
def basename(filename=zero)
|
6
|
+
File.basename(filename).match(/(.*?)(\-|$)/).captures.first
|
7
|
+
end
|
8
|
+
alias_method :primary_name, :basename
|
9
|
+
|
10
|
+
# checks the bin directory for all files starting with +basename+ and
|
11
|
+
# returns an array of strings specifying the subcommands
|
12
|
+
def subcommand_names(filename=zero)
|
13
|
+
subfiles = Dir[File.join(binary_directory, basename + "-*")]
|
14
|
+
cmds = subfiles.collect{|file| File.basename(file).sub(/^#{basename}-/, '')}.sort
|
15
|
+
cmds += built_in_command_names
|
16
|
+
cmds.uniq
|
17
|
+
end
|
18
|
+
|
19
|
+
def binary_directory(filename=zero)
|
20
|
+
File.dirname(filename)
|
21
|
+
end
|
22
|
+
|
23
|
+
def built_in_commands_directory
|
24
|
+
File.dirname(__FILE__) + "/../commands"
|
25
|
+
end
|
26
|
+
|
27
|
+
def built_in_command_names
|
28
|
+
Dir[built_in_commands_directory + "/*.rb"].collect{|f| File.basename(f.sub(/\.rb$/,''))}
|
29
|
+
end
|
30
|
+
|
31
|
+
def list_subcommands(filename=zero)
|
32
|
+
subcommand_names(filename).join(", ")
|
33
|
+
end
|
34
|
+
|
35
|
+
# load first from users binary directory. then load built-in commands if
|
36
|
+
# available
|
37
|
+
def binary_filename_for(name)
|
38
|
+
user_file = File.join(binary_directory, "#{basename}-#{name}")
|
39
|
+
return user_file if File.exists?(user_file)
|
40
|
+
built_in = File.join(built_in_commands_directory, "#{name}.rb")
|
41
|
+
return built_in if File.exists?(built_in)
|
42
|
+
user_file
|
43
|
+
end
|
44
|
+
|
45
|
+
def current_command_name(filename=zero,argv=ARGV)
|
46
|
+
current = File.basename(zero)
|
47
|
+
first_arg = ARGV[0]
|
48
|
+
return first_arg if valid_subcommand?(first_arg)
|
49
|
+
return basename if basename == current
|
50
|
+
current.sub(/^#{basename}-/, '')
|
51
|
+
end
|
52
|
+
|
53
|
+
# returns the command name with the prefix if needed
|
54
|
+
def full_current_command_name(filename=zero,argv=ARGV)
|
55
|
+
cur = current_command_name(filename, argv)
|
56
|
+
subcmd = cur == basename(filename) ? false : true # is this a subcmd?
|
57
|
+
"%s%s%s" % [basename(filename), subcmd ? "-" : "", subcmd ? current_command_name(filename, argv) : ""]
|
58
|
+
end
|
59
|
+
|
60
|
+
def valid_subcommand?(name)
|
61
|
+
subcommand_names.include?(name)
|
62
|
+
end
|
63
|
+
|
64
|
+
def zero
|
65
|
+
$0
|
66
|
+
end
|
67
|
+
|
68
|
+
def pretty_known_subcommands
|
69
|
+
GitStyleBinary.known_commands.collect do |k,cmd|
|
70
|
+
next if k == basename
|
71
|
+
cmd.process_parser!
|
72
|
+
("%-s%-10s" % [basename, k]).colorize(:blue) + "\n " + ("%s" % [cmd.short_desc]) + "\n"
|
73
|
+
end.compact.sort
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module GitStyleBinary
|
2
|
+
module Helpers
|
3
|
+
module Pager
|
4
|
+
|
5
|
+
# by Nathan Weizenbaum - http://nex-3.com/posts/73-git-style-automatic-paging-in-ruby
|
6
|
+
def run_pager
|
7
|
+
return if PLATFORM =~ /win32/
|
8
|
+
return unless STDOUT.tty?
|
9
|
+
STDOUT.use_color = true
|
10
|
+
|
11
|
+
read, write = IO.pipe
|
12
|
+
|
13
|
+
unless Kernel.fork # Child process
|
14
|
+
STDOUT.reopen(write)
|
15
|
+
STDERR.reopen(write) if STDERR.tty?
|
16
|
+
read.close
|
17
|
+
write.close
|
18
|
+
return
|
19
|
+
end
|
20
|
+
|
21
|
+
# Parent process, become pager
|
22
|
+
STDIN.reopen(read)
|
23
|
+
read.close
|
24
|
+
write.close
|
25
|
+
|
26
|
+
ENV['LESS'] = 'FSRX' # Don't page if the input is short enough
|
27
|
+
|
28
|
+
Kernel.select [STDIN] # Wait until we have input before we start the pager
|
29
|
+
pager = ENV['PAGER'] || 'less -erXF'
|
30
|
+
exec pager rescue exec "/bin/sh", "-c", pager
|
31
|
+
end
|
32
|
+
|
33
|
+
module_function :run_pager
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,204 @@
|
|
1
|
+
module GitStyleBinary
|
2
|
+
class Parser < Trollop::Parser
|
3
|
+
attr_reader :runs
|
4
|
+
attr_reader :short_desc
|
5
|
+
attr_accessor :command
|
6
|
+
|
7
|
+
def initialize *a, &b
|
8
|
+
super
|
9
|
+
@runs = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def banner s=nil; @banner = s if s; @banner end
|
13
|
+
def short_desc s=nil; @short_desc = s if s; @short_desc end
|
14
|
+
def name_desc s=nil; @name_desc = s if s; @name_desc end
|
15
|
+
|
16
|
+
# Set the theme. Valid values are +:short+ or +:long+. Default +:long+
|
17
|
+
attr_writer :theme
|
18
|
+
|
19
|
+
def theme
|
20
|
+
@theme ||= :long
|
21
|
+
end
|
22
|
+
|
23
|
+
## Adds text to the help display.
|
24
|
+
def text s; @order << [:text, s] end
|
25
|
+
|
26
|
+
def spec_names
|
27
|
+
@specs.collect{|name, spec| spec[:long]}
|
28
|
+
end
|
29
|
+
|
30
|
+
# should probably be somewhere else
|
31
|
+
def load_all_commands
|
32
|
+
GitStyleBinary.subcommand_names.each do |name|
|
33
|
+
cmd_file = GitStyleBinary.binary_filename_for(name)
|
34
|
+
GitStyleBinary.load_command_file(name, cmd_file)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
## Print the help message to 'stream'.
|
39
|
+
def educate(stream=$stdout)
|
40
|
+
load_all_commands
|
41
|
+
width # just calculate it now; otherwise we have to be careful not to
|
42
|
+
# call this unless the cursor's at the beginning of a line.
|
43
|
+
GitStyleBinary::Helpers::Pager.run_pager
|
44
|
+
self.send("educate_#{theme}", stream)
|
45
|
+
end
|
46
|
+
|
47
|
+
def educate_long(stream=$stdout)
|
48
|
+
left = {}
|
49
|
+
|
50
|
+
@specs.each do |name, spec|
|
51
|
+
left[name] =
|
52
|
+
((spec[:short] ? "-#{spec[:short]}, " : "") +
|
53
|
+
"--#{spec[:long]}" +
|
54
|
+
case spec[:type]
|
55
|
+
when :flag; ""
|
56
|
+
when :int; "=<i>"
|
57
|
+
when :ints; "=<i+>"
|
58
|
+
when :string; "=<s>"
|
59
|
+
when :strings; "=<s+>"
|
60
|
+
when :float; "=<f>"
|
61
|
+
when :floats; "=<f+>"
|
62
|
+
end).colorize(:red)
|
63
|
+
end
|
64
|
+
|
65
|
+
leftcol_width = left.values.map { |s| s.length }.max || 0
|
66
|
+
rightcol_start = leftcol_width + 6 # spaces
|
67
|
+
leftcol_start = 6
|
68
|
+
leftcol_spaces = " " * leftcol_start
|
69
|
+
|
70
|
+
unless @order.size > 0 && @order.first.first == :text
|
71
|
+
|
72
|
+
if @name_desc
|
73
|
+
stream.puts "NAME".colorize(:red)
|
74
|
+
stream.puts "#{leftcol_spaces}"+ colorize_known_words(eval(%Q["#{@name_desc}"])) + "\n"
|
75
|
+
stream.puts
|
76
|
+
end
|
77
|
+
|
78
|
+
if @version
|
79
|
+
stream.puts "VERSION".colorize(:red)
|
80
|
+
stream.puts "#{leftcol_spaces}#@version\n"
|
81
|
+
end
|
82
|
+
|
83
|
+
stream.puts
|
84
|
+
|
85
|
+
# banner = wrap(colorize_known_words(eval(%Q["#{@banner}"])) + "\n", :prefix => leftcol_start) if @banner # lazy banner
|
86
|
+
banner = colorize_known_words_array(wrap(eval(%Q["#{@banner}"]) + "\n", :prefix => leftcol_start)) if @banner # lazy banner
|
87
|
+
stream.puts banner
|
88
|
+
|
89
|
+
stream.puts
|
90
|
+
stream.puts "OPTIONS".colorize(:red)
|
91
|
+
else
|
92
|
+
stream.puts "#@banner\n" if @banner
|
93
|
+
end
|
94
|
+
|
95
|
+
@order.each do |what, opt|
|
96
|
+
if what == :text
|
97
|
+
stream.puts wrap(opt)
|
98
|
+
next
|
99
|
+
end
|
100
|
+
|
101
|
+
spec = @specs[opt]
|
102
|
+
stream.printf " %-#{leftcol_width}s\n", left[opt]
|
103
|
+
desc = spec[:desc] +
|
104
|
+
if spec[:default]
|
105
|
+
if spec[:desc] =~ /\.$/
|
106
|
+
" (Default: #{spec[:default]})"
|
107
|
+
else
|
108
|
+
" (default: #{spec[:default]})"
|
109
|
+
end
|
110
|
+
else
|
111
|
+
""
|
112
|
+
end
|
113
|
+
stream.puts wrap(" %s" % [desc], :prefix => leftcol_start, :width => width - rightcol_start - 1 )
|
114
|
+
stream.puts
|
115
|
+
stream.puts
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
def educate_short(stream=$stdout)
|
121
|
+
left = {}
|
122
|
+
|
123
|
+
@specs.each do |name, spec|
|
124
|
+
left[name] = "--#{spec[:long]}" +
|
125
|
+
(spec[:short] ? ", -#{spec[:short]}" : "") +
|
126
|
+
case spec[:type]
|
127
|
+
when :flag; ""
|
128
|
+
when :int; " <i>"
|
129
|
+
when :ints; " <i+>"
|
130
|
+
when :string; " <s>"
|
131
|
+
when :strings; " <s+>"
|
132
|
+
when :float; " <f>"
|
133
|
+
when :floats; " <f+>"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
leftcol_width = left.values.map { |s| s.length }.max || 0
|
138
|
+
rightcol_start = leftcol_width + 6 # spaces
|
139
|
+
|
140
|
+
unless @order.size > 0 && @order.first.first == :text
|
141
|
+
stream.puts "#@version\n" if @version
|
142
|
+
stream.puts eval(%Q["#{@banner}"]) + "\n" if @banner # lazy banner
|
143
|
+
stream.puts "Options:"
|
144
|
+
else
|
145
|
+
stream.puts "#@banner\n" if @banner
|
146
|
+
end
|
147
|
+
|
148
|
+
@order.each do |what, opt|
|
149
|
+
if what == :text
|
150
|
+
stream.puts wrap(opt)
|
151
|
+
next
|
152
|
+
end
|
153
|
+
|
154
|
+
spec = @specs[opt]
|
155
|
+
stream.printf " %#{leftcol_width}s: ", left[opt]
|
156
|
+
desc = spec[:desc] +
|
157
|
+
if spec[:default]
|
158
|
+
if spec[:desc] =~ /\.$/
|
159
|
+
" (Default: #{spec[:default]})"
|
160
|
+
else
|
161
|
+
" (default: #{spec[:default]})"
|
162
|
+
end
|
163
|
+
else
|
164
|
+
""
|
165
|
+
end
|
166
|
+
stream.puts wrap(desc, :width => width - rightcol_start - 1, :prefix => rightcol_start)
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
def colorize_known_words_array(txts)
|
173
|
+
txts.collect{|txt| colorize_known_words(txt)}
|
174
|
+
end
|
175
|
+
|
176
|
+
def colorize_known_words(txt)
|
177
|
+
txt = txt.gsub(/^([A-Z]+\s*)$/, '\1'.colorize(:red)) # all caps words on their own line
|
178
|
+
txt = txt.gsub(/\b(#{bin_name})\b/, '\1'.colorize(:blue)) # the current command name
|
179
|
+
txt = txt.gsub(/\[([^\s]+)\]/, "[".colorize(:magenta) + '\1'.colorize(:green) + "]".colorize(:magenta)) # synopsis options
|
180
|
+
end
|
181
|
+
|
182
|
+
def consume(&block)
|
183
|
+
cloaker(&block).bind(self).call
|
184
|
+
end
|
185
|
+
|
186
|
+
def consume_all(blocks)
|
187
|
+
blocks.each {|b| consume(&b)}
|
188
|
+
end
|
189
|
+
|
190
|
+
def bin_name
|
191
|
+
GitStyleBinary.full_current_command_name
|
192
|
+
end
|
193
|
+
|
194
|
+
def all_options_string
|
195
|
+
# '#{spec_names.collect(&:to_s).collect{|name| "[".colorize(:magenta) + "--" + name + "]".colorize(:magenta)}.join(" ")} COMMAND [ARGS]'
|
196
|
+
'#{spec_names.collect(&:to_s).collect{|name| "[" + "--" + name + "]"}.join(" ")} COMMAND [ARGS]'
|
197
|
+
end
|
198
|
+
|
199
|
+
def run(&block)
|
200
|
+
@runs << block
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__))
|
2
|
+
require 'rubygems'
|
3
|
+
require 'trollop'
|
4
|
+
require 'ext/core'
|
5
|
+
require 'ext/colorize'
|
6
|
+
require 'git-style-binary/autorunner'
|
7
|
+
Dir[File.dirname(__FILE__) + "/git-style-binary/helpers/*.rb"].each {|f| require f}
|
8
|
+
|
9
|
+
module GitStyleBinary
|
10
|
+
|
11
|
+
class << self
|
12
|
+
include Helpers::NameResolver
|
13
|
+
attr_accessor :current_command
|
14
|
+
attr_accessor :primary_command
|
15
|
+
attr_writer :known_commands
|
16
|
+
|
17
|
+
# If set to false GitStyleBinary will not automatically run at exit.
|
18
|
+
attr_writer :run
|
19
|
+
|
20
|
+
# Automatically run at exit?
|
21
|
+
def run?
|
22
|
+
@run ||= false
|
23
|
+
end
|
24
|
+
|
25
|
+
def parser
|
26
|
+
@p ||= Parser.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def known_commands
|
30
|
+
@known_commands ||= {}
|
31
|
+
end
|
32
|
+
|
33
|
+
def load_primary
|
34
|
+
unless @loaded_primary
|
35
|
+
@loaded_primary = true
|
36
|
+
primary_file = File.join(binary_directory, basename)
|
37
|
+
load primary_file
|
38
|
+
|
39
|
+
if !GitStyleBinary.primary_command # you still dont have a primary load a default
|
40
|
+
GitStyleBinary.primary do
|
41
|
+
run do |command|
|
42
|
+
educate
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def load_subcommand
|
50
|
+
unless @loaded_subcommand
|
51
|
+
@loaded_subcommand = true
|
52
|
+
cmd_file = GitStyleBinary.binary_filename_for(GitStyleBinary.current_command_name)
|
53
|
+
load cmd_file
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def load_command_file(name, file)
|
58
|
+
self.name_of_command_being_loaded = name
|
59
|
+
load file
|
60
|
+
self.name_of_command_being_loaded = nil
|
61
|
+
end
|
62
|
+
|
63
|
+
# UGLY eek
|
64
|
+
attr_accessor :name_of_command_being_loaded
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
at_exit do
|
70
|
+
unless $! || GitStyleBinary.run?
|
71
|
+
command = GitStyleBinary::AutoRunner.run
|
72
|
+
exit 0
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift(File.dirname(__FILE__) + "/../../lib")
|
3
|
+
require 'git-style-binary/command'
|
4
|
+
|
5
|
+
GitStyleBinary.command do
|
6
|
+
short_desc "download a flickr image"
|
7
|
+
banner <<-EOS
|
8
|
+
SYNOPSIS
|
9
|
+
#{command.full_name} #{all_options_string} url
|
10
|
+
|
11
|
+
Downloads an image from flickr
|
12
|
+
|
13
|
+
EOS
|
14
|
+
run do |command|
|
15
|
+
puts "would download: #{command.argv.inspect}"
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift(File.dirname(__FILE__) + "/../../lib")
|
3
|
+
|
4
|
+
require 'git-style-binary/command'
|
5
|
+
GitStyleBinary.primary do
|
6
|
+
version "0.0.1 (c) 2009 Nate Murray - local"
|
7
|
+
opt :test_primary, "test an option on the primary", :type => String
|
8
|
+
|
9
|
+
run do |command|
|
10
|
+
puts "Primary Options: #{command.opts.inspect}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# OR
|
15
|
+
|
16
|
+
# require 'git-style-binary/primary'
|
17
|
+
# command = GitStyleBinary::primary("wordpress") do
|
18
|
+
# version "#{$0} 0.0.1 (c) 2009 Nate Murray"
|
19
|
+
# banner <<-EOS
|
20
|
+
# usage: #{$0} #{all_options.collect(:&to_s).join(" ")} COMMAND [ARGS]
|
21
|
+
#
|
22
|
+
# The wordpress subcommands commands are:
|
23
|
+
# {subcommand_names.pretty_print}
|
24
|
+
#
|
25
|
+
# See 'wordpress help COMMAND' for more information on a specific command.
|
26
|
+
# EOS
|
27
|
+
# opt :verbose, "verbose", :default => false
|
28
|
+
# opt :dry, "dry run", :default => false
|
29
|
+
# opt :test_global, "a basic global string option", :type => String
|
30
|
+
# end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift(File.dirname(__FILE__) + "/../../lib")
|
3
|
+
require 'git-style-binary/command'
|
4
|
+
|
5
|
+
GitStyleBinary.command do
|
6
|
+
short_desc "do something with categories"
|
7
|
+
banner <<-EOS
|
8
|
+
SYNOPSIS
|
9
|
+
#{command.full_name} #{all_options_string}
|
10
|
+
|
11
|
+
Does something with categories
|
12
|
+
|
13
|
+
EOS
|
14
|
+
run do |command|
|
15
|
+
puts "does something with categories"
|
16
|
+
end
|
17
|
+
end
|