lightning 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,8 @@
1
+ == 0.3.2
2
+ * Better tests
3
+ * Added a manpage
4
+ * All command options can be abbreviated
5
+
1
6
  == 0.3.1
2
7
  * Fixed lightning function create bug
3
8
 
@@ -1,5 +1,5 @@
1
1
  == Description
2
- Lightning is a commandline framework that could revolutionize how fast you are on the commandline. Lightning let’s you easily define and generate shell functions which autocomplete and interpret paths (files and directories) by their basenames. With these functions you don’t have to ever type the full path to any file for any command again.
2
+ Lightning is a commandline framework that lets users wrap commands with shell functions that are able to refer to any filesystem path by its basename. To achieve this, a group of paths to be translated are defined with shell globs. These shell globs, known as a lightning _bolt_, are then applied to commands to produce functions. In addition to translating basenames to full paths, lightning _functions_ can autocomplete these basenames, resolve conflicts if they have the same name, leave any non-basename arguments untouched, and autocomplete directories above and below a basename. To make bolts shareable between users and functions easier to create, lightning has _generators_. A _generator_ generates filesystem-specific globs for a bolt. Lightning comes with some default generators. Users can make their own generators with generator plugins placed under ~/.lightning/generators/.
3
3
 
4
4
  == Intro
5
5
  Lightning generates shell functions which can interpret paths by their basenames. So instead of carpal-typing
@@ -59,6 +59,18 @@ Once lightning is installed, we need to do a one-time setup:
59
59
  # or for zsh
60
60
  echo source ~/.lightning/functions.sh >> ~/.zshrc
61
61
 
62
+ To install and view lightning's man page:
63
+
64
+ # If installed with rip
65
+ $ LDIR=`ruby -rrip -e 'puts Rip::PackageManager.new.package("lightning").cache_path'`
66
+ # Assumes /usr/local/man is in $MANPATH
67
+ $ cp $LDIR/man/lightning.1 /usr/local/man/man1/
68
+ $ man lightning
69
+
70
+ # If installed with rubygems
71
+ $ sudo gem install gem-man
72
+ $ gem man lightning
73
+
62
74
  == Bugs/Issues
