runfile 0.3.4 → 0.3.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|