lightning 0.3.4 → 0.4.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.
@@ -1,3 +1,7 @@
1
+ == 0.4.0
2
+ * Add shell variables to globs
3
+ * Allow globs to call generators to be used at runtime
4
+
1
5
  == 0.3.4
2
6
  * Fix lightning-reload and source_file command
3
7
 
@@ -77,7 +77,7 @@ To install and view lightning's man page:
77
77
  $ man lightning
78
78
 
79
79
  # If installed with rubygems
80
- $ sudo gem install gem-man
80
+ $ gem install gem-man
81
81
  $ gem man lightning
82
82
 
83
83
  == Bugs/Issues
@@ -29,9 +29,9 @@ module Lightning
29
29
  @globs = []
30
30
  @functions = []
31
31
  @aliases = {}
32
- (Lightning.config.bolts[@name] || {}).each do |k,v|
33
- instance_variable_set("@#{k}", v)
34
- end
32
+ config = Lightning.config.bolts[@name] || {}
33
+ config.each { |k,v| instance_variable_set("@#{k}", v) }
34
+ @globs = Generator.run(@name, :live => true) unless config.key?('globs')
35
35
  end
36
36
 
37
37
  # Generates functions from a bolt's functions and global shell commands
@@ -19,7 +19,10 @@ module Lightning
19
19
  # over name when generating function names.
20
20
  # * *global*: true or false (default is false). When set, uses bolt to generate functions with each command
21
21
  # in :shell_commands.
22
- # * *globs*(required): Array of globs which defines group of paths bolt handles
22
+ # * *globs*(required): Array of globs which defines group of paths bolt handles. A glob can
23
+ # any number of shell variables i.e. $HOME which are translated at runtime. If globs is not
24
+ # present, lightning will generate them using a Lightning::Generator method with the same name as the
25
+ # bolt, if it exists.
23
26
  # * *functions*: Array of lightning functions. A function can either be a string (shell command with default
24
27
  # options) or a hash with the following keys:
25
28
  # * *name*: Name of the lightning function
@@ -37,13 +37,13 @@ module Lightning
37
37
 
38
38
  # @return [Array] Globs used to create {Function#completion_map completion_map}
39
39
  def globs
40
- @globs ||= @bolt.globs
40
+ @globs ||= @bolt.globs.map {|g| gsub_shell_vars(g) }
41
41
  end
42
42
 
43
43
  # User-defined aliases for any path. Defaults to its bolt's aliases.
44
44
  # @return [Hash] Maps aliases to full paths
45
45
  def aliases
46
- @aliases ||= @bolt.aliases
46
+ @aliases ||= Hash[@bolt.aliases.map {|k,v| [k, gsub_shell_vars(v)] }]
47
47
  end
48
48
 
49
49
  # @return [CompletionMap] Map of basenames to full paths used in completion
@@ -66,5 +66,11 @@ module Lightning
66
66
  new_arg
67
67
  }
68
68
  end
69
+
70
+ private
71
+ def gsub_shell_vars(str)
72
+ str.gsub(/\$(\w+)/) {|e| ENV[$1] }
73
+ end
74
+
69
75
  end
70
- end
76
+ end
@@ -17,6 +17,7 @@ module Lightning
17
17
  # @option options [String] :once Generator to run once
18
18
  # @option options [Boolean] :test Runs generators in test mode which only displays
19
19
  # generated globs and doesn't save them
20
+ # @option options [Boolean] :live Generates globs for use at runtime
20
21
  def self.run(gens=[], options={})
21
22
  load_plugins
22
23
  new.run(gens, options)
@@ -43,6 +44,8 @@ module Lightning
43
44
  def run(gens, options)
44
45
  if options.key?(:once)
45
46
  run_once(gens, options)
47
+ elsif options.key?(:live)
48
+ Array(call_generator(gens, false))
46
49
  else
47
50
  gens = DEFAULT_GENERATORS if Array(gens).empty?
48
51
  gens = Hash[*gens.zip(gens).flatten] if gens.is_a?(Array)
@@ -72,11 +75,14 @@ module Lightning
72
75
  results.all?
73
76
  end
74
77
 
75
- def call_generator(gen)
76
- raise "Generator method doesn't exist." unless @underling.respond_to?(gen)
77
- Array(@underling.send(gen)).map {|e| e.to_s }
78
+ def call_generator(gen, strict=true)
79
+ if @underling.respond_to?(gen)
80
+ Array(@underling.send(gen)).map {|e| e.to_s }
81
+ elsif strict
82
+ raise("Generator method doesn't exist.")
83
+ end
78
84
  rescue
79
85
  $stdout.puts "Generator '#{gen}' failed with: #{$!.message}"
80
86
  end
81
87
  end
82
- end
88
+ end
@@ -1,3 +1,3 @@
1
1
  module Lightning
2
- VERSION = '0.3.4'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -19,7 +19,7 @@ context "bolt command" do
19
19
  end
20
20
 
21
21
  test 'list lists bolts and aliases with --alias' do