63
75
  Please report them {on github}[http://github.com/cldwalker/lightning/issues].
64
76
 
@@ -68,12 +80,13 @@ Please report them {on github}[http://github.com/cldwalker/lightning/issues].
68
80
 
69
81
  == Credits
70
82
  * ryanb's dotfiles inspired tinkering with autocompletion in ruby: http://github.com/ryanb/dotfiles/blob/master/bash/completion_scripts/project_completion
71
- * defunkt's rip, http://github.com/defunkt/rip, was inflential in designing plugins
83
+ * defunkt's rip, http://github.com/defunkt/rip, was influential in designing plugins
72
84
  * Bug fixes: ljsc
73
85
 
86
+ == Links
87
+ * http://tagaholic.me/2010/04/08/lightning-speed-for-your-shell.html
88
+ * http://tagaholic.me/2010/04/09/lightning-speed-for-the-user.html
89
+
74
90
  == Todo
75
- * More tests
76
- * Manpage
77
- * Consider underscore anchored autocompletion i.e. textmate style file search
78
91
  * Possible aliasing of paths per function, bolt or global
79
92
  * Possible irb builder using bond
data/Rakefile CHANGED
@@ -20,11 +20,11 @@ begin
20
20
  s.version = Lightning::VERSION
21
21
  s.executables = ['lightning', 'lightning-complete', 'lightning-translate']
22
22
  s.summary = "Lightning is a commandline framework that generates shell functions which wrap around commands to autocomplete and translate full paths by their basenames."
23
- s.description = "Lightning is a commandline framework that changes how you use paths in your filesystem. Lightning generates shell functions which wrap any command with the ability to autocomplete and interpret paths simply by their basenames. With these functions you don't have to ever type the full path to any file for any command again."
23
+ s.description = "Lightning is a commandline framework that lets users wrap commands with shell functions that are able to refer to any filesystem path by its basename. To achieve this, a group of paths to be translated are defined with shell globs. These shell globs, known as a lightning _bolt_, are then applied to commands to produce functions. In addition to translating basenames to full paths, lightning _functions_ can autocomplete these basenames, resolve conflicts if they have the same name, leave any non-basename arguments untouched, and autocomplete directories above and below a basename."
24
24
  s.email = "gabriel.horner@gmail.com"
25
25
  s.homepage = "http://tagaholic.me/lightning"
26
26
  s.authors = ["Gabriel Horner"]
27
- s.files = FileList["CHANGELOG.rdoc", "Rakefile","README.rdoc", "LICENSE.txt", "{bin,lib,test}/**/*"]
27
+ s.files = FileList["CHANGELOG.rdoc", "Rakefile","README.rdoc", "LICENSE.txt", "{bin,lib,test,man}/**/*"]
28
28
  s.has_rdoc = 'yard'
29
29
  s.rdoc_options = ['--title', "Lightning #{Lightning::VERSION} Documentation"]
30
30
  s.rubyforge_project = 'tagaholic'
@@ -4,27 +4,28 @@ module Lightning::Commands
4
4
  "generate BOLT [generator] [-t|--test] | global ON_OR_OFF BOLTS | show BOLT)",
5
5
  "Commands for managing bolts. Defaults to listing them."
6
6
  def bolt(argv)
7
- subcommand = argv.shift || 'list'
8
- subcommand = %w{alias create delete generate global list show}.find {|e| e[/^#{subcommand}/]} || subcommand
9
- bolt_subcommand(subcommand, argv) if subcommand_has_required_args(subcommand, argv)
7
+ call_subcommand(argv, %w{alias create delete generate global list show}) do |scmd, argv|
8
+ case scmd
9
+ when 'list' then list_bolts(argv)
10
+ when 'create' then create_bolt(argv.shift, argv)
11
+ when 'alias' then alias_bolt(argv[0], argv[1])
12
+ when 'delete' then delete_bolt(argv[0])
13
+ when 'show' then show_bolt(argv[0])
14
+ when 'global' then globalize_bolts(argv.shift, argv)
15
+ when 'generate' then generate_bolt(argv)
16
+ end
17
+ end
10
18
  end
11
19
 
12
- def bolt_subcommand(subcommand, argv)
13
- case subcommand
14
- when 'list' then list_subcommand(:bolts, argv)
15
- when 'create' then create_bolt(argv.shift, argv)
16
- when 'alias' then alias_bolt(argv[0], argv[1])
17
- when 'delete' then delete_bolt(argv[0])
18
- when 'show' then show_bolt(argv[0])
19
- when 'global' then globalize_bolts(argv.shift, argv)
20
- when 'generate' then generate_bolt(argv)
21
- else puts "Invalid subcommand '#{subcommand}'", command_usage
22
- end
20
+ def list_bolts(argv)
21
+ args, options = parse_args argv, %w{alias}
22
+ options[:alias] ? print_sorted_hash(config.bolts.inject({}) {|a,(k,v)| a[k] = v['alias']; a }) :
23
+ puts(config.bolts.keys.sort)
23
24
  end
24
25
 
25
26
  def generate_bolt(argv)
26
- args, options = parse_args argv
27
- Lightning::Generator.run(args[0], :once=>args[1], :test=>options[:test] || options[:t])
27
+ args, options = parse_args argv, %w{test}
28
+ Lightning::Generator.run(args[0], :once=>args[1], :test=>options[:test])
28
29
  end
29
30
 
30
31
  def create_bolt(bolt, globs)
@@ -32,7 +32,7 @@ module Lightning
32
32
  desc "[--file=FILE] [--shell=SHELL]",
33
33
  "Builds shell functions and installs them into FILE to be sourced by shell."
34
34
  def install(argv)
35
- args, options = parse_args(argv)
35
+ args, options = parse_args(argv, %w{file shell})
36
36
  config[:shell] = options[:shell] if options[:shell]
37
37
  config.source_file = options[:file] if options[:file]
38
38
 
@@ -3,24 +3,20 @@ module Lightning::Commands
3
3
  desc '(list [--command=SHELL_COMMAND] [--bolt=BOLT] | create SHELL_COMMAND BOLT [function] | delete FUNCTION)',
4
4
  'Commands for managing functions. Defaults to listing them.'
5
5
  def function(argv)
6
- subcommand = argv.shift || 'list'
7
- subcommand = %w{create delete list}.find {|e| e[/^#{subcommand}/]} || subcommand
8
- function_subcommand(subcommand, argv) if subcommand_has_required_args(subcommand, argv)
9
- end
10
-
11
- def function_subcommand(subcommand, argv)
12
- case subcommand
13
- when 'list' then list_function(argv)
14
- when 'create' then create_function_and_bolt(argv)
15
- when 'delete' then delete_function argv.shift
16
- else puts "Invalid subcommand '#{subcommand}'", command_usage
6
+ call_subcommand(argv, %w{create delete list}) do |subcommand, argv|
7
+ case subcommand
8
+ when 'list' then list_function(argv)
9
+ when 'create' then create_function_and_bolt(argv)
10
+ when 'delete' then delete_function argv.shift
11
+ end
17
12
  end
18
13
  end
19
14
 
20
15
  def list_function(argv)
21
- args, options = parse_args argv
16
+ args, options = parse_args argv, %w{bolt command}
22
17
  functions = if options[:bolt]
23
- Lightning.functions.values.select {|e| e.bolt.name == options[:bolt] }.map {|e| e.name}
18
+ bolt = config.unalias_bolt(options[:bolt])
19
+ Lightning.functions.values.select {|e| e.bolt.name == bolt }.map {|e| e.name}
24
20
  elsif options[:command]
25
21
  Lightning.functions.values.select {|e| e.shell_command == options[:command] }.map {|e| e.name}
26
22
  else
@@ -3,18 +3,18 @@ module Lightning::Commands
3
3
  desc '(list [-a|--alias] | create SHELL_COMMAND [alias]| delete SHELL_COMMAND)',
4
4
  'Commands for managing shell commands. Defaults to listing them.'
5
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)
6
+ call_subcommand(argv, %w{create delete list}) do |scmd, argv|
7
+ case scmd
8
+ when 'list' then list_shell_commands(argv)
9
+ when 'create' then create_shell_command(argv[0], argv[1])
10
+ when 'delete' then delete_shell_command(argv[0])
11
+ end
12
+ end
9
13
  end
10
14
 
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
15
+ def list_shell_commands(argv)
16
+ args, options = parse_args argv, %w{alias}
17
+ options[:alias] ? print_sorted_hash(config.shell_commands) : puts(config.shell_commands.keys.sort)
18
18
  end
19
19
 
20
20
  def create_shell_command(scmd, scmd_alias=nil)
@@ -23,7 +23,7 @@ module Lightning::Commands
23
23
  puts "Alias '#{scmd_alias}' already exists for shell command '#{config.unaliased_command(scmd_alias)}'"
24
24
  else
25
25
  config.shell_commands[scmd] = scmd_alias
26
- save_and_say "Added shell command '#{scmd}'"
26
+ save_and_say "Created shell command '#{scmd}'"
27
27
  end
28
28
  end
29
29
 
@@ -23,27 +23,33 @@ module Lightning
23
23
  puts message
24
24
  end
25
25
 
26
+ # Handles abbreviated subcommands and printing errors for invalid subcommands.
27
+ # Defaults to 'list' subcommand if none given.
28
+ def call_subcommand(argv, cmds)
29
+ subcommand = argv.shift || 'list'
30
+ (subcmd = cmds.find {|e| e[/^#{subcommand}/]}) ?
31
+ subcommand_has_required_args(subcmd, argv) && yield(subcmd, argv) :
32
+ puts("Invalid subcommand '#{subcommand}'", command_usage)
33
+ end
34
+
26
35
  # @return [nil, true] Determines if command has required arguments
27
36
  def command_has_required_args(argv, required)
28
37
  return true if argv.size >= required
29
38
  puts "'lightning #{@command}' was called incorrectly.", command_usage
30
39
  end
31
40
 
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
41
  # 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.
42
+ # values with an equal sign i.e. '--option=value'. Options can be abbreviated with
43
+ # their first letter. Options without a value are set to true.
40
44
  # @param [Array]
41
45
  # @return [Array<Array, Hash>] Hash of options has symbolic keys
42
- def parse_args(args)
46
+ def parse_args(args, names=[])
43
47
  options, args = args.partition {|e| e =~ /^-/ }
44
48
  options = options.inject({}) do |hash, flag|
45
49
  key, value = flag.split('=')
46
- hash[key.sub(/^--?/,'').intern] = value.nil? ? true : value
50
+ name = key.sub(/^--?/,'')
51
+ name = names.sort.find {|e| e[/^#{name}/] } || name
52
+ hash[name.intern] = value.nil? ? true : value
47
53
  hash
48
54
  end
49
55
  [args, options]
@@ -52,18 +58,12 @@ module Lightning
52
58
  # Shortcut to Lightning.config
53
59
  def config; Lightning.config; end
54
60
 
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
61
+ private
62
+ def subcommand_has_required_args(subcommand, argv)
63
+ return true if argv.size >= (subcommand_required_args[subcommand] || 0)
64
+ puts "'lightning #{@command} #{subcommand}' was called incorrectly.", command_usage
64
65
  end
65
66
 
66
- private
67
67
  def subcommand_required_args
68
68
  desc_array[0].split('|').inject({}) {|a,e|
69
69
  cmd, *args = e.strip.split(/\s+/)
@@ -54,11 +54,11 @@ module Lightning
54
54
  def run_once(bolt, options)
55
55
  generator = options[:once] || bolt
56
56
  if options[:test]
57
- puts Config.bolt(Array(call_generator(generator)))['globs']
57
+ $stdout.puts Config.bolt(Array(call_generator(generator)))['globs']
58
58
  else
59
59
  if generate_bolts(bolt=>generator)
60
- puts "Generated following globs for bolt '#{bolt}':"
61
- puts Lightning.config.bolts[bolt]['globs'].map {|e| " "+e }
60
+ $stdout.puts "Generated following globs for bolt '#{bolt}':",
61
+ Lightning.config.bolts[bolt]['globs'].map {|e| " "+e }
62
62
  true
63
63
  end
64
64
  end
@@ -1,3 +1,3 @@
1
1
  module Lightning
2
- VERSION = '0.3.1'
2
+ VERSION = '0.3.2'
3
3
  end
@@ -0,0 +1,207 @@
1
+ .\" generated with Ronn/v0.4.1
2
+ .\" http://github.com/rtomayko/ronn/
3
+ .
4
+ .TH "LIGHTNING" "1" "April 2010" "CLDWALKER" "Lightning Manual"
5
+ .
6
+ .SH "NAME"
7
+ \fBlightning\fR \-\- Speed for your shell
8
+ .
9
+ .SH "SYNOPSIS"
10
+ .
11
+ .nf
12
+ lightning [\-h|\-\-help] [\-v|\-\-version] COMMAND [ARGS]
13
+ .
14
+ .fi
15
+ .
16
+ .SH "DESCRIPTION"
17
+ \fBlightning\fR is a commandline framework that lets users wrap commands with shell functions that are able to refer (translate) to any filesystem path by its basename. To achieve this, a group of paths to be translated are defined with shell globs. These shell globs, known as a lightning \fIbolt\fR, are then applied to commands to produce functions. In addition to translating basenames to full paths, lightning \fIfunctions\fR can autocomplete these basenames, resolve conflicts if they have the same name, leave any non\-basename arguments untouched, and autocomplete directories above and below a basename.
18
+ .
19
+ .P
20
+ To make bolts shareable between users and functions easier to create, \fBlightning\fR has \fIgenerators\fR. A \fIgenerator\fR generates filesystem\-specific globs for a bolt. \fBlightning\fR comes with some default generators. Users can make their own generators with generator plugins placed under ~/.lightning/generators/.
21
+ .
22
+ .SH "COMMANDS"
23
+ \fBlightning\fR comes with the following commands, some which have subcommands. Commands and subcommands can be abbreviated i.e. 'function create grep ruby' \-> 'f c grep ruby'. Users can define their own commands by placing command plugins under ~/.lightning/commands/.
24
+ .
25
+ .TP
26
+ \fBbolt\fR
27
+ Commands for managing bolts. Defaults to listing them.
28
+ .
29
+ .TP
30
+ \fBcomplete\fR
31
+ Prints a function's completions based on the last argument.
32
+ .
33
+ .TP
34
+ \fBfunction\fR
35
+ Commands for managing functions. Defaults to listing them.
36
+ .
37
+ .TP
38
+ \fBgenerator\fR
39
+ Lists available generators.
40
+ .
41
+ .TP
42
+ \fBinstall\fR
43
+ Builds shell functions and installs them into FILE to be sourced by shell.
44
+ .
45
+ .TP
46
+ \fBshell_command\fR
47
+ Commands for managing shell commands. Defaults to listing them.
48
+ .
49
+ .TP
50
+ \fBtranslate\fR
51
+ Translates each argument and prints it on a separate line.
52
+ .
53
+ .SH "CREATE FUNCTIONS"
54
+ There are two nonexclusive ways of creating functions. The first involves combining bolts with individual shell commands. Here are the steps involved:
55
+ .
56
+ .IP "\(bu" 4
57
+ Create a bolt with shell globs. This step can be skipped if a bolt has a generator with the same name.
58
+ # Globs are quoted to prevent filename expansion.
59
+ $ lightning bolt create code '~/code/fork/*' '~/code/gems/*'
60
+ Created bolt 'code'
61
+ .
62
+ .IP "\(bu" 4
63
+ Create function(s) for that bolt by applying to shell commands.
64
+ $ lightning function create cd code
65
+ Created function 'cd\-code'
66
+ $ lightning function create grep code
67
+ Created function 'grep\-code'
68
+ .
69
+ .IP "\(bu" 4
70
+ Generate and load functions into shell
71
+ $ lightning\-reload
72
+ Created ~/.lightning/function.sh
73
+ Loaded ~/.lightning/function.sh
74
+ .
75
+ .IP "" 0
76
+ .
77
+ .P
78
+ The second, more brute\-force way of creating functions is to make global functions. Global functions are made from combining each global bolt with each global shell command. For example, 4 global bolts combined with 7 global commands will make 28 global functions.
79
+ .
80
+ .P
81
+ # First make bolts global since bolts aren't global by default
82
+ $ lg bolt global on python clojure ruby
83
+ Global on for bolts python, clojure, ruby
84
+ .
85
+ .P
86
+ # Then add the global commands
87
+ $ lg shell_command create vim
88
+ Created shell command 'vim'
89
+ $ lg shell_command create grep
90
+ Created shell command 'grep'
91
+ $ lightning\-reload
92
+ .
93
+ .P
94
+ # Verify global functions
95
+ $ lightning function list
96
+ grep\-clojure
97
+ grep\-python
98
+ grep\-ruby
99
+ vim\-clojure
100
+ vim\-python
101
+ vim\-ruby
102
+ .
103
+ .SH "LIGHTNINGRC"
104
+ \fBlightning\fR's configuration is stored in ~/.lightningrc as YAML. Since it's human readable it's easy to modify. However, \fBlightning\fR depends on this file to function and will fail if the file has a syntax error. Modifying this file is only recommended if you need to modify existing functions, bolts or global commands in a way that the lightning commands can't. To read up on the config file format see \fIhttp://tagaholic.me/lightning/doc/Lightning/Config.html\fR.
105
+ .
106
+ .SH "INSTALLATION"
107
+ Install with either rip or rubygems:
108
+ $ rip install git://github.com/cldwalker/lightning.git
109
+ # OR
110
+ $ sudo gem install yard # to install documentation correctly
111
+ $ sudo gem install lightning
112
+ .
113
+ .P
114
+ If you've installed with rubygems and the command \fBtime lightning\fR takes longer than 0.05 seconds, I \fIstrongly recommend\fR installing with rip, http://hellorip.com. Your startup time directly effects your autocompletion speed with lightning.
115
+ .
116
+ .P
117
+ Once lightning is installed, we need to do a one\-time setup:
118
+ .
119
+ .P
120
+ # To see available install options
121
+ $ lightning install \-h
122
+ .
123
+ .P
124
+ # Installs lightning's core files
125
+ $ lightning install && source ~/.lightning/functions.sh
126
+ Created ~/.lightning_yml
127
+ Created ~/.lightning/functions.sh
128
+ .
129
+ .P
130
+ # To have lightning's functionality loaded when your shell starts up
131
+ echo source ~/.lightning/functions.sh >> ~/.bashrc
132
+ # or for zsh
133
+ echo source ~/.lightning/functions.sh >> ~/.zshrc
134
+ .
135
+ .SH "EXAMPLES"
136
+ Get help on any command:
137
+ .
138
+ .P
139
+ $ lightning function \-h
140
+ $ lightning bolt \-h
141
+ .
142
+ .P
143
+ List functions:
144
+ .
145
+ .P
146
+ # All functions
147
+ $ lightning function list
148
+ # All functions from ruby bolt
149
+ $ lightning function list \-\-bolt=ruby
150
+ # All functions from global command echo
151
+ $ lightning function list \-\-command=echo
152
+ .
153
+ .P
154
+ Regenerate functions and source them into the shell:
155
+ .
156
+ .P
157
+ # Call every time for changes to bolts and functions to take effect
158
+ $ lightning\-reload
159
+ .
160
+ .P
161
+ Manage global shell commands:
162
+ .
163
+ .P
164
+ $ lightning shell_command list
165
+ $ lightning shell_command create cd
166
+ $ lightning shell_command delete cd
167
+ .
168
+ .P
169
+ Manage/edit bolts:
170
+ .
171
+ .P
172
+ $ lightning bolt list
173
+ $ lightning bolt delete ruby
174
+ $ lightning bolt alias ruby r
175
+ $ lightning bolt global off ruby gem local_ruby
176
+ .
177
+ .P
178
+ Generate a bolt using a generator:
179
+ .
180
+ .P
181
+ # Generates ruby bolt with ruby generator
182
+ $ lightning bolt generate ruby
183
+ # Generates ruby19 bolt with ruby generator
184
+ $ lightning bolt generate ruby19 ruby
185
+ # Test what ruby bolt generates
186
+ $ lightning bolt generate ruby \-\-test
187
+ .
188
+ .P
189
+ Test what a function will execute:
190
+ .
191
+ .P
192
+ # Normal execution
193
+ $ cp\-gem \-r rubygems\-update\-1.3.6 .
194
+ # Prints cp\-gem's translated arguments, one per line
195
+ $ lightning translate cp\-gem \-r rubygems\-update\-1.3.6 .
196
+ \-r
197
+ /Library/Ruby/Gems/1.8/gems/rubygems\-update\-1.3.6
198
+ .
199
+ .
200
+ .SH "BUGS"
201
+ Please report bugs at \fIhttp://github.com/cldwalker/lightning/issues\fR.
202
+ .
203
+ .SH "COPYRIGHT"
204
+ \fBlightning\fR is Copyright (C) 2010 Gabriel Horner
205
+ .
206
+ .SH "SEE ALSO"
207
+ \fIhttp://tagaholic.me/lightning\fR, \fIhttp://tagaholic.me/lightning/doc/\fR, \fIhttp://github.com/cldwalker/lightning\fR