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 ADDED
@@ -0,0 +1,259 @@
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
+ ## Goal
13
+
14
+ Lets use the imaginary `wordpress` gem. Let's say we have three different
15
+ actions we want to specify:
16
+
17
+ * categories
18
+ * list
19
+ * post
20
+
21
+ Each command has its own binary in a directory structure like this:
22
+
23
+ bin/
24
+ |-- wordpress
25
+ |-- wordpress-categories
26
+ |-- wordpress-list
27
+ `-- wordpress-post
28
+
29
+ The goal is to be able to call commands in this manner:
30
+
31
+ wordpress -h # gives help summary of all commands
32
+ wordpress-list -h # gives long help of wordpress-list
33
+ wordpress list -h # ditto
34
+ echo "about me" | wordpress-post --title="new post" # posts a new post with that title
35
+
36
+ ## Example code
37
+ Our `bin/wordpress` binary is called the *primary* . Our primary only needs to contain the following line:
38
+
39
+ #!/usr/bin/env ruby
40
+ require 'git-style-binary/command'
41
+
42
+ `git-style-binary` will automatically make this command the primary.
43
+
44
+ The `bin/wordpress-post` binary could contain the following:
45
+
46
+ #!/usr/bin/env ruby
47
+ require 'git-style-binary/command'
48
+
49
+ GitStyleBinary.command do
50
+ short_desc "create a blog post"
51
+ banner <<-EOS
52
+ Usage: #{command.full_name} #{all_options_string} {content|STDIN}
53
+
54
+ Posts content to a wordpress blog
55
+
56
+ EOS
57
+ opt :blog, "short name of the blog to use", :default => 'default'
58
+ opt :category, "tag/category. specify multiple times for multiple categories", :type => String, :multi => true
59
+ opt :title, "title for the post", :required => true, :type => String
60
+ opt :type, "type of the content [html|xhtml|text]", :default => 'html', :type => String
61
+
62
+ run do |command|
63
+ command.die :type, "type must be one of [html|xhtml|text]" unless command.opts[:type] =~ /^(x?html|text)$/i
64
+
65
+ puts "Subcommand name: #{command.name.inspect}"
66
+ puts "Options: #{command.opts.inspect}"
67
+ puts "Remaining arguments: #{command.argv.inspect}"
68
+ end
69
+ end
70
+
71
+ And so on with the other binaries.
72
+
73
+ ## Running the binaries
74
+
75
+ Now if we run `wordpress -h` we get the following output:
76
+
77
+ NAME
78
+ wordpress
79
+
80
+ VERSION
81
+ 0.0.1 (c) 2009 Nate Murray - local
82
+
83
+ SYNOPSIS
84
+ wordpress [--version] [--test-primary] [--help] [--verbose] COMMAND [ARGS]
85
+
86
+ SUBCOMMANDS
87
+ wordpress-categories
88
+ do something with categories
89
+
90
+ wordpress-help
91
+ get help for a specific command
92
+
93
+ wordpress-list
94
+ list blog postings
95
+
96
+ wordpress-post
97
+ create a blog post
98
+
99
+
100
+ See 'wordpress help COMMAND' for more information on a specific command.
101
+
102
+ OPTIONS
103
+ -v, --verbose
104
+ verbose
105
+
106
+
107
+ -t, --test-primary=<s>
108
+ test an option on the primary
109
+
110
+
111
+ -e, --version
112
+ Print version and exit
113
+
114
+
115
+ -h, --help
116
+ Show this message
117
+
118
+
119
+
120
+ Default **options**, **version string**, and **usage banner** are automatically selected for you.
121
+ The subcommands and their short descriptions are loaded automatically!
122
+
123
+ You can pass the `-h` flag to any one of the subcommands (with or without the
124
+ connecting `-`) or use the built-in `help` subcommand for the same effect. For instance:
125
+
126
+ $ wordpress help post
127
+
128
+ NAME
129
+ wordpress-post - create a blog post
130
+
131
+ VERSION
132
+ 0.0.1 (c) 2009 Nate Murray - local
133
+
134
+ SYNOPSIS
135
+ wordpress-post [--type] [--version] [--test-primary] [--blog] [--help] [--verbose] [--category]
136
+ [--title] COMMAND [ARGS] {content|STDIN}
137
+
138
+ OPTIONS
139
+ -v, --verbose
140
+ verbose
141
+
142
+
143
+ -t, --test-primary=<s>
144
+ test an option on the primary
145
+
146
+
147
+ -b, --blog=<s>
148
+ short name of the blog to use (default: default)
149
+
150
+
151
+ -c, --category=<s>
152
+ tag/category. specify multiple times for multiple
153
+ categories
154
+
155
+
156
+ -i, --title=<s>
157
+ title for the post
158
+
159
+
160
+ -y, --type=<s>
161
+ type of the content [html|xhtml|text] (default: html)
162
+
163
+
164
+ -e, --version
165
+ Print version and exit
166
+
167
+
168
+ -h, --help
169
+ Show this message
170
+
171
+
172
+ For more examples, see the binaries in `test/fixtures/`.
173
+
174
+ ## Primary options
175
+
176
+ Often you may *want* the primary to have its own set of options. Simply call `GitStyleBinary.primary` with a block like so:
177
+
178
+ #!/usr/bin/env ruby
179
+ require 'git-style-binary/command'
180
+ GitStyleBinary.primary do
181
+ version "#{command.full_name} 0.0.1 (c) 2009 Nate Murray - local"
182
+ opt :test_primary, "a primary string option", :type => String
183
+
184
+ run do |command|
185
+ puts "Primary Options: #{command.opts.inspect}"
186
+ end
187
+ end
188
+
189
+ Primary options are **inherited** by all subcommands. That means in this case
190
+ all subcommands will now get the `--test-primary` option available to them as
191
+ well as this new `version` string.
192
+
193
+ ## Option parsing
194
+
195
+ Option parsing is done by [trollop](http://trollop.rubyforge.org/).
196
+ `git-style-binary` uses this more-or-less exactly. See the [trollop
197
+ documentation](http://trollop.rubyforge.org/) for information on how to setup
198
+ the options and flags.
199
+
200
+ ## The `run` block
201
+
202
+ To get the 'introspection' on the individual binaries every binary is `load`ed
203
+ on `primary help`. We need a way to get that information while not running
204
+ every command when calling `primary help`. To achieve that you need to put what
205
+ will be run in the `run` block.
206
+
207
+ `run` `yields` a `Command` object which contains a number of useful options
208
+ such as `name`, `full_name`, `opts`, and `argv`.
209
+
210
+ * `command.opts` is a hash of the options parsed
211
+ * `command.argv` is an array of the remaining arguments
212
+
213
+ ## Features
214
+ * automatic colorization
215
+ * automatic paging
216
+
217
+ ## To Learn more
218
+
219
+ Play with the examples in the `test/fixtures` directory.
220
+
221
+ ## Credits
222
+ * `git-style-binary` was written by Nate Murray `<nate@natemurray.com>`
223
+ * `trollop` was written by [William Morgan](http://trollop.rubyforge.org/)
224
+ * 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)
225
+ * [`colorize.rb`](http://colorize.rubyforge.org) by Michal Kalbarczyk
226
+ * Automatic less paging by [Nathan Weizenbaum](http://nex-3.com/posts/73-git-style-automatic-paging-in-ruby)
227
+ * Color inspiration from [Brian Henderson](http://xcombinator.com) teaching me how to get `man git` colors using `less` on MacOSX
228
+
229
+ ## TODO
230
+ * automagic tab completion - Automatic for subcommands and options for any library that uses this
231
+
232
+ ## Known Bugs/Problems
233
+ * Young
234
+ * A few places of really ugly code
235
+ * A feeling that this could be done in 1/2 lines of code
236
+
237
+ ## Copyright
238
+
239
+ The MIT License
240
+
241
+ Copyright (c) 2009 Nate Murray. See LICENSE for details.
242
+
243
+ Permission is hereby granted, free of charge, to any person obtaining a copy
244
+ of this software and associated documentation files (the "Software"), to deal
245
+ in the Software without restriction, including without limitation the rights
246
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
247
+ copies of the Software, and to permit persons to whom the Software is
248
+ furnished to do so, subject to the following conditions:
249
+
250
+ The above copyright notice and this permission notice shall be included in
251
+ all copies or substantial portions of the Software.
252
+
253
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
254
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
255
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
256
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
257
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
258
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
259
+ THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,64 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "git-style-binaries"
8
+ gem.description = %Q{Ridiculously easy git-style binaries}
9
+ gem.summary =<<-EOF
10
+ Add git-style binaries to your project easily.
11
+ EOF
12
+ gem.email = "nate@natemurray.com"
13
+ gem.homepage = "http://github.com/jashmenn/git-style-binaries"
14
+ gem.authors = ["Nate Murray"]
15
+ gem.add_dependency 'trollop'
16
+ gem.add_dependency 'thoughtbot-shoulda' # for running the tests
17
+
18
+ excludes = /(README\.html)/
19
+ gem.files = (FileList["[A-Z]*.*", "{bin,examples,generators,lib,rails,spec,test}/**/*", 'Rakefile', 'LICENSE*']).delete_if{|f| f =~ excludes}
20
+ gem.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']
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 1
4
+ :patch: 3
@@ -0,0 +1,199 @@
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
+ puts
199
+ end
data/lib/ext/core.rb ADDED
@@ -0,0 +1,16 @@
1
+ class Object
2
+ def returning(value)
3
+ yield(value)
4
+ value
5
+ end unless Object.respond_to?(:returning)
6
+ end
7
+
8
+ class Symbol
9
+ def to_proc
10
+ Proc.new { |*args| args.shift.__send__(self, *args) }
11
+ end
12
+ end
13
+
14
+ class IO
15
+ attr_accessor :use_color
16
+ end
@@ -0,0 +1,21 @@
1
+ require 'git-style-binary/parser'
2
+
3
+ module GitStyleBinary
4
+ class AutoRunner
5
+
6
+ def self.run(argv=ARGV)
7
+ r = new
8
+ r.run
9
+ end
10
+
11
+ def run
12
+ unless GitStyleBinary.run?
13
+ if !GitStyleBinary.current_command
14
+ GitStyleBinary.load_primary
15
+ end
16
+ GitStyleBinary.current_command.run
17
+ end
18
+ end
19
+
20
+ end
21
+ end