lightning 0.2.1 → 0.3.0
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/CHANGELOG.rdoc +9 -0
- data/README.rdoc +53 -125
- data/Rakefile +14 -40
- data/bin/lightning +4 -0
- data/bin/lightning-complete +1 -10
- data/bin/lightning-translate +4 -0
- data/lib/lightning.rb +36 -50
- data/lib/lightning/bolt.rb +53 -26
- data/lib/lightning/builder.rb +87 -0
- data/lib/lightning/commands.rb +92 -69
- data/lib/lightning/commands/bolt.rb +63 -0
- data/lib/lightning/commands/core.rb +57 -0
- data/lib/lightning/commands/function.rb +76 -0
- data/lib/lightning/commands/shell_command.rb +38 -0
- data/lib/lightning/commands_util.rb +75 -0
- data/lib/lightning/completion.rb +72 -28
- data/lib/lightning/completion_map.rb +42 -39
- data/lib/lightning/config.rb +92 -57
- data/lib/lightning/function.rb +70 -0
- data/lib/lightning/generator.rb +77 -43
- data/lib/lightning/generators.rb +53 -0
- data/lib/lightning/generators/misc.rb +12 -0
- data/lib/lightning/generators/ruby.rb +32 -0
- data/lib/lightning/util.rb +70 -0
- data/lib/lightning/version.rb +3 -0
- data/test/bolt_test.rb +16 -28
- data/test/builder_test.rb +54 -0
- data/test/commands_test.rb +98 -0
- data/test/completion_map_test.rb +31 -54
- data/test/completion_test.rb +106 -36
- data/test/config_test.rb +22 -56
- data/test/function_test.rb +90 -0
- data/test/generator_test.rb +73 -0
- data/test/lightning.yml +26 -34
- data/test/test_helper.rb +80 -15
- metadata +42 -20
- data/VERSION.yml +0 -4
- data/bin/lightning-full_path +0 -18
- data/bin/lightning-install +0 -7
- data/lib/lightning/bolts.rb +0 -12
- data/lightning.yml.example +0 -87
- data/lightning_completions.example +0 -147
- data/test/lightning_test.rb +0 -58
@@ -0,0 +1,38 @@
|
|
1
|
+
module Lightning::Commands
|
2
|
+
protected
|
3
|
+
desc '(list [-a|--alias] | create SHELL_COMMAND [alias]| delete SHELL_COMMAND)',
|
4
|
+
'Commands for managing shell commands. Defaults to listing them.'
|
5
|
+
def shell_command(argv)
|
6
|
+
subcommand = argv.shift || 'list'
|
7
|
+
subcommand = %w{create delete list}.find {|e| e[/^#{subcommand}/]} || subcommand
|
8
|
+
shell_command_subcommand(subcommand, argv) if subcommand_has_required_args(subcommand, argv)
|
9
|
+
end
|
10
|
+
|
11
|
+
def shell_command_subcommand(subcommand, argv)
|
12
|
+
case subcommand
|
13
|
+
when 'list' then list_subcommand(:shell_commands, argv)
|
14
|
+
when 'create' then create_shell_command(argv[0], argv[1])
|
15
|
+
when 'delete' then delete_shell_command(argv[0])
|
16
|
+
else puts "Invalid subcommand '#{subcommand}'", command_usage
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_shell_command(scmd, scmd_alias=nil)
|
21
|
+
scmd_alias ||= scmd
|
22
|
+
if config.shell_commands.values.include?(scmd_alias)
|
23
|
+
puts "Alias '#{scmd_alias}' already exists for shell command '#{config.unaliased_command(scmd_alias)}'"
|
24
|
+
else
|
25
|
+
config.shell_commands[scmd] = scmd_alias
|
26
|
+
save_and_say "Added shell command '#{scmd}'"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def delete_shell_command(scmd)
|
31
|
+
if config.shell_commands[scmd]
|
32
|
+
config.shell_commands.delete scmd
|
33
|
+
save_and_say "Deleted shell command '#{scmd}' and its functions"
|
34
|
+
else
|
35
|
+
puts "Can't find shell command '#{scmd}'"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Lightning
|
2
|
+
# Utility methods to be used inside lightning commands.
|
3
|
+
module CommandsUtil
|
4
|
+
# Yields a block for an existing bolt or prints an error message
|
5
|
+
def if_bolt_found(bolt)
|
6
|
+
bolt = config.unalias_bolt(bolt)
|
7
|
+
config.bolts[bolt] ? yield(bolt) : puts("Can't find bolt '#{bolt}'")
|
8
|
+
end
|
9
|
+
|
10
|
+
# Prints a hash as a 2 column table sorted by keys
|
11
|
+
def print_sorted_hash(hash, indent=false)
|
12
|
+
offset = hash.keys.map {|e| e.size }.max + 2
|
13
|
+
offset += 1 unless offset % 2 == 0
|
14
|
+
indent_char = indent ? ' ' : ''
|
15
|
+
hash.sort.each do |k,v|
|
16
|
+
puts "#{indent_char}#{k}" << ' ' * (offset - k.size) << (v || '')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Saves config and prints message
|
21
|
+
def save_and_say(message)
|
22
|
+
config.save
|
23
|
+
puts message
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [nil, true] Determines if command has required arguments
|
27
|
+
def command_has_required_args(argv, required)
|
28
|
+
return true if argv.size >= required
|
29
|
+
puts "'lightning #{@command}' was called incorrectly.", command_usage
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [nil, true] Determines if subcommand has required arguments
|
33
|
+
def subcommand_has_required_args(subcommand, argv)
|
34
|
+
return true if argv.size >= (subcommand_required_args[subcommand] || 0)
|
35
|
+
puts "'lightning #{@command} #{subcommand}' was called incorrectly.", command_usage
|
36
|
+
end
|
37
|
+
|
38
|
+
# Parses arguments into non-option arguments and hash of options. Options can have
|
39
|
+
# values with an equal sign i.e. '--option=value'. Options without a value are set to true.
|
40
|
+
# @param [Array]
|
41
|
+
# @return [Array<Array, Hash>] Hash of options has symbolic keys
|
42
|
+
def parse_args(args)
|
43
|
+
options, args = args.partition {|e| e =~ /^-/ }
|
44
|
+
options = options.inject({}) do |hash, flag|
|
45
|
+
key, value = flag.split('=')
|
46
|
+
hash[key.sub(/^--?/,'').intern] = value.nil? ? true : value
|
47
|
+
hash
|
48
|
+
end
|
49
|
+
[args, options]
|
50
|
+
end
|
51
|
+
|
52
|
+
# Shortcut to Lightning.config
|
53
|
+
def config; Lightning.config; end
|
54
|
+
|
55
|
+
# Lists a bolt or shell_command with optional --alias
|
56
|
+
def list_subcommand(list_type, argv)
|
57
|
+
if %w{-a --alias}.include?(argv[0])
|
58
|
+
hash = config.send(list_type)
|
59
|
+
hash = hash.inject({}) {|a,(k,v)| a[k] = v['alias']; a } if list_type == :bolts
|
60
|
+
print_sorted_hash hash
|
61
|
+
else
|
62
|
+
puts config.send(list_type).keys.sort
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
def subcommand_required_args
|
68
|
+
desc_array[0].split('|').inject({}) {|a,e|
|
69
|
+
cmd, *args = e.strip.split(/\s+/)
|
70
|
+
a[cmd] = args.select {|e| e[/^[A-Z]/]}.size
|
71
|
+
a
|
72
|
+
}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/lightning/completion.rb
CHANGED
@@ -1,43 +1,87 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require 'shellwords'
|
2
|
+
|
3
|
+
module Lightning
|
4
|
+
# This class returns completions for the last word typed for a given lightning function and its {Function} object.
|
5
|
+
# Inspired loosely by ryanb[http://github.com/ryanb/dotfiles/tree/master/bash/completion_scripts/project_completion].
|
6
|
+
#
|
7
|
+
# == Regex Completion
|
8
|
+
# By default, regular expressions can be used while completing to filter/match possible completions. For duplicate
|
9
|
+
# paths that offer their full paths in completion, this means their full paths can also match. One non-regexp
|
10
|
+
# shorthand is that a '*' is converted to '.*' for glob-like behavior.To revert to standard completion, toggle
|
11
|
+
# Lightning.config[:complete_regex].
|
4
12
|
class Completion
|
5
|
-
|
6
|
-
|
13
|
+
# @return [Array] Returns completions that match last word typed
|
14
|
+
def self.complete(text_to_complete, function, shellescape=true)
|
15
|
+
return error_array("No function found to complete.") unless function
|
16
|
+
new(text_to_complete, function, shellescape).matches
|
7
17
|
end
|
8
|
-
|
9
|
-
|
18
|
+
|
19
|
+
# @return [Array] Constructs completion error message. More than one element long to ensure error message
|
20
|
+
# gets displayed and not completed
|
21
|
+
def self.error_array(message)
|
22
|
+
["#Error: #{message}", "Please open an issue."]
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(text_typed, function, shellescape=true)
|
10
26
|
@text_typed = text_typed
|
11
|
-
@
|
27
|
+
@function = function
|
28
|
+
@shellescape = shellescape
|
12
29
|
end
|
13
30
|
|
31
|
+
# @return [Array] Main method to determine and return completions that match
|
14
32
|
def matches
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
33
|
+
matched = get_matches(possible_completions)
|
34
|
+
matched = match_when_completing_subdirectories(matched)
|
35
|
+
@shellescape ? matched.map {|e| Util.shellescape(e) } : matched
|
36
|
+
rescue SystemCallError
|
37
|
+
self.class.error_array("Nonexistent directory.")
|
38
|
+
rescue RegexpError
|
39
|
+
self.class.error_array("Invalid regular expression.")
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param [Array]
|
43
|
+
# @return [Array] Selects possible completions that match using {Completion#typed typed}
|
44
|
+
def get_matches(possible)
|
45
|
+
Lightning.config[:complete_regex] ? possible.grep(/^#{blob_to_regex(typed)}/) :
|
46
|
+
possible.select {|e| e[0, typed.length] == typed }
|
47
|
+
end
|
48
|
+
|
49
|
+
# @param [Array]
|
50
|
+
# @return [Array] Generates completions when completing a directory above or below a basename
|
51
|
+
def match_when_completing_subdirectories(matched)
|
52
|
+
if matched.empty? && (top_dir = typed[/^([^\/]+)\//,1]) && !typed.include?('//')
|
53
|
+
matched = possible_completions.grep(/^#{top_dir}/)
|
54
|
+
|
55
|
+
# for typed = some/dir/file, top_dir = path and translated_dir = /full/bolt/path
|
56
|
+
if matched.size == 1 && (translated_dir = @function.translate([top_dir])[0])
|
57
|
+
short_dir = typed.sub(/\/([^\/]+)?$/, '') # some/dir
|
58
|
+
completed_dir = short_dir.sub(top_dir, translated_dir) #/full/bolt/path/some/dir
|
59
|
+
completed_dir = File.expand_path(completed_dir) if completed_dir[/\/\.\.($|\/)/]
|
60
|
+
matched = Dir.entries(completed_dir).delete_if {|e| %w{. ..}.include?(e) }.map {|f|
|
61
|
+
File.directory?(completed_dir+'/'+f) ? File.join(short_dir,f) +'/' : File.join(short_dir,f)
|
62
|
+
}
|
63
|
+
matched = get_matches(matched)
|
24
64
|
end
|
25
65
|
end
|
66
|
+
matched
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return [String] Last word typed by user
|
70
|
+
def typed
|
71
|
+
@typed ||= begin
|
72
|
+
args = Shellwords.shellwords(@text_typed)
|
73
|
+
!args[-1][/\s+/] && @text_typed[/\s+$/] ? '' : args[-1]
|
74
|
+
end
|
26
75
|
end
|
27
|
-
|
28
|
-
#
|
76
|
+
|
77
|
+
# @private Converts * to .* to make a glob-like regex when in regex completion mode
|
29
78
|
def blob_to_regex(string)
|
30
79
|
string.gsub(/^\*|([^\.])\*/) {|e| $1 ? $1 + ".*" : ".*" }
|
31
80
|
end
|
32
|
-
|
33
|
-
|
34
|
-
# @text_typed[/\s(.+?)$/, 1] || ''
|
35
|
-
text = @text_typed[/^(\S+)\s+(#{Lightning::TEST_FLAG})?\s*(.+?)$/, 3] || ''
|
36
|
-
text.strip
|
37
|
-
end
|
38
|
-
|
81
|
+
|
82
|
+
protected
|
39
83
|
def possible_completions
|
40
|
-
|
41
|
-
end
|
84
|
+
@function.completions
|
85
|
+
end
|
42
86
|
end
|
43
87
|
end
|
@@ -1,59 +1,62 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module Lightning
|
2
|
+
# Maps completions (file basenames) and aliases to their full paths given a {Bolt} object's globs.
|
3
3
|
class CompletionMap
|
4
|
+
DUPLICATE_DELIMITER = '//'
|
5
|
+
# @return [Array] Regular expression paths to ignore. By default paths ending in . or .. are ignored.
|
6
|
+
def self.ignore_paths
|
7
|
+
@ignore_paths ||= (Lightning.config[:ignore_paths] || []) + %w{\.\.?$}
|
8
|
+
end
|
9
|
+
|
10
|
+
# Sets ignore_paths
|
11
|
+
def self.ignore_paths=(val)
|
12
|
+
@ignore_paths = val
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [Hash] Maps file basenames to full paths
|
4
16
|
attr_accessor :map
|
17
|
+
# @return [Hash] Maps aliases to full paths
|
5
18
|
attr_reader :alias_map
|
6
19
|
|
7
20
|
def initialize(*globs)
|
8
21
|
options = globs[-1].is_a?(Hash) ? globs.pop : {}
|
9
22
|
globs.flatten!
|
10
|
-
@map =
|
11
|
-
@alias_map =
|
23
|
+
@map = create_globbed_map(globs)
|
24
|
+
@alias_map = options[:aliases] || {}
|
12
25
|
end
|
13
|
-
|
26
|
+
|
27
|
+
# @return [String] Fetches full path of file or alias
|
14
28
|
def [](completion)
|
15
29
|
@map[completion] || @alias_map[completion]
|
16
30
|
end
|
17
|
-
|
31
|
+
|
32
|
+
# @return [Array] List of unique basenames and aliases
|
18
33
|
def keys
|
19
34
|
(@map.keys + @alias_map.keys).uniq
|
20
35
|
end
|
21
|
-
|
22
|
-
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
globs.
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
37
|
-
else
|
38
|
-
path_hash[basename] = e
|
39
|
-
end
|
40
|
-
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
def create_globbed_map(globs)
|
39
|
+
duplicates = {}
|
40
|
+
ignore_regexp = /(#{self.class.ignore_paths.join('|')})/
|
41
|
+
globs.map {|e| Dir.glob(e, File::FNM_DOTMATCH)}.flatten.uniq.
|
42
|
+
inject({}) do |acc, file|
|
43
|
+
basename = File.basename file
|
44
|
+
next acc if file =~ ignore_regexp
|
45
|
+
if duplicates[basename]
|
46
|
+
duplicates[basename] << file
|
47
|
+
elsif acc.key?(basename)
|
48
|
+
duplicates[basename] = [acc.delete(basename), file]
|
49
|
+
else
|
50
|
+
acc[basename] = file
|
41
51
|
end
|
42
|
-
|
43
|
-
|
44
|
-
path_hash
|
52
|
+
acc
|
53
|
+
end.merge create_resolved_duplicates(duplicates)
|
45
54
|
end
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
paths.each do |e|
|
51
|
-
new_key = "#{key}/#{File.dirname(e)}"
|
52
|
-
path_hash[new_key] = e
|
53
|
-
end
|
54
|
-
path_hash.delete(key)
|
55
|
+
|
56
|
+
def create_resolved_duplicates(duplicates)
|
57
|
+
duplicates.inject({}) do |hash, (basename, paths)|
|
58
|
+
paths.each {|e| hash["#{basename}#{DUPLICATE_DELIMITER}#{File.dirname(e)}"] = e }; hash
|
55
59
|
end
|
56
60
|
end
|
57
|
-
|
58
61
|
end
|
59
62
|
end
|
data/lib/lightning/config.rb
CHANGED
@@ -1,72 +1,107 @@
|
|
1
|
-
|
1
|
+
require 'yaml'
|
2
|
+
module Lightning
|
3
|
+
# Handles config file used to generate bolts and functions.
|
4
|
+
# The config file is in YAML so it's easy to manually edit. Nevertheless, it's recommended to modify
|
5
|
+
# the config through lightning commands since their API is more stable than the config file's API.
|
6
|
+
#
|
7
|
+
# == Config File Format
|
8
|
+
#
|
9
|
+
# Top level keys:
|
10
|
+
#
|
11
|
+
# * *:source_file*: Location of shell file generated by {Builder}. Defaults to ~/.lightning/functions.sh
|
12
|
+
# * *:ignore_paths*: Array of paths to globally ignore when generating possible completions
|
13
|
+
# * *:complete_regex*: true or false (default is true). When true, regular expressions can be used while
|
14
|
+
# completing. See {Completion} for more details.
|
15
|
+
# * *:shell*: Specifies shell Builder uses to generate completions. Defaults to bash.
|
16
|
+
# * *:bolts*: Array of bolts with each bolt being a hash with the following keys:
|
17
|
+
# * *name*(required): Unique name
|
18
|
+
# * *alias*: Abbreviated name which can be used to reference bolt in most lightning commands. This is used
|
19
|
+
# over name when generating function names.
|
20
|
+
# * *global*: true or false (default is false). When set, uses bolt to generate functions with each command
|
21
|
+
# in :shell_commands.
|
22
|
+
# * *globs*(required): Array of globs which defines group of paths bolt handles
|
23
|
+
# * *functions*: Array of lightning functions. A function can either be a string (shell command with default
|
24
|
+
# options) or a hash with the following keys:
|
25
|
+
# * *name*: Name of the lightning function
|
26
|
+
# * *shell_command*(required): Shell command with default options which this function wraps
|
27
|
+
# * *aliases*: A hash of custom aliases and full paths only for this function
|
28
|
+
# * *post_path*: String to add immediately after a resolved path
|
29
|
+
# * *:shell_commands*: Hash of global shell commands which are combined with all global bolts to generate functions
|
2
30
|
class Config < ::Hash
|
3
31
|
class <<self
|
4
32
|
attr_accessor :config_file
|
33
|
+
# @return [String] ~/.lightningrc
|
5
34
|
def config_file
|
6
|
-
@config_file ||=
|
35
|
+
@config_file ||= File.join(Lightning.home,".lightningrc")
|
7
36
|
end
|
8
37
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
configure_commands_and_paths(obj) if options[:read_only]
|
13
|
-
obj
|
14
|
-
end
|
15
|
-
|
16
|
-
def read_config_file(file=nil)
|
17
|
-
default_config = {'shell'=>'bash', 'generated_file'=>File.expand_path(File.join('~', '.lightning_completions')),
|
18
|
-
'complete_regex'=>true}
|
19
|
-
@config_file = file if file
|
20
|
-
hash = YAML::load_file(config_file)
|
21
|
-
default_config.merge(hash)
|
22
|
-
end
|
23
|
-
|
24
|
-
def commands_to_bolt_key(map_to_command, new_command)
|
25
|
-
"#{map_to_command}-#{new_command}"
|
26
|
-
end
|
27
|
-
|
28
|
-
def configure_commands_and_paths(hash)
|
29
|
-
hash[:paths] ||= {}
|
30
|
-
hash[:commands].each do |e|
|
31
|
-
#mapping a referenced path
|
32
|
-
if e['paths'].is_a?(String)
|
33
|
-
e['bolt_key'] = e['paths'].dup
|
34
|
-
end
|
35
|
-
#create a path entry + key if none exists
|
36
|
-
if e['bolt_key'].nil?
|
37
|
-
#extract command in case it has options after it
|
38
|
-
e['map_to'] =~ /\s*(\w+)/
|
39
|
-
bolt_key = commands_to_bolt_key($1, e['name'])
|
40
|
-
e['bolt_key'] = bolt_key
|
41
|
-
hash[:paths][bolt_key] = e['paths'] || []
|
42
|
-
end
|
43
|
-
end
|
44
|
-
hash
|
38
|
+
# @return [Hash] Creates a bolt hash given globs
|
39
|
+
def bolt(globs)
|
40
|
+
{'globs'=>globs.map {|e| e.sub(/^~/, Lightning.home) }}
|
45
41
|
end
|
46
42
|
end
|
47
|
-
|
48
|
-
def save
|
49
|
-
File.open(self.class.config_file, "w") { |f| f.puts self.to_hash.to_yaml }
|
50
|
-
end
|
51
43
|
|
52
|
-
|
44
|
+
DEFAULT = {:complete_regex=>true, :bolts=>{}, :shell_commands=>{'cd'=>'cd', 'echo'=>'echo'} }
|
45
|
+
attr_accessor :source_file
|
46
|
+
def initialize(hash=read_config_file)
|
47
|
+
hash = DEFAULT.merge hash
|
53
48
|
super
|
54
49
|
replace(hash)
|
55
|
-
self.replace(self.symbolize_keys)
|
56
50
|
end
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
51
|
+
|
52
|
+
# @return [String] Shell file generated by Builder. Defaults to ~/.lightning/functions.sh
|
53
|
+
def source_file
|
54
|
+
@source_file ||= self[:source_file] || File.join(Lightning.dir, 'functions.sh')
|
61
55
|
end
|
62
|
-
|
63
|
-
#
|
64
|
-
def
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
56
|
+
|
57
|
+
# @return [Array] Global shell commands used to generate Functions for all Bolts.
|
58
|
+
def global_commands
|
59
|
+
shell_commands.keys
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [Hash] Maps shell command names to their aliases
|
63
|
+
def shell_commands
|
64
|
+
self[:shell_commands]
|
65
|
+
end
|
66
|
+
|
67
|
+
# @return [Hash] Maps bolt names to their config hashes
|
68
|
+
def bolts
|
69
|
+
self[:bolts]
|
70
|
+
end
|
71
|
+
|
72
|
+
# @return [String] Converts shell command alias to shell command
|
73
|
+
def unaliased_command(cmd)
|
74
|
+
shell_commands.invert[cmd] || cmd
|
75
|
+
end
|
76
|
+
|
77
|
+
# @return [String] Converts bolt alias to bolt's name
|
78
|
+
def unalias_bolt(bolt)
|
79
|
+
bolts[bolt] ? bolt : (Array(bolts.find {|k,v| v['alias'] == bolt })[0] || bolt)
|
80
|
+
end
|
81
|
+
|
82
|
+
# @return [String] Extracts shell command from a shell_command string
|
83
|
+
def only_command(shell_command)
|
84
|
+
shell_command[/\w+/]
|
85
|
+
end
|
86
|
+
|
87
|
+
# @return [String] Creates a command name from its shell command and bolt in the form "#{command}-#{bolt}".
|
88
|
+
# Uses aliases for either if they exist.
|
89
|
+
def function_name(shell_command, bolt)
|
90
|
+
cmd = only_command shell_command
|
91
|
+
"#{shell_commands[cmd] || cmd}-#{bolt}"
|
92
|
+
end
|
93
|
+
|
94
|
+
# Saves config to Config.config_file
|
95
|
+
def save
|
96
|
+
File.open(self.class.config_file, "w") {|f| f.puts Hash.new.replace(self).to_yaml }
|
97
|
+
end
|
98
|
+
|
99
|
+
protected
|
100
|
+
def read_config_file
|
101
|
+
File.exists?(self.class.config_file) ?
|
102
|
+
Util.symbolize_keys(YAML::load_file(self.class.config_file)) : {}
|
103
|
+
rescue
|
104
|
+
raise $!.message.sub('syntax error', "Syntax error in '#{Config.config_file}'")
|
69
105
|
end
|
70
|
-
|
71
106
|
end
|
72
|
-
end
|
107
|
+
end
|