git-style-binaries 0.1.10

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,280 @@
1
+ git-style-binaries
2
+ ==================
3
+
4
+ Ridiculously easy git-style binaries.
5
+
6
+ This gem uses [`trollop`](http://trollop.rubyforge.org/) for option parsing
7
+
8
+ ## Installation
9
+
10
+ gem install jashmenn-git-style-binaries --source=http://gems.github.com
11
+
12
+ ## Screencast
13
+
14
+ Checkout <a href="http://www.xcombinator.com/movies/git-style-binaries.mov">the new screencast!</a>
15
+
16
+ <a href="http://www.xcombinator.com/movies/git-style-binaries.mov"><img src="http://github.com/jashmenn/git-style-binaries/tree/master/doc/gsb-screencast.png?raw=true" width='880' height='784' border=0></a>
17
+
18
+ ## Try it out
19
+
20
+ cd `gem env gemdir`/gems/jashmenn-git-style-binaries-0.1.4/test/fixtures
21
+ ./wordpress -h
22
+ ./wordpress help post
23
+
24
+ ## Goal
25
+
26
+ Lets use the imaginary `wordpress` gem. Let's say we have three different
27
+ actions we want to specify:
28
+
29
+ * categories
30
+ * list
31
+ * post
32
+
33
+ Each command has its own binary in a directory structure like this:
34
+
35
+ bin/
36
+ |-- wordpress
37
+ |-- wordpress-categories
38
+ |-- wordpress-list
39
+ `-- wordpress-post
40
+
41
+ The goal is to be able to call commands in this manner:
42
+
43
+ wordpress -h # gives help summary of all commands
44
+ wordpress-list -h # gives long help of wordpress-list
45
+ wordpress list -h # ditto
46
+ echo "about me" | wordpress-post --title="new post" # posts a new post with that title
47
+
48
+ ## Example code
49
+ Our `bin/wordpress` binary is called the *primary* . Our primary only needs to contain the following line:
50
+
51
+ #!/usr/bin/env ruby
52
+ require 'git-style-binary/command'
53
+
54
+ `git-style-binary` will automatically make this command the primary.
55
+
56
+ The `bin/wordpress-post` binary could contain the following:
57
+
58
+ #!/usr/bin/env ruby
59
+ require 'git-style-binary/command'
60
+
61
+ GitStyleBinary.command do
62
+ short_desc "create a blog post"
63
+ banner <<-EOS
64
+ Usage: #{command.full_name} #{all_options_string} {content|STDIN}
65
+
66
+ Posts content to a wordpress blog
67
+
68
+ EOS
69
+ opt :blog, "short name of the blog to use", :default => 'default'
70
+ opt :category, "tag/category. specify multiple times for multiple categories", :type => String, :multi => true
71
+ opt :title, "title for the post", :required => true, :type => String
72
+ opt :type, "type of the content [html|xhtml|text]", :default => 'html', :type => String
73
+
74
+ run do |command|
75
+ command.die :type, "type must be one of [html|xhtml|text]" unless command.opts[:type] =~ /^(x?html|text)$/i
76
+
77
+ puts "Subcommand name: #{command.name.inspect}"
78
+ puts "Options: #{command.opts.inspect}"
79
+ puts "Remaining arguments: #{command.argv.inspect}"
80
+ end
81
+ end
82
+
83
+ And so on with the other binaries.
84
+
85
+ ## Running the binaries
86
+
87
+ Now if we run `wordpress -h` we get the following output:
88
+
89
+ NAME
90
+ wordpress
91
+
92
+ VERSION
93
+ 0.0.1 (c) 2009 Nate Murray - local
94
+
95
+ SYNOPSIS
96
+ wordpress [--version] [--test-primary] [--help] [--verbose] COMMAND [ARGS]
97
+
98
+ SUBCOMMANDS
99
+ wordpress-categories
100
+ do something with categories
101
+
102
+ wordpress-help
103
+ get help for a specific command
104
+
105
+ wordpress-list
106
+ list blog postings
107
+
108
+ wordpress-post
109
+ create a blog post
110
+
111
+
112
+ See 'wordpress help COMMAND' for more information on a specific command.
113
+
114
+ OPTIONS
115
+ -v, --verbose
116
+ verbose
117
+
118
+
119
+ -t, --test-primary=<s>
120
+ test an option on the primary
121
+
122
+
123
+ -e, --version
124
+ Print version and exit
125
+
126
+
127
+ -h, --help
128
+ Show this message
129
+
130
+
131
+
132
+ Default **options**, **version string**, and **usage banner** are automatically selected for you.
133
+ The subcommands and their short descriptions are loaded automatically!
134
+
135
+ You can pass the `-h` flag to any one of the subcommands (with or without the
136
+ connecting `-`) or use the built-in `help` subcommand for the same effect. For instance:
137
+
138
+ $ wordpress help post
139
+
140
+ NAME
141
+ wordpress-post - create a blog post
142
+
143
+ VERSION
144
+ 0.0.1 (c) 2009 Nate Murray - local
145
+
146
+ SYNOPSIS
147
+ wordpress-post [--type] [--version] [--test-primary] [--blog] [--help] [--verbose] [--category]
148
+ [--title] COMMAND [ARGS] {content|STDIN}
149
+
150
+ OPTIONS
151
+ -v, --verbose
152
+ verbose
153
+
154
+
155
+ -t, --test-primary=<s>
156
+ test an option on the primary
157
+
158
+
159
+ -b, --blog=<s>
160
+ short name of the blog to use (default: default)
161
+
162
+
163
+ -c, --category=<s>
164
+ tag/category. specify multiple times for multiple
165
+ categories
166
+
167
+
168
+ -i, --title=<s>
169
+ title for the post
170
+
171
+
172
+ -y, --type=<s>
173
+ type of the content [html|xhtml|text] (default: html)
174
+
175
+
176
+ -e, --version
177
+ Print version and exit
178
+
179
+
180
+ -h, --help
181
+ Show this message
182
+
183
+
184
+ For more examples, see the binaries in `test/fixtures/`.
185
+
186
+ ## Primary options
187
+
188
+ Often you may *want* the primary to have its own set of options. Simply call `GitStyleBinary.primary` with a block like so:
189
+
190
+ #!/usr/bin/env ruby
191
+ require 'git-style-binary/command'
192
+ GitStyleBinary.primary do
193
+ version "#{command.full_name} 0.0.1 (c) 2009 Nate Murray - local"
194
+ opt :test_primary, "a primary string option", :type => String
195
+
196
+ run do |command|
197
+ puts "Primary Options: #{command.opts.inspect}"
198
+ end
199
+ end
200
+
201
+ Primary options are **inherited** by all subcommands. That means in this case
202
+ all subcommands will now get the `--test-primary` option available to them as
203
+ well as this new `version` string.
204
+
205
+ ## Option parsing
206
+
207
+ Option parsing is done by [trollop](http://trollop.rubyforge.org/).
208
+ `git-style-binary` uses this more-or-less exactly. See the [trollop
209
+ documentation](http://trollop.rubyforge.org/) for information on how to setup
210
+ the options and flags.
211
+
212
+ ## Callbacks
213
+
214
+ Callbacks are available on the primary and subcommands. Available callbacks currently
215
+ are before/after_run. These execute before the run block of the command parser and take
216
+ take one argument, which is the command itself
217
+
218
+ ## The `run` block
219
+
220
+ To get the 'introspection' on the individual binaries every binary is `load`ed
221
+ on `primary help`. We need a way to get that information while not running
222
+ every command when calling `primary help`. To achieve that you need to put what
223
+ will be run in the `run` block.
224
+
225
+ `run` `yields` a `Command` object which contains a number of useful options
226
+ such as `name`, `full_name`, `opts`, and `argv`.
227
+
228
+ * `command.opts` is a hash of the options parsed
229
+ * `command.argv` is an array of the remaining arguments
230
+
231
+ ## Features
232
+ * automatic colorization
233
+ * automatic paging
234
+
235
+ ## To Learn more
236
+
237
+ Play with the examples in the `test/fixtures` directory.
238
+
239
+ ## Credits
240
+ * `git-style-binary` was written by Nate Murray `<nate@natemurray.com>`
241
+ * `trollop` was written by [William Morgan](http://trollop.rubyforge.org/)
242
+ * Inspiration comes from Ari Lerner's [git-style-binaries](http://blog.xnot.org/2008/12/16/git-style-binaries/) for [PoolParty.rb](http://poolpartyrb.com)
243
+ * [`colorize.rb`](http://colorize.rubyforge.org) by Michal Kalbarczyk
244
+ * Automatic less paging by [Nathan Weizenbaum](http://nex-3.com/posts/73-git-style-automatic-paging-in-ruby)
245
+ * Color inspiration from [Brian Henderson](http://xcombinator.com) teaching me how to get `man git` colors using `less` on MacOSX
246
+
247
+ ## TODO
248
+ * automagic tab completion - Automatic for subcommands and options for any library that uses this
249
+
250
+ ## Known Bugs/Problems
251
+ * Young
252
+ * A few places of really ugly code
253
+ * A feeling that this could be done in 1/2 lines of code
254
+
255
+ ## Authors
256
+ By Nate Murray and Ari Lerner
257
+
258
+ ## Copyright
259
+
260
+ The MIT License
261
+
262
+ Copyright (c) 2009 Nate Murray. See LICENSE for details.
263
+
264
+ Permission is hereby granted, free of charge, to any person obtaining a copy
265
+ of this software and associated documentation files (the "Software"), to deal
266
+ in the Software without restriction, including without limitation the rights
267
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
268
+ copies of the Software, and to permit persons to whom the Software is
269
+ furnished to do so, subject to the following conditions:
270
+
271
+ The above copyright notice and this permission notice shall be included in
272
+ all copies or substantial portions of the Software.
273
+
274
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
275
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
276
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
277
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
278
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
279
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
280
+ THE SOFTWARE.
@@ -0,0 +1,64 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gemspec|
7
+ gemspec.name = "git-style-binaries"
8
+ gemspec.description = %Q{Ridiculously easy git-style binaries}
9
+ gemspec.summary =<<-EOF
10
+ Add git-style binaries to your project easily.
11
+ EOF
12
+ gemspec.email = "nate@natemurray.com"
13
+ gemspec.homepage = "http://github.com/jashmenn/git-style-binaries"
14
+ gemspec.authors = ["Nate Murray"]
15
+ gemspec.add_dependency 'trollop'
16
+ gemspec.add_dependency 'shoulda' # for running the tests
17
+
18
+ excludes = /(README\.html)/
19
+ gemspec.files = (FileList["[A-Z]*.*", "{bin,examples,generators,lib,rails,spec,test,vendor}/**/*", 'Rakefile', 'LICENSE*']).delete_if{|f| f =~ excludes}
20
+ gemspec.extra_rdoc_files = FileList["README*", "ChangeLog*", "LICENSE*"].delete_if{|f| f =~ excludes}
21
+ end
22
+ rescue LoadError
23
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
24
+ end
25
+
26
+ require 'rake/testtask'
27
+ Rake::TestTask.new(:test) do |test|
28
+ test.libs << 'lib' << 'test'
29
+ test.pattern = 'test/**/*_test.rb'
30
+ test.verbose = true
31
+ end
32
+
33
+ begin
34
+ require 'rcov/rcovtask'
35
+ Rcov::RcovTask.new do |test|
36
+ test.libs << 'test'
37
+ test.pattern = 'test/**/*_test.rb'
38
+ test.verbose = true
39
+ end
40
+ rescue LoadError
41
+ task :rcov do
42
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
43
+ end
44
+ end
45
+
46
+
47
+ task :default => :test
48
+
49
+ require 'rake/rdoctask'
50
+ Rake::RDocTask.new do |rdoc|
51
+ if File.exist?('VERSION.yml')
52
+ config = YAML.load(File.read('VERSION.yml'))
53
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
54
+ else
55
+ version = ""
56
+ end
57
+
58
+ rdoc.rdoc_dir = 'rdoc'
59
+ rdoc.title = "git-style-binaries #{version}"
60
+ rdoc.rdoc_files.include('README*')
61
+ rdoc.rdoc_files.include('lib/**/*.rb')
62
+ end
63
+
64
+ task :bump => ['version:bump:patch', 'gemspec', 'build']
@@ -0,0 +1,4 @@
1
+ ---
2
+ :patch: 10
3
+ :major: 0
4
+ :minor: 1
@@ -0,0 +1,198 @@
1
+ #
2
+ # Colorize String class extension.
3
+ #
4
+ class String
5
+
6
+ #
7
+ # Version string
8
+ #
9
+ COLORIZE_VERSION = '0.5.6'
10
+
11
+ #
12
+ # Colors Hash
13
+ #
14
+ COLORS = {
15
+ :black => 0,
16
+ :red => 1,
17
+ :green => 2,
18
+ :yellow => 3,
19
+ :blue => 4,
20
+ :magenta => 5,
21
+ :cyan => 6,
22
+ :white => 7,
23
+ :default => 9,
24
+
25
+ :light_black => 10,
26
+ :light_red => 11,
27
+ :light_green => 12,
28
+ :light_yellow => 13,
29
+ :light_blue => 14,
30
+ :light_magenta => 15,
31
+ :light_cyan => 16,
32
+ :light_white => 17
33
+ }
34
+
35
+ #
36
+ # Modes Hash
37
+ #
38
+ MODES = {
39
+ :default => 0, # Turn off all attributes
40
+ #:bright => 1, # Set bright mode
41
+ :underline => 4, # Set underline mode
42
+ :blink => 5, # Set blink mode
43
+ :swap => 7, # Exchange foreground and background colors
44
+ :hide => 8 # Hide text (foreground color would be the same as background)
45
+ }
46
+
47
+ protected
48
+
49
+ #
50
+ # Set color values in new string intance
51
+ #
52
+ def set_color_parameters( params )
53
+ if (params.instance_of?(Hash))
54
+ @color = params[:color]
55
+ @background = params[:background]
56
+ @mode = params[:mode]
57
+ @uncolorized = params[:uncolorized]
58
+ self
59
+ else
60
+ nil
61
+ end
62
+ end
63
+
64
+ public
65
+
66
+ #
67
+ # Change color of string
68
+ #
69
+ # Examples:
70
+ #
71
+ # puts "This is blue".colorize( :blue )
72
+ # puts "This is light blue".colorize( :light_blue )
73
+ # puts "This is also blue".colorize( :color => :blue )
74
+ # puts "This is blue with red background".colorize( :color => :light_blue, :background => :red )
75
+ # puts "This is blue with red background".colorize( :light_blue ).colorize( :background => :red )
76
+ # puts "This is blue text on red".blue.on_red
77
+ # puts "This is red on blue".colorize( :red ).on_blue
78
+ # puts "This is red on blue and underline".colorize( :red ).on_blue.underline
79
+ # puts "This is blue text on red".blue.on_red.blink
80
+ #
81
+ def colorize( params )
82
+
83
+ unless STDOUT.use_color
84
+ return self unless STDOUT.isatty
85
+ end
86
+ return self if ENV['NO_COLOR']
87
+
88
+ begin
89
+ require 'Win32/Console/ANSI' if PLATFORM =~ /win32/
90
+ rescue LoadError
91
+ raise 'You must gem install win32console to use color on Windows'
92
+ end
93
+
94
+ color_parameters = {}
95
+
96
+ if (params.instance_of?(Hash))
97
+ color_parameters[:color] = COLORS[params[:color]]
98
+ color_parameters[:background] = COLORS[params[:background]]
99
+ color_parameters[:mode] = MODES[params[:mode]]
100
+ elsif (params.instance_of?(Symbol))
101
+ color_parameters[:color] = COLORS[params]
102
+ end
103
+
104
+ color_parameters[:color] ||= @color || 9
105
+ color_parameters[:background] ||= @background || 9
106
+ color_parameters[:mode] ||= @mode || 0
107
+
108
+ color_parameters[:uncolorized] ||= @uncolorized || self.dup
109
+
110
+ # calculate bright mode
111
+ color_parameters[:color] += 50 if color_parameters[:color] > 10
112
+
113
+ color_parameters[:background] += 50 if color_parameters[:background] > 10
114
+
115
+ return "\033[#{color_parameters[:mode]};#{color_parameters[:color]+30};#{color_parameters[:background]+40}m#{color_parameters[:uncolorized]}\033[0m".set_color_parameters( color_parameters )
116
+ end
117
+
118
+
119
+ #
120
+ # Return uncolorized string
121
+ #
122
+ def uncolorize
123
+ return @uncolorized || self
124
+ end
125
+
126
+ #
127
+ # Return true if sting is colorized
128
+ #
129
+ def colorized?
130
+ return !@uncolorized.nil?
131
+ end
132
+
133
+ #
134
+ # Make some color and on_color methods
135
+ #
136
+ COLORS.each_key do | key |
137
+ eval <<-"end_eval"
138
+ def #{key.to_s}
139
+ return self.colorize( :color => :#{key.to_s} )
140
+ end
141
+ def on_#{key.to_s}
142
+ return self.colorize( :background => :#{key.to_s} )
143
+ end
144
+ end_eval
145
+ end
146
+
147
+ #
148
+ # Methods for modes
149
+ #
150
+ MODES.each_key do | key |
151
+ eval <<-"end_eval"
152
+ def #{key.to_s}
153
+ return self.colorize( :mode => :#{key.to_s} )
154
+ end
155
+ end_eval
156
+ end
157
+
158
+ class << self
159
+
160
+ #
161
+ # Return array of available modes used by colorize method
162
+ #
163
+ def modes
164
+ keys = []
165
+ MODES.each_key do | key |
166
+ keys << key
167
+ end
168
+ keys
169
+ end
170
+
171
+ #
172
+ # Return array of available colors used by colorize method
173
+ #
174
+ def colors
175
+ keys = []
176
+ COLORS.each_key do | key |
177
+ keys << key
178
+ end
179
+ keys
180
+ end
181
+
182
+ #
183
+ # Display color matrix with color names.
184
+ #
185
+ def color_matrix( txt = "[X]" )
186
+ size = String.colors.length
187
+ String.colors.each do | color |
188
+ String.colors.each do | back |
189
+ print txt.colorize( :color => color, :background => back )
190
+ end
191
+ puts " < #{color}"
192
+ end
193
+ String.colors.reverse.each_with_index do | back, index |
194
+ puts "#{"|".rjust(txt.length)*(size-index)} < #{back}"
195
+ end
196
+ end
197
+ end
198
+ end