cli_tool 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.pryrc +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +107 -0
- data/Rakefile +1 -0
- data/cli_tool.gemspec +24 -0
- data/lib/cli_tool/option_parser.rb +94 -0
- data/lib/cli_tool/software_dependencies.rb +38 -0
- data/lib/cli_tool/stdin_out.rb +127 -0
- data/lib/cli_tool/version.rb +3 -0
- data/lib/cli_tool.rb +8 -0
- metadata +101 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4420b2da040b6b7fb8f05664834fd7cc0d33cf14
|
4
|
+
data.tar.gz: 3ade50f54e87003b8111a9812c6d31502c598103
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 65f885c50ac8668a209e9ef99197b78de9afce9932f225503b3f82cb4a11e756fc284fb326c41c4e000379e3ece271cbe9f1367bbe5397c3613d37f01119e58e
|
7
|
+
data.tar.gz: db5e0aae0a5c47c6966f241bb92b29751e5c8e240c9da7aee4d197d71a2b225a8d148e6015a562af4740a834c433279f88e93a5ea95b93bcbe464e6df08c725e
|
data/.gitignore
ADDED
data/.pryrc
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Kelly Becker
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
# CliTool
|
2
|
+
|
3
|
+
Have trouble with advanced command line options, software dependency presence validation, handling inputs, confirmations and colorizing? Then this gem is for you. It provides you with some modules you can include to add those specific features.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'cli_tool'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install cli_tool
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
**To include the GetoptLong option parser:**
|
22
|
+
|
23
|
+
``` ruby
|
24
|
+
include CliTool::OptionParser
|
25
|
+
```
|
26
|
+
|
27
|
+
You can then define command line arguments using the following class method.
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
class New
|
31
|
+
include CliTool::OptionParser
|
32
|
+
|
33
|
+
options {
|
34
|
+
:log => :required,
|
35
|
+
[:other, :alias] => {
|
36
|
+
:dependency => :optional, # Valid values are :none, :optional and :required.
|
37
|
+
:short => :o, # The short arg this would be '-o'
|
38
|
+
:default => 'default value'
|
39
|
+
}
|
40
|
+
}
|
41
|
+
```
|
42
|
+
|
43
|
+
These are then returned as GetoptLong array syntax. So to use in GetoptLong:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
GetoptLong(*New.options).each |option, value|
|
47
|
+
puts option
|
48
|
+
# => :other
|
49
|
+
puts value
|
50
|
+
# => 'default value'
|
51
|
+
end
|
52
|
+
```
|
53
|
+
|
54
|
+
**To include the software dependency module**
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
include CliTool::SoftwareDependencies
|
58
|
+
```
|
59
|
+
|
60
|
+
You can then have you application check that dependencies are accessible in your $PATH on startup by using the following class method.
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
class New
|
64
|
+
include CliTool::SoftwareDependencies
|
65
|
+
|
66
|
+
software(:git, :ls, :cp, :mysqld, ...)
|
67
|
+
end
|
68
|
+
```
|
69
|
+
|
70
|
+
If the executable cannot be found in the $PATH then it will throw `CliTool::MissingDependencies`.
|
71
|
+
|
72
|
+
**To include the input, confirm and colorized_puts tool**
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
include CliTool::StdinOut
|
76
|
+
```
|
77
|
+
|
78
|
+
You can then make use of the methods as follows.
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
include CliTool::StdinOut
|
82
|
+
|
83
|
+
puts("My normal message", :red)
|
84
|
+
puts("My normal message", [:red, :purple_bg, :bold])
|
85
|
+
|
86
|
+
input("What is your name?", :red)
|
87
|
+
input("What is your name?", [:red, :purple_bg, :bold])
|
88
|
+
|
89
|
+
confirm("Do you really want to do that?", :red)
|
90
|
+
confirm("Do you really want to do that?", [:red, :purple_bg, :bold])
|
91
|
+
```
|
92
|
+
|
93
|
+
The available options for the methods are.
|
94
|
+
|
95
|
+
`puts(message, color = :reset, sleep_in_seconds = nil)`
|
96
|
+
`input(message, color = :reset, timeout_in_seconds = nil, default_value_for_timeout = nil)`
|
97
|
+
`confirm(message, color = :reset, default_value = :n, timeout_in_seconds = nil)`
|
98
|
+
|
99
|
+
The only required values are message.
|
100
|
+
|
101
|
+
## Contributing
|
102
|
+
|
103
|
+
1. Fork it
|
104
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
105
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
106
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
107
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/cli_tool.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'cli_tool/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "cli_tool"
|
8
|
+
spec.version = CliTool::VERSION
|
9
|
+
spec.authors = ["Kelly Becker"]
|
10
|
+
spec.email = ["kellylsbkr@gmail.com"]
|
11
|
+
spec.description = %q{Have trouble with advanced command line options, software dependency presence validation, handling inputs, confirmations and colorizing? Then this gem is for you. It provides you with some modules you can include to add those specific features.}
|
12
|
+
spec.summary = %q{Tools to help with writing command line applications}
|
13
|
+
spec.homepage = "http://kellybecker.me"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "pry"
|
24
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'getoptlong'
|
2
|
+
|
3
|
+
module CliTool
|
4
|
+
module OptionParser
|
5
|
+
|
6
|
+
# Use to add the methods below to any class
|
7
|
+
def self.included(base)
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
# Map for symbol types
|
14
|
+
GOL_MAP = {
|
15
|
+
:none => GetoptLong::NO_ARGUMENT,
|
16
|
+
:optional => GetoptLong::OPTIONAL_ARGUMENT,
|
17
|
+
:required => GetoptLong::REQUIRED_ARGUMENT
|
18
|
+
}
|
19
|
+
|
20
|
+
# Create the options array
|
21
|
+
def options(opts = nil)
|
22
|
+
@@options ||= []
|
23
|
+
|
24
|
+
# If no options were passed then return
|
25
|
+
return @@options.uniq unless opts
|
26
|
+
|
27
|
+
_create_attrs_(opts)
|
28
|
+
@@options = @@options.concat(_create_gola_(opts)).uniq
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def _create_attrs_(opts)
|
34
|
+
|
35
|
+
# Get the option keys for attr creation
|
36
|
+
keys = opts.keys
|
37
|
+
|
38
|
+
# "symlink" the additional names to the original method
|
39
|
+
keys.each do |key|
|
40
|
+
default = nil
|
41
|
+
key = [key] unless key.is_a?(Array)
|
42
|
+
key.each_with_index do |k, i|
|
43
|
+
if i < 1
|
44
|
+
default = k.to_sym
|
45
|
+
attr_accessor(k.to_sym)
|
46
|
+
else
|
47
|
+
define_method("#{k}=", Proc.new { |x| send(default, x) })
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def _create_gola_(opts)
|
54
|
+
gola = []
|
55
|
+
|
56
|
+
# Loop through the options to create
|
57
|
+
# the GetoptLong configuration array
|
58
|
+
opts.each do |opt, details|
|
59
|
+
|
60
|
+
short = nil
|
61
|
+
dependency = :none
|
62
|
+
|
63
|
+
# If we have extended details determine them
|
64
|
+
if details.is_a?(Hash)
|
65
|
+
short = details[:short]
|
66
|
+
dependency = details[:dependency]
|
67
|
+
else
|
68
|
+
dependency ||= details
|
69
|
+
end
|
70
|
+
|
71
|
+
# Prepare the GetoptLong Array option
|
72
|
+
golao = []
|
73
|
+
golao << short if short
|
74
|
+
golao << GOL_MAP[dependency.to_sym]
|
75
|
+
|
76
|
+
# If the option has aliases then create
|
77
|
+
# additional GetoptLong Array options
|
78
|
+
if opt.is_a?(Array)
|
79
|
+
opt.each do |key|
|
80
|
+
golaot = golao.dup
|
81
|
+
golaot.unshift(key)
|
82
|
+
gola << golaot
|
83
|
+
end
|
84
|
+
else
|
85
|
+
golao.unshift(opt)
|
86
|
+
gola << golao
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
gola
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module CliTool
|
2
|
+
class MissingDependencies < StandardError; end;
|
3
|
+
|
4
|
+
module SoftwareDependencies
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.extend(ClassMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
|
12
|
+
# Create the options array
|
13
|
+
def software(*soft)
|
14
|
+
@@software ||= []
|
15
|
+
|
16
|
+
# If no software dependencies were passed then return
|
17
|
+
return @@software.uniq unless soft
|
18
|
+
|
19
|
+
# Find missing software
|
20
|
+
missing = []
|
21
|
+
soft.each do |app|
|
22
|
+
%x{which #{app}}
|
23
|
+
missing << app unless $?.success?
|
24
|
+
end
|
25
|
+
|
26
|
+
# Raise if there were any missing software's
|
27
|
+
unless missing.empty?
|
28
|
+
missing = missing.join(', ')
|
29
|
+
raise CliTool::MissingDependencies,
|
30
|
+
%{The required software packages "#{missing}" could not be found in your $PATH.}
|
31
|
+
end
|
32
|
+
|
33
|
+
# Append to the software list
|
34
|
+
@@software = @@software.concat(soft).uniq
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
|
3
|
+
module CliTool
|
4
|
+
module StdinOut
|
5
|
+
class MissingInput < StandardError; end;
|
6
|
+
|
7
|
+
ANSI_COLORS = {
|
8
|
+
:reset => 0,
|
9
|
+
:bold => 1,
|
10
|
+
:italic => 3,
|
11
|
+
:underline => 4,
|
12
|
+
:inverse => 7,
|
13
|
+
:strike => 9,
|
14
|
+
:bold_off => 22,
|
15
|
+
:italic_off => 23,
|
16
|
+
:underline_off => 24,
|
17
|
+
:inverse_off => 27,
|
18
|
+
:strike_off => 29,
|
19
|
+
:black => 30,
|
20
|
+
:red => 31,
|
21
|
+
:green => 32,
|
22
|
+
:yellow => 33,
|
23
|
+
:blue => 34,
|
24
|
+
:magenta => 35,
|
25
|
+
:purple => 35,
|
26
|
+
:cyan => 36,
|
27
|
+
:white => 37,
|
28
|
+
:default => 39,
|
29
|
+
:black_bg => 40,
|
30
|
+
:red_bg => 41,
|
31
|
+
:green_bg => 42,
|
32
|
+
:yellow_bg => 43,
|
33
|
+
:blue_bg => 44,
|
34
|
+
:magenta_bg => 45,
|
35
|
+
:purple_bg => 45,
|
36
|
+
:cyan_bg => 46,
|
37
|
+
:white_bg => 47,
|
38
|
+
:default_bg => 49
|
39
|
+
}
|
40
|
+
|
41
|
+
def self.included(base)
|
42
|
+
base.extend(ClassMethods)
|
43
|
+
base.__send__(:include, ClassMethods)
|
44
|
+
end
|
45
|
+
|
46
|
+
module ClassMethods
|
47
|
+
|
48
|
+
# Handle putsing of information (supports color and sleeps)
|
49
|
+
def puts(text, color = :reset, timer = nil)
|
50
|
+
|
51
|
+
# Process information for ANSI color codes
|
52
|
+
super(_colorize_(text, color))
|
53
|
+
|
54
|
+
# Sleep after displaying the message
|
55
|
+
if timer
|
56
|
+
puts(_colorize_("Sleeping for #{timer} seconds...", color))
|
57
|
+
sleep(timer)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def input(message = '', color = :reset, timer = nil, default = nil)
|
62
|
+
|
63
|
+
# Prompt for input
|
64
|
+
puts(message, color)
|
65
|
+
|
66
|
+
# Get the input from the CLI
|
67
|
+
gets = Proc.new do
|
68
|
+
STDIN.gets.strip
|
69
|
+
end
|
70
|
+
|
71
|
+
# Handle timing out
|
72
|
+
result = begin
|
73
|
+
if timer
|
74
|
+
Timeout::timeout(timer, &gets)
|
75
|
+
else
|
76
|
+
gets.call
|
77
|
+
end
|
78
|
+
rescue Timeout::Error # Verify that this is correct?
|
79
|
+
default
|
80
|
+
end
|
81
|
+
|
82
|
+
result
|
83
|
+
end
|
84
|
+
|
85
|
+
def confirm(message, color = :reset, default = :n, timer = nil)
|
86
|
+
|
87
|
+
# Handle the default value
|
88
|
+
default = "#{default}".downcase[0..0].to_sym
|
89
|
+
|
90
|
+
# Get the prompt
|
91
|
+
prompt = if default == :y
|
92
|
+
'Y/n'
|
93
|
+
else
|
94
|
+
'y/N'
|
95
|
+
end
|
96
|
+
|
97
|
+
begin
|
98
|
+
# Prompt for answer
|
99
|
+
result = input("#{message} [#{prompt}]", color, timer).strip
|
100
|
+
result = result.empty? ? default : result.downcase[0..0].to_sym
|
101
|
+
raise MissingInput unless [:y, :n].include?(result)
|
102
|
+
rescue MissingInput
|
103
|
+
puts "Sorry that input was not accepted", :red
|
104
|
+
retry
|
105
|
+
end
|
106
|
+
|
107
|
+
result
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def _colorize_(text, *color)
|
113
|
+
|
114
|
+
# Determine what to colors we should use
|
115
|
+
color = [:reset] if color.empty?
|
116
|
+
color = color.flatten
|
117
|
+
|
118
|
+
# Prepare the colorizing prefix for the text
|
119
|
+
prefix = color.inject('') do |o, c|
|
120
|
+
ANSI_COLORS[c] ? o << "\e[#{ANSI_COLORS[c]}m" : o
|
121
|
+
end
|
122
|
+
|
123
|
+
"#{prefix}#{text}\e[0m" # Add color
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
data/lib/cli_tool.rb
ADDED
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cli_tool
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kelly Becker
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-07-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Have trouble with advanced command line options, software dependency
|
56
|
+
presence validation, handling inputs, confirmations and colorizing? Then this gem
|
57
|
+
is for you. It provides you with some modules you can include to add those specific
|
58
|
+
features.
|
59
|
+
email:
|
60
|
+
- kellylsbkr@gmail.com
|
61
|
+
executables: []
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- .gitignore
|
66
|
+
- .pryrc
|
67
|
+
- Gemfile
|
68
|
+
- LICENSE.txt
|
69
|
+
- README.md
|
70
|
+
- Rakefile
|
71
|
+
- cli_tool.gemspec
|
72
|
+
- lib/cli_tool.rb
|
73
|
+
- lib/cli_tool/option_parser.rb
|
74
|
+
- lib/cli_tool/software_dependencies.rb
|
75
|
+
- lib/cli_tool/stdin_out.rb
|
76
|
+
- lib/cli_tool/version.rb
|
77
|
+
homepage: http://kellybecker.me
|
78
|
+
licenses:
|
79
|
+
- MIT
|
80
|
+
metadata: {}
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
requirements: []
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 2.0.2
|
98
|
+
signing_key:
|
99
|
+
specification_version: 4
|
100
|
+
summary: Tools to help with writing command line applications
|
101
|
+
test_files: []
|