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