22
- mock(Commands).print_sorted_hash({"app"=>nil, "wild_dir"=>"w"})
22
+ mock(Commands).print_sorted_hash({"app"=>nil, "wild_dir"=>"w", 'live_glob' => nil})
23
23
  bolt 'list', '--alias'
24
24
  end
25
25
 
@@ -15,7 +15,7 @@ context "function command" do
15
15
  end
16
16
 
17
17
  test "list lists functions with --bolt" do
18
- mock(Commands).puts Lightning.functions.keys.sort
18
+ mock(Commands).puts Lightning.functions.keys.delete_if {|e| e[/live_glob/] }.sort
19
19
  function('list', '--bolt=app')
20
20
  end
21
21
 
@@ -119,4 +119,4 @@ context "function command" do
119
119
  function 'delete', 'zzz'
120
120
  end
121
121
  end
122
- end
122
+ end
@@ -1,90 +1,113 @@
1
1
  require File.join(File.dirname(__FILE__), 'test_helper')
2
2
 
3
3
  context "Function" do
4
+ # bolt, path and aliases depend on test/lightning.yml
4
5
  def create_function(attributes={})
5
- # bolt, path and aliases depend on test/lightning.yml
6
- @fn = Function.new({'name'=>'blah', 'bolt'=>Bolt.new('app'), 'desc'=>'blah'}.merge(attributes))
7
- @fn.completion_map.map = {'path1'=>'/dir/path1','path2'=>'/dir/path2',
8
- 'path3'=>'/dir/path3', 'file 1'=>'/dir/file 1'}
6
+ Function.new({'name'=>'blah', 'bolt'=>Bolt.new('app'), 'desc'=>'blah'}.merge(attributes))
9
7
  end
10
8
 
11
- def translate(input, *expected)
12
- Lightning.functions['blah'] = @fn
13
- mock(Commands).puts(expected.join("\n"))
14
- run_command :translate, ['blah'] + input.split(' ')
15
- end
9
+ context "basic function" do
10
+ def translate(*args); super(@fn, *args); end
11
+ def map; @fn.completion_map; end
16
12
 
17
- before_all do
18
- create_function
19
- @map = @fn.completion_map
20
- end
13
+ before do
14
+ @fn = create_function
15
+ @fn.completion_map.map = {'path1'=>'/dir/path1','path2'=>'/dir/path2',
16
+ 'path3'=>'/dir/path3', 'file 1'=>'/dir/file 1'}
17
+ end
21
18
 
22
- test "has correct completions" do
23
- assert_arrays_equal %w{a1 a2}+['file 1']+%w{path1 path2 path3}, @fn.completions
24
- end
19
+ test "has correct completions" do
20
+ assert_arrays_equal %w{a1 a2}+['file 1']+%w{path1 path2 path3}, @fn.completions
21
+ end
25
22
 
26
- test "has bolt's globs" do
27
- @fn.globs.should.not.be.empty?
28
- @fn.globs.should == @fn.bolt.globs
29
- end
23
+ test "has bolt's globs" do
24
+ @fn.globs.should.not.be.empty?
25
+ @fn.globs.should == @fn.bolt.globs
26
+ end
30
27
 
31
- test "has bolt's aliases" do
32
- @fn.aliases.should.not.be.empty?
33
- @fn.aliases.should == @fn.bolt.aliases
34
- end
28
+ test "has bolt's aliases" do
29
+ @fn.aliases.should.not.be.empty?
30
+ @fn.aliases.should == @fn.bolt.aliases
31
+ end
35
32
 
36
- test "can have a desc" do
37
- @fn.desc.should.not.be.empty?
38
- end
33
+ test "can have a desc" do
34
+ @fn.desc.should.not.be.empty?
35
+ end
39
36
 
40
- test "translates a completion" do
41
- translate 'path1', @map['path1']
42
- end
37
+ test "translates a completion" do
38
+ translate 'path1', map['path1']
39
+ end
43
40
 
44
- test "translates multiple completions separately" do
45
- translate 'path1 path2', @map['path1'], @map['path2']
46
- end
41
+ test "translates multiple completions separately" do
42
+ translate 'path1 path2', map['path1'], map['path2']
43
+ end
47
44
 
48
- test "translates instant multiple completions (..)" do
49
- translate 'path.. blah a1', @map['path1'], @map['path2'], @map['path3'], 'blah', @map['a1']
50
- end
45
+ test "translates instant multiple completions (..)" do
46
+ translate 'path.. blah a1', map['path1'], map['path2'], map['path3'], 'blah', map['a1']
47
+ end
51
48
 
52
- test "translates instant multiple completions containing spaces" do
53
- translate 'file..', @map['file 1']
54
- end
49
+ test "translates instant multiple completions containing spaces" do
50
+ translate 'file..', map['file 1']
51
+ end
55
52
 
56
- test "translates non-completion to same string" do
57
- translate 'blah', 'blah'
58
- end
53
+ test "translates non-completion to same string" do
54
+ translate 'blah', 'blah'
55
+ end
59
56
 
