lightning 0.3.4 → 0.4.0

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