runfile 0.3.4 → 0.3.5
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.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/lib/runfile/action.rb +16 -16
- data/lib/runfile/docopt_helper.rb +72 -72
- data/lib/runfile/dsl.rb +49 -49
- data/lib/runfile/runfile_helper.rb +85 -85
- data/lib/runfile/runner.rb +128 -128
- data/lib/runfile/templates/Runfile +5 -5
- data/lib/runfile/util.rb +9 -9
- data/lib/runfile/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 222548480931d04a04df3ff85727d00b22f6da55
|
4
|
+
data.tar.gz: 47139374b01f97e8797295f22555cfe0389640e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed8ab0427040556585a8d2504dbf09e0ec29309f7c1fb4fd79866ef5c2d52d0d754815403ca99604025107ce07b1cdd9f221cd1513d72752ecc5a51c9017b6f3
|
7
|
+
data.tar.gz: a7184d573a3ead9707b14cf75a150fc40df54b102ef7a6481a8a4746b77b039a3dba5268fd163dd0a0f6e36b1566df3ef681f5d1a3dea8c2480aae5734713e83
|
data/README.md
CHANGED
@@ -59,7 +59,7 @@ Executing `run` without parameters, will show the usage patterns:
|
|
59
59
|
$ run
|
60
60
|
Usage:
|
61
61
|
run greet <name>
|
62
|
-
run (-h
|
62
|
+
run (-h|--help|--version)
|
63
63
|
```
|
64
64
|
|
65
65
|
Executing `run --help` will show the full help document (docopt)
|
@@ -70,7 +70,7 @@ Runfile 0.0.0
|
|
70
70
|
|
71
71
|
Usage:
|
72
72
|
run greet <name>
|
73
|
-
run (-h
|
73
|
+
run (-h|--help|--version)
|
74
74
|
|
75
75
|
Options:
|
76
76
|
-h --help
|
data/lib/runfile/action.rb
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
module Runfile
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
# The Action class represents a single Runfile action.
|
4
|
+
# This object holds all the information needed to execute it and
|
5
|
+
# show its help text (excluding the options, as they are considered
|
6
|
+
# global throughout the application)
|
7
|
+
class Action
|
8
|
+
attr :usage, :help
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
def initialize(block, usage, help)
|
11
|
+
@usage = usage
|
12
|
+
@help = help
|
13
|
+
@block = block
|
14
|
+
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
16
|
+
# Call the provided block
|
17
|
+
def execute(args)
|
18
|
+
@block.yield args
|
19
|
+
end
|
20
|
+
end
|
21
21
|
end
|
@@ -2,84 +2,84 @@ require 'docopt'
|
|
2
2
|
require 'colsole'
|
3
3
|
|
4
4
|
module Runfile
|
5
|
-
|
5
|
+
include Colsole
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
# The DocoptHelper class handles the dynamic generation of the
|
8
|
+
# docopt document and the docopt part of the execution (meaning,
|
9
|
+
# to call Docopt so it returns the parsed arguments or halts with
|
10
|
+
# usage message).
|
11
|
+
class DocoptHelper
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
13
|
+
# The constructor expects to get all the textual details
|
14
|
+
# needed to generate a docopt document (name, version,
|
15
|
+
# summary, options) and an array of Action objects.
|
16
|
+
def initialize(name, version, summary, actions, options)
|
17
|
+
@name = name
|
18
|
+
@version = version
|
19
|
+
@summary = summary
|
20
|
+
@actions = actions
|
21
|
+
@options = options
|
22
|
+
end
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
24
|
+
# Generate a document based on all the actions, help messages
|
25
|
+
# and options we have collected from the Runfile DSL.
|
26
|
+
def docopt
|
27
|
+
width, height = detect_terminal_size
|
28
|
+
doc = ["#{@name} #{@version}"]
|
29
|
+
doc << "#{@summary}" if @summary
|
30
|
+
doc += docopt_usage
|
31
|
+
doc += docopt_commands width
|
32
|
+
doc += docopt_options width
|
33
|
+
doc.join "\n"
|
34
|
+
end
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
36
|
+
# Return all docopt lines for the 'Usage' section
|
37
|
+
def docopt_usage
|
38
|
+
doc = ["\nUsage:"];
|
39
|
+
@actions.each do |name, action|
|
40
|
+
doc << " run #{action.usage}" unless action.usage == false
|
41
|
+
end
|
42
|
+
doc << " run (-h|--help|--version)\n"
|
43
|
+
doc
|
44
|
+
end
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
46
|
+
# Return all docopt lines for the 'Commands' section
|
47
|
+
def docopt_commands(width)
|
48
|
+
doc = []
|
49
|
+
caption_printed = false
|
50
|
+
@actions.each do |name, action|
|
51
|
+
action.help or next
|
52
|
+
doc << "Commands:" unless caption_printed
|
53
|
+
caption_printed = true
|
54
|
+
helpline = " #{action.help}"
|
55
|
+
wrapped = word_wrap helpline, width
|
56
|
+
doc << " #{action.usage}\n#{wrapped}\n" unless action.usage == false
|
57
|
+
end
|
58
|
+
doc
|
59
|
+
end
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
61
|
+
# Return all docopt lines for the various 'Options' sections
|
62
|
+
def docopt_options(width)
|
63
|
+
@options['Options'] = {} unless @options['Options']
|
64
|
+
@options['Options']['-h --help'] = 'Show this screen'
|
65
|
+
@options['Options']['--version'] = 'Show version number'
|
66
66
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
67
|
+
doc = []
|
68
|
+
@options.each do |scope, values|
|
69
|
+
doc << "#{scope}:"
|
70
|
+
values.each do |flag, text|
|
71
|
+
helpline = " #{text}"
|
72
|
+
wrapped = word_wrap helpline, width
|
73
|
+
doc << " #{flag}\n#{wrapped}\n"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
doc
|
77
|
+
end
|
78
78
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
79
|
+
# Call the docopt handler, which will either return a parsed
|
80
|
+
# arguments list, or halt execution and show usage.
|
81
|
+
def args(argv)
|
82
|
+
Docopt::docopt(docopt, version: @version, argv:argv)
|
83
|
+
end
|
84
|
+
end
|
85
85
|
end
|
data/lib/runfile/dsl.rb
CHANGED
@@ -4,53 +4,53 @@
|
|
4
4
|
|
5
5
|
# Smells of :reek:UtilityFunction
|
6
6
|
module Runfile
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
7
|
+
# Set the name of your Runfile program
|
8
|
+
def name(name)
|
9
|
+
Runner.instance.name = name
|
10
|
+
end
|
11
|
+
|
12
|
+
# Set the version of your Runfile program
|
13
|
+
def version(ver)
|
14
|
+
Runner.instance.version = ver
|
15
|
+
end
|
16
|
+
|
17
|
+
# Set the one line summary of your Runfile program
|
18
|
+
def summary(text)
|
19
|
+
Runner.instance.summary = text
|
20
|
+
end
|
21
|
+
|
22
|
+
# Set the usage pattern for the next action
|
23
|
+
def usage(text)
|
24
|
+
Runner.instance.last_usage = text
|
25
|
+
end
|
26
|
+
|
27
|
+
# Set the help message for the next action
|
28
|
+
def help(text)
|
29
|
+
Runner.instance.last_help = text
|
30
|
+
end
|
31
|
+
|
32
|
+
# Add an option/flag to the next action (can be called multiple
|
33
|
+
# times)
|
34
|
+
def option(flag, text, scope=nil)
|
35
|
+
Runner.instance.add_option flag, text, scope
|
36
|
+
end
|
37
|
+
|
38
|
+
# Define the action
|
39
|
+
def action(name, altname=nil, &block)
|
40
|
+
Runner.instance.add_action name, altname, &block
|
41
|
+
end
|
42
|
+
|
43
|
+
# Define a new command namespace
|
44
|
+
def command(name=nil)
|
45
|
+
Runner.instance.namespace = name
|
46
|
+
end
|
47
|
+
|
48
|
+
# Cross-call another action
|
49
|
+
def call(command_string)
|
50
|
+
Runner.instance.cross_call command_string
|
51
|
+
end
|
52
|
+
|
53
|
+
# Also allow to use 'endcommand' instead of 'command' to end
|
54
|
+
# a command namespace definition
|
55
|
+
alias_method :endcommand, :command
|
56
56
|
end
|
@@ -3,99 +3,99 @@ require 'pp'
|
|
3
3
|
|
4
4
|
module Runfile
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
6
|
+
# The RunfileHelper class assists in:
|
7
|
+
# 1. Finding named.runfiles
|
8
|
+
# 2. Creating new runfiles (`run make`)
|
9
|
+
# 3. Showing a list of found system runfiles in a colorful help
|
10
|
+
class RunfileHelper
|
11
|
+
|
12
|
+
# Handle the case when `run` is called without a Runfile
|
13
|
+
# present. We will let the user know they can type `run make`
|
14
|
+
# to create a new sample Runfile.
|
15
|
+
# If the first argument matches the name of a *.runfile name,
|
16
|
+
# we will return it to the caller. Otherwise, we return false
|
17
|
+
# to indicate "no further handling is needed".
|
18
|
+
def handle(argv)
|
19
|
+
# make a new runfile
|
20
|
+
if argv[0] == "make"
|
21
|
+
make_runfile argv[1]
|
22
|
+
return false
|
23
|
+
end
|
24
24
|
|
25
|
-
|
26
|
-
|
25
|
+
# get a list of *.runfile path-wide
|
26
|
+
runfiles = find_runfiles || []
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
# if first arg is a valid *.runfile, run it
|
29
|
+
if argv[0]
|
30
|
+
runfile = runfiles.select { |f| f[/#{argv[0]}.runfile/] }.first
|
31
|
+
runfile and return runfile
|
32
|
+
end
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
# if we are here, offer some help and advice
|
35
|
+
show_make_help runfiles
|
36
|
+
return false
|
37
|
+
end
|
38
38
|
|
39
|
-
|
39
|
+
private
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
41
|
+
# Create a new runfile in the current directory. We can either
|
42
|
+
# create a standard 'Runfile' or a 'named.runfile'.
|
43
|
+
def make_runfile(name=nil)
|
44
|
+
name = 'Runfile' if name.nil?
|
45
|
+
template = File.expand_path("../templates/Runfile", __FILE__)
|
46
|
+
name += ".runfile" unless name == 'Runfile'
|
47
|
+
dest = "#{Dir.pwd}/#{name}"
|
48
|
+
begin
|
49
|
+
File.write(dest, File.read(template))
|
50
|
+
puts "#{name} created."
|
51
|
+
rescue => e
|
52
|
+
abort "Failed creating #{name}\n#{e.message}"
|
53
|
+
end
|
54
|
+
end
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
56
|
+
# Find all *.runfile files in in our search difrectories
|
57
|
+
def find_runfiles
|
58
|
+
result = []
|
59
|
+
dirs = runfile_folders
|
60
|
+
dirs.each do |d|
|
61
|
+
found = Dir[File.join(d, '*.runfile')]
|
62
|
+
result << found unless found.empty?
|
63
|
+
end
|
64
|
+
return result.empty? ? false : result.flatten.uniq
|
65
|
+
end
|
66
66
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
67
|
+
# Show some helpful tips, and a list of available runfiles
|
68
|
+
def show_make_help(runfiles)
|
69
|
+
say "!txtpur!Runfile engine v#{Runfile::VERSION}"
|
70
|
+
runfiles.size < 3 and say "\nTip: Type '!txtblu!run make!txtrst!' or '!txtblu!run make name!txtrst!' to create a runfile.\nFor global access, place !txtblu!named.runfiles!txtrst! in ~/runfile/ or in /etc/runfile/ or anywhere in the PATH."
|
71
|
+
if runfiles.empty?
|
72
|
+
say "\n!txtred!Runfile not found."
|
73
|
+
else
|
74
|
+
say ""
|
75
|
+
say_runfile_list runfiles
|
76
|
+
end
|
77
|
+
end
|
78
78
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
79
|
+
# Return array of folders we should search for runfiles
|
80
|
+
def runfile_folders
|
81
|
+
dirs = path_dirs
|
82
|
+
dirs.insert 0, Dir.pwd, "#{Dir.home}/runfile", "/etc/runfile"
|
83
|
+
dirs
|
84
|
+
end
|
85
85
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
86
|
+
# Output the list of available runfiles
|
87
|
+
def say_runfile_list(runfiles)
|
88
|
+
max = runfiles.max_by(&:length).size
|
89
|
+
width, height = detect_terminal_size
|
90
|
+
runfiles.each do |f|
|
91
|
+
f[/([^\/]+).runfile$/]
|
92
|
+
command = "run #{$1}"
|
93
|
+
spacer_size = width - max - command.size - 6
|
94
|
+
spacer_size = [1, spacer_size].max
|
95
|
+
spacer = '.' * spacer_size
|
96
|
+
say " !txtgrn!#{command}!txtrst! #{spacer} #{f}"
|
97
|
+
end
|
98
|
+
end
|
99
99
|
|
100
|
-
|
100
|
+
end
|
101
101
|
end
|
data/lib/runfile/runner.rb
CHANGED
@@ -3,144 +3,144 @@ require 'pp'
|
|
3
3
|
|
4
4
|
module Runfile
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
6
|
+
# The Runner class is the main workhorse behind Runfile.
|
7
|
+
# It handles all the Runfile DSL commands and executes the
|
8
|
+
# Runfile with the help of two more specialized classes:
|
9
|
+
# 1. DocoptHelper - for deeper docopt related actions
|
10
|
+
# 2. RunfileHelper - for Runfile creation and system wide search
|
11
|
+
class Runner
|
12
|
+
attr_accessor :last_usage, :last_help, :name, :version,
|
13
|
+
:summary, :namespace, :superspace
|
14
14
|
|
15
|
-
|
15
|
+
@@instance = nil
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
17
|
+
# Initialize all variables to sensible defaults.
|
18
|
+
def initialize
|
19
|
+
@superspace = nil # used when filename != Runfile
|
20
|
+
@last_usage = nil # dsl: usage
|
21
|
+
@last_help = nil # dsl: help
|
22
|
+
@namespace = nil # dsl: command
|
23
|
+
@actions = {} # dsl: action
|
24
|
+
@options = {} # dsl: option
|
25
|
+
@name = "Runfile" # dsl: name
|
26
|
+
@version = "0.0.0" # dsl: version
|
27
|
+
@summary = false # dsl: summary
|
28
|
+
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
# Return a singleton Runner instance.
|
31
|
+
def self.instance
|
32
|
+
@@instance = self.new if @@instance.nil?
|
33
|
+
@@instance
|
34
|
+
end
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
36
|
+
# Load and execute a Runfile call.
|
37
|
+
def execute(argv, filename='Runfile')
|
38
|
+
File.file?(filename) or handle_no_runfile argv
|
39
|
+
begin
|
40
|
+
load filename
|
41
|
+
rescue => ex
|
42
|
+
abort "Runfile error:\n#{ex.message}\n#{ex.backtrace[0]}"
|
43
|
+
end
|
44
|
+
@@instance.run *argv
|
45
|
+
end
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
47
|
+
# Add an action to the @actions array, and use the last known
|
48
|
+
# usage and help messages sent by the DSL.
|
49
|
+
def add_action(name, altname=nil, &block)
|
50
|
+
if @last_usage.nil?
|
51
|
+
@last_usage = altname ? "(#{name}|#{altname})" : name
|
52
|
+
end
|
53
|
+
[@namespace, @superspace].each do |prefix|
|
54
|
+
prefix or next
|
55
|
+
name = "#{prefix}_#{name}"
|
56
|
+
@last_usage = "#{prefix} #{last_usage}" unless @last_usage == false
|
57
|
+
end
|
58
|
+
name = name.to_sym
|
59
|
+
@actions[name] = Action.new(block, @last_usage, @last_help)
|
60
|
+
@last_usage = nil
|
61
|
+
@last_help = nil
|
62
|
+
if altname
|
63
|
+
@last_usage = false
|
64
|
+
add_action(altname, nil, &block)
|
65
|
+
end
|
66
|
+
end
|
67
67
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
68
|
+
# Add an option flag and its help text.
|
69
|
+
def add_option(flag, text, scope=nil)
|
70
|
+
scope or scope = 'Options'
|
71
|
+
@options[scope] ||= {}
|
72
|
+
@options[scope][flag] = text
|
73
|
+
end
|
74
74
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
75
|
+
# Run the command. This is a wrapper around docopt. It will
|
76
|
+
# generate the docopt document on the fly, using all the
|
77
|
+
# information collected so far.
|
78
|
+
def run(*argv)
|
79
|
+
begin
|
80
|
+
docopt_exec argv
|
81
|
+
rescue Docopt::Exit => ex
|
82
|
+
puts ex.message
|
83
|
+
end
|
84
|
+
end
|
85
85
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
86
|
+
# Invoke action from another action. Used by the DSL's #call
|
87
|
+
# function. Expects to get a single string that looks as if
|
88
|
+
# it was typed in the command prompt.
|
89
|
+
def cross_call(command_string)
|
90
|
+
argv = command_string.split /\s(?=(?:[^"]|"[^"]*")*$)/
|
91
|
+
begin
|
92
|
+
docopt_exec argv
|
93
|
+
rescue Docopt::Exit => ex
|
94
|
+
puts "Cross call failed: #{command_string}"
|
95
|
+
abort ex.message
|
96
|
+
end
|
97
|
+
end
|
98
98
|
|
99
|
-
|
99
|
+
private
|
100
100
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
101
|
+
# Call the docopt parser and execute the action with the
|
102
|
+
# parsed arguments.
|
103
|
+
# This should always be called in a begin...rescue block and
|
104
|
+
# you should handle the Docopt::Exit exception.
|
105
|
+
def docopt_exec(argv)
|
106
|
+
helper = DocoptHelper.new(@name, @version, @summary, @actions, @options)
|
107
|
+
args = helper.args argv
|
108
|
+
action = find_action argv
|
109
|
+
action or abort "Runfile error: Action not found"
|
110
|
+
@actions[action].execute args
|
111
|
+
end
|
112
112
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
113
|
+
# Inspect the first three arguments in the argv and look for
|
114
|
+
# a matching action.
|
115
|
+
# We will first look for a_b_c action, then for a_b and
|
116
|
+
# finally for a. This is intended to allow "overloading" of
|
117
|
+
# the command as an action (e.g. also allow a global action
|
118
|
+
# called 'a').
|
119
|
+
# if no command was found, but we have a :global command,
|
120
|
+
# assume this is the requested one (since we will not reach
|
121
|
+
# this point unless the usage pattern matches).
|
122
|
+
def find_action(argv)
|
123
|
+
3.downto(1).each do |count|
|
124
|
+
next unless argv.size >= count
|
125
|
+
action = argv[0..count-1].join('_').to_sym
|
126
|
+
return action if @actions.has_key? action
|
127
|
+
end
|
128
|
+
return :global if @actions.has_key? :global
|
129
|
+
return false
|
130
|
+
end
|
131
131
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
132
|
+
# When `run` is called without a Runfile (or runfile not
|
133
|
+
# found), hand over handling to the RunfileHelper class.
|
134
|
+
# If will either return false if no further handling is needed
|
135
|
+
# on our part, or the name of a runfile to execute.
|
136
|
+
def handle_no_runfile(argv)
|
137
|
+
maker = RunfileHelper.new
|
138
|
+
runfile = maker.handle argv
|
139
|
+
if runfile
|
140
|
+
@superspace = argv[0]
|
141
|
+
execute argv, runfile
|
142
|
+
end
|
143
|
+
exit
|
144
|
+
end
|
145
|
+
end
|
146
146
|
end
|
@@ -6,9 +6,9 @@ usage "hello [<name> --color]"
|
|
6
6
|
help "Say hello"
|
7
7
|
option "-c --color", "Greet with color"
|
8
8
|
action :hello do |args|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
if args['--color']
|
10
|
+
say "!txtgrn!Hello #{args['<name>']}"
|
11
|
+
else
|
12
|
+
say "Hello #{args['<name>']}"
|
13
|
+
end
|
14
14
|
end
|
data/lib/runfile/util.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# Utility methods
|
2
2
|
module Runfile
|
3
|
-
|
3
|
+
# Debug print and exit
|
4
4
|
# Smells of :reek:UncommunicativeMethodName
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
def d(obj)
|
6
|
+
pp obj
|
7
|
+
exit
|
8
|
+
end
|
9
9
|
|
10
|
-
|
10
|
+
# Return an array of path directories
|
11
11
|
# Smells of :reek:UtilityFunction
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
def path_dirs
|
13
|
+
ENV['PATH'].split(File::PATH_SEPARATOR)
|
14
|
+
end
|
15
15
|
end
|
data/lib/runfile/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: runfile
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Danny Ben Shitrit
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-08-
|
11
|
+
date: 2015-08-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colsole
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '5.
|
47
|
+
version: '5.8'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '5.
|
54
|
+
version: '5.8'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: run-gem-dev
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|