60
- test "translates completion anywhere amongst non-completions" do
61
- translate '-r path1', "-r", "#{@map['path1']}"
62
- translate '-r path1 doc/', "-r", "#{@map['path1']}", "doc/"
63
- end
57
+ test "translates completion anywhere amongst non-completions" do
58
+ translate '-r path1', "-r", "#{map['path1']}"
59
+ translate '-r path1 doc/', "-r", "#{map['path1']}", "doc/"
60
+ end
64
61
 
65
- test "translates completion embedded in subdirectory completion" do
66
- translate '-r path1/sub/dir', "-r", "#{@map['path1']}/sub/dir"
67
- end
62
+ test "translates completion embedded in subdirectory completion" do
63
+ translate '-r path1/sub/dir', "-r", "#{map['path1']}/sub/dir"
64
+ end
68
65
 
69
- test "translates completion with a superdirectory" do
70
- mock(File).expand_path("#{@map['path1']}/../file1") { '/dir/file1' }
71
- translate 'path1/../file1', '/dir/file1'
72
- end
66
+ test "translates completion with a superdirectory" do
67
+ mock(File).expand_path("#{map['path1']}/../file1") { '/dir/file1' }
68
+ translate 'path1/../file1', '/dir/file1'
69
+ end
73
70
 
74
- test "translates completion over alias" do
75
- translate 'path3', '/dir/path3'
76
- end
71
+ test "translates completion over alias" do
72
+ translate 'path3', '/dir/path3'
73
+ end
74
+
75
+ test "translates alias" do
76
+ translate 'a1', map['a1']
77
+ end
77
78
 
78
- test "translates alias" do
79
- translate 'a1', @map['a1']
79
+ after_all { config[:aliases] = {}}
80
80
  end
81
81
 
82
- after_all { config[:aliases] = {}}
82
+ context "function with global variables" do
83
+ before { @fn = create_function; ENV['MY_HOME'] = '/my/home' }
84
+ after { ENV.delete 'MY_HOME' }
85
+
86
+ test "has globs that expand shell variables" do
87
+ orig = @fn.bolt.globs.dup
88
+ @fn.bolt.globs << '$MY_HOME/*.rc'
89
+ @fn.globs.should == orig << '/my/home/*.rc'
90
+ end
83
91
 
84
- context "function attributes:" do
92
+ test "has aliases that expand shell variables" do
93
+ orig = @fn.bolt.aliases.dup
94
+ @fn.bolt.aliases['f'] = '$MY_HOME/file'
95
+ @fn.aliases.should == orig.merge('f' => '/my/home/file')
96
+ end
97
+ end
98
+
99
+ context "with" do
100
+ test "live globs" do
101
+ live_globs = %w{one two three}
102
+ Lightning::Generators.send(:define_method, :live_glob) { live_globs * 2 }
103
+ @fn = create_function 'bolt' => Bolt.new('live_glob')
104
+ @fn.globs.should == live_globs * 2
105
+ end
85
106
  test "post_path added after each translation" do
86
- create_function 'post_path'=>'/rdoc/index.html'
87
- translate '-r path1 path2', "-r", "/dir/path1/rdoc/index.html", "/dir/path2/rdoc/index.html"
107
+ @fn = create_function 'post_path'=>'/rdoc/index.html'
108
+ @fn.completion_map.map = {'path1'=>'/dir/path1','path2'=>'/dir/path2',
109
+ 'path3'=>'/dir/path3', 'file 1'=>'/dir/file 1'}
110
+ translate @fn, '-r path1 path2', "-r", "/dir/path1/rdoc/index.html", "/dir/path2/rdoc/index.html"
88
111
  end
89
112
  end
90
113
  end
@@ -29,7 +29,10 @@ bolts:
29
29
  globs:
30
30
  - /Applications/*.app
31
31
  - /Applications/Utilities/*.app
32
+ live_glob:
33
+ functions:
34
+ - cd
32
35
  shell_commands:
33
36
  vim: v
34
37
  grep: grep
35
- cd: cd
38
+ cd: cd
@@ -35,6 +35,12 @@ module Helpers
35
35
  def slice_hash(*keys)
36
36
  keys.shift.reject { |key,| !keys.include?(key) }
37
37
  end
38
+
39
+ def translate(fn, input, *expected)
40
+ Lightning.functions['blah'] = fn
41
+ mock(Commands).puts(expected.join("\n"))
42
+ run_command :translate, ['blah'] + input.split(' ')
43
+ end
38
44
  end
39
45
 
40
46
  class Bacon::Context
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: lightning
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.3.4
5
+ version: 0.4.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Gabriel Horner
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-04-08 00:00:00 -04:00
13
+ date: 2011-04-20 00:00:00 -04:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -120,7 +120,7 @@ licenses:
120
120
  post_install_message:
121
121
  rdoc_options:
122
122
  - --title
123
- - Lightning 0.3.4 Documentation
123
+ - Lightning 0.4.0 Documentation
124
124
  require_paths:
125
125
  - lib
126
126
  required_ruby_version: !ruby/object:Gem::Requirement