ing 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  or gratuitous backronym: <b>I</b> <b>N</b>eed a <b>G</b>enerator!
5
5
 
6
- Note this is a work-in-progress, not quite ready for use.
6
+ (Note this is a work-in-progress. Expect some quirkiness.)
7
7
 
8
8
  The command-line syntax is similar to Thor's, and it incorporates Thor's
9
9
  (Rails') generator methods and shell conventions like
@@ -22,8 +22,6 @@ Option parsing courtesy of the venerable and excellent
22
22
 
23
23
  ## Installation
24
24
 
25
- _Note: not yet gemified_
26
-
27
25
  gem install ing
28
26
 
29
27
  ## A quick tour
@@ -25,5 +25,7 @@ rest.
25
25
 
26
26
  s.requirements << "ruby >= 1.9"
27
27
 
28
+ s.add_development_dependency 'minitest'
28
29
  s.add_development_dependency 'fakeweb'
30
+
29
31
  end
data/lib/ing.rb CHANGED
@@ -4,8 +4,9 @@
4
4
  'ing/util',
5
5
  'ing/dispatcher',
6
6
  'ing/shell',
7
+ 'ing/common_options',
8
+ 'ing/boot',
7
9
  'ing/files',
8
- 'ing/commands/boot',
9
10
  'ing/commands/implicit',
10
11
  'ing/commands/list',
11
12
  'ing/commands/help',
@@ -0,0 +1,53 @@
1
+ # Base implementation of boot dispatch
2
+ # Mixed in to Commands::Implicit, Commands::Generate
3
+ # Note this does NOT provide any options, only provides implementation.
4
+ # Assumes target class will provide +namespace+ option, otherwise defaults to
5
+ # global namespace (::Object).
6
+ #
7
+ module Ing
8
+ module Boot
9
+
10
+ # Configure the command prior to dispatch.
11
+ # Default behavior is to set the shell of the dispatched command.
12
+ # Override in target class as needed; if you want to keep the default
13
+ # behavior then call +super+.
14
+ def configure_command(cmd)
15
+ cmd.shell = Ing.shell_class.new if cmd.respond_to?(:"shell=")
16
+ end
17
+
18
+ # Main processing of arguments and dispatch from command line (+Ing.run+)
19
+ # Note that three hooks are provided for target classes,
20
+ # +before+:: runs before any processing of arguments or dispatch of command
21
+ # +configure_command+:: configures the command prior to dispatch
22
+ # +after+:: runs after command dispatched
23
+ #
24
+ def call(*args)
25
+ before *args if respond_to?(:before)
26
+ ns = Ing::Util.to_class_names(options[:namespace] || 'object')
27
+ classes = Ing::Util.to_class_names(args.shift)
28
+ Dispatcher.new(ns, classes, *args).dispatch do |cmd|
29
+ configure_command cmd
30
+ end
31
+ after if respond_to?(:after)
32
+ end
33
+
34
+ # Dispatch from +Ing.invoke+
35
+ def call_invoke(klass, meth, *args)
36
+ before *args if respond_to?(:before)
37
+ Dispatcher.invoke(klass, meth, *args) do |cmd|
38
+ configure_command cmd
39
+ end
40
+ after if respond_to?(:after)
41
+ end
42
+
43
+ # Dispatch from +Ing.execute+
44
+ def call_execute(klass, meth, *args)
45
+ before *args if respond_to?(:before)
46
+ Dispatcher.execute(klass, meth, *args) do |cmd|
47
+ configure_command cmd
48
+ end
49
+ after if respond_to?(:after)
50
+ end
51
+
52
+ end
53
+ end
@@ -3,7 +3,7 @@ module Ing
3
3
  module Commands
4
4
 
5
5
  # This is the boot command invoked from `ing generate ...`
6
- class Generate < Boot
6
+ class Generate
7
7
 
8
8
  DEFAULTS = {
9
9
  namespace: 'object',
@@ -13,25 +13,25 @@ module Ing
13
13
 
14
14
  def self.specify_options(parser)
15
15
  parser.text "Run a generator task"
16
- parser.opt :debug, "Display debug messages"
17
- parser.opt :namespace, "Top-level namespace for generators",
18
- :type => :string, :default => DEFAULTS[:namespace]
19
16
  parser.opt :gen_root, "Generators root directory",
20
17
  :type => :string, :short => 'r',
21
18
  :default => DEFAULTS[:gen_root]
22
- parser.opt :ing_file, "Default generator file (ruby)",
23
- :type => :string, :short => 'f',
24
- :default => DEFAULTS[:ing_file]
25
19
  parser.stop_on_unknown
26
20
  end
27
21
 
22
+ include Ing::Boot
23
+ include Ing::CommonOptions
24
+
28
25
  def generator_root
29
26
  @generator_root ||= File.expand_path(options[:gen_root])
30
27
  end
31
28
 
32
- # Locate and require the generator ruby file identified by the first arg,
29
+ # Require libs and ing_file, then
30
+ # locate and require the generator ruby file identified by the first arg,
33
31
  # before dispatching to it.
34
32
  def before(*args)
33
+ require_libs
34
+ require_ing_file
35
35
  require_generator args.first
36
36
  end
37
37
 
@@ -14,17 +14,10 @@
14
14
  parser.text " ing help generate # help on built-in command generate"
15
15
  parser.text " ing help --namespace test unit # help on command within namespace"
16
16
  parser.text " ing help # display this message"
17
- parser.text "\nOptions:"
18
- parser.opt :debug, "Display debug messages"
19
- parser.opt :namespace, "Top-level namespace",
20
- :type => :string, :default => DEFAULTS[:namespace]
21
- parser.opt :require, "Require file or library before running (multi)",
22
- :multi => true, :type => :string
23
- parser.opt :ing_file, "Default task file (ruby)",
24
- :type => :string, :short => 'f',
25
- :default => DEFAULTS[:ing_file]
26
17
  end
27
18
 
19
+ include Ing::CommonOptions
20
+
28
21
  attr_accessor :options
29
22
  attr_writer :shell
30
23
 
@@ -34,51 +27,23 @@
34
27
 
35
28
  def initialize(options)
36
29
  self.options = options
37
- debug "#{__FILE__}:#{__LINE__} :: options #{options.inspect}"
38
30
  end
39
31
 
40
32
  # Require each passed file or library before running
41
33
  # and require the ing file if it exists
42
- def before(*args)
43
- require_libs options[:require]
34
+ def before
35
+ require_libs
44
36
  require_ing_file
45
37
  end
46
38
 
47
39
  def call(cmd="help")
48
- before(cmd)
40
+ before
49
41
  ns = Ing::Util.to_class_names(options[:namespace] || 'object')
50
42
  cs = Ing::Util.to_class_names(cmd)
51
43
  help = Dispatcher.new(ns, cs).help
52
44
  shell.say help.read
53
45
  end
54
46
 
55
- private
56
-
57
- # require relative paths relative to the Dir.pwd
58
- # otherwise, require as given (so gems can be required, etc.)
59
- def require_libs(libs)
60
- libs = Array(libs)
61
- libs.each do |lib|
62
- f = if /\A\.{1,2}\// =~ lib
63
- File.expand_path(lib)
64
- else
65
- lib
66
- end
67
- debug "#{__FILE__}:#{__LINE__} :: require #{f.inspect}"
68
- require f
69
- end
70
- end
71
-
72
- def require_ing_file
73
- f = File.expand_path(options[:ing_file])
74
- require_libs(f) if File.exists?(f)
75
- end
76
-
77
- # Internal debugging
78
- def debug(*args)
79
- shell.debug(*args) if options[:debug]
80
- end
81
-
82
47
  end
83
48
 
84
49
  H = Help
@@ -4,7 +4,7 @@ module Ing
4
4
 
5
5
  # This is the default boot command when ARGV.first not recognized as
6
6
  # a built-in Ing command. For example, `ing some:task run` .
7
- class Implicit < Boot
7
+ class Implicit
8
8
 
9
9
  DEFAULTS = {
10
10
  namespace: 'object',
@@ -13,46 +13,24 @@ module Ing
13
13
 
14
14
  def self.specify_options(parser)
15
15
  parser.text "(internal)"
16
- parser.opt :debug, "Display debug messages"
17
- parser.opt :namespace, "Top-level namespace for generators",
18
- :type => :string, :default => DEFAULTS[:namespace]
19
- parser.opt :require, "Require file or library before running (multi)",
20
- :multi => true, :type => :string
21
- parser.opt :ing_file, "Default generator file (ruby)",
22
- :type => :string, :short => 'f',
23
- :default => DEFAULTS[:ing_file]
24
16
  parser.stop_on_unknown
25
17
  end
26
18
 
19
+ include Ing::Boot
20
+ include Ing::CommonOptions
21
+
22
+ attr_accessor :options
23
+ def initialize(options)
24
+ self.options = options
25
+ end
26
+
27
27
  # Require each passed file or library before running
28
28
  # and require the ing file if it exists
29
29
  def before(*args)
30
- require_libs options[:require]
30
+ require_libs
31
31
  require_ing_file
32
32
  end
33
33
 
34
- private
35
-
36
- # require relative paths relative to the Dir.pwd
37
- # otherwise, require as given (so gems can be required, etc.)
38
- def require_libs(libs)
39
- libs = Array(libs)
40
- libs.each do |lib|
41
- f = if /\A\.{1,2}\// =~ lib
42
- File.expand_path(lib)
43
- else
44
- lib
45
- end
46
- debug "#{__FILE__}:#{__LINE__} :: require #{f.inspect}"
47
- require f
48
- end
49
- end
50
-
51
- def require_ing_file
52
- f = File.expand_path(options[:ing_file])
53
- require_libs(f) if File.exists?(f)
54
- end
55
-
56
34
  end
57
35
 
58
36
  end
@@ -14,17 +14,10 @@
14
14
  parser.text " ing list # list all built-in ing commands"
15
15
  parser.text " ing list rspec # list all ing commands in rspec namespace, or"
16
16
  parser.text " ing list --namespace rspec"
17
- parser.text "\nOptions:"
18
- parser.opt :debug, "Display debug messages"
19
- parser.opt :namespace, "Top-level namespace",
20
- :type => :string, :default => DEFAULTS[:namespace]
21
- parser.opt :require, "Require file or library before running (multi)",
22
- :multi => true, :type => :string
23
- parser.opt :ing_file, "Default task file (ruby)",
24
- :type => :string, :short => 'f',
25
- :default => DEFAULTS[:ing_file]
26
17
  end
27
18
 
19
+ include Ing::CommonOptions
20
+
28
21
  attr_accessor :options
29
22
  attr_writer :shell
30
23
 
@@ -34,19 +27,17 @@
34
27
 
35
28
  def initialize(options)
36
29
  self.options = options
37
- debug "#{__FILE__}:#{__LINE__} :: options #{options.inspect}"
38
30
  end
39
31
 
40
32
  # Require each passed file or library before running
41
33
  # and require the ing file if it exists
42
- def before(*args)
43
- require_libs options[:require]
34
+ def before
35
+ require_libs
44
36
  require_ing_file
45
37
  end
46
-
47
38
 
48
39
  def call(namespace=options[:namespace])
49
- before(namespace)
40
+ before
50
41
  ns = Ing::Util.to_class_names(namespace)
51
42
  mod = Ing::Util.namespaced_const_get(ns)
52
43
  data = mod.constants.map do |c|
@@ -59,27 +50,7 @@
59
50
  end
60
51
 
61
52
  private
62
-
63
- # require relative paths relative to the Dir.pwd
64
- # otherwise, require as given (so gems can be required, etc.)
65
- def require_libs(libs)
66
- libs = Array(libs)
67
- libs.each do |lib|
68
- f = if /\A\.{1,2}\// =~ lib
69
- File.expand_path(lib)
70
- else
71
- lib
72
- end
73
- debug "#{__FILE__}:#{__LINE__} :: require #{f.inspect}"
74
- require f
75
- end
76
- end
77
-
78
- def require_ing_file
79
- f = File.expand_path(options[:ing_file])
80
- require_libs(f) if File.exists?(f)
81
- end
82
-
53
+
83
54
  def desc_lines(ns, data)
84
55
  colwidths = data.inject([0,0]) {|max, (line, desc)|
85
56
  max[0] = line.length if line.length > max[0]
@@ -95,11 +66,6 @@
95
66
  ].join(" # ")
96
67
  }
97
68
  end
98
-
99
- # Internal debugging
100
- def debug(*args)
101
- shell.debug(*args) if options[:debug]
102
- end
103
69
 
104
70
  end
105
71
 
@@ -0,0 +1,65 @@
1
+ # Common options for built-in Ing commands
2
+ module Ing
3
+ module CommonOptions
4
+
5
+ # a bit of trickiness to change a singleton method...
6
+ def self.included(base)
7
+ meth = base.method(:specify_options) if base.respond_to?(:specify_options)
8
+ base.send(:define_singleton_method, :specify_options) do |expect|
9
+ meth.call(expect) if meth
10
+ expect.text "\nCommon Options:"
11
+ expect.opt :debug, "Display debug messages"
12
+ expect.opt :namespace, "Top-level namespace",
13
+ :type => :string, :default => base::DEFAULTS[:namespace]
14
+ expect.opt :require, "Require file or library before running (multi)",
15
+ :multi => true, :type => :string
16
+ expect.opt :ing_file, "Default task file (ruby)",
17
+ :type => :string, :short => 'f',
18
+ :default => base::DEFAULTS[:ing_file]
19
+ end
20
+ end
21
+
22
+ def debug?
23
+ !!options[:debug]
24
+ end
25
+
26
+ def requires
27
+ options[:require]
28
+ end
29
+
30
+ def ing_file
31
+ options[:ing_file]
32
+ end
33
+
34
+ def namespace
35
+ options[:namespace]
36
+ end
37
+
38
+ # require relative paths relative to the Dir.pwd
39
+ # otherwise, require as given (so gems can be required, etc.)
40
+ def require_libs(libs=requires)
41
+ libs = Array(libs)
42
+ libs.each do |lib|
43
+ f = if /\A\.{1,2}\// =~ lib
44
+ File.expand_path(lib)
45
+ else
46
+ lib
47
+ end
48
+ require f
49
+ end
50
+ end
51
+
52
+ def require_ing_file
53
+ f = File.expand_path(ing_file)
54
+ require_libs(f) if f && File.exists?(f)
55
+ end
56
+
57
+ # Internal debugging
58
+ def debug(*msgs)
59
+ if debug?
60
+ msgs.each do |msg| $stderr.puts "DEBUG :: #{msg}" end
61
+ end
62
+ end
63
+
64
+ end
65
+ end
@@ -1,3 +1,3 @@
1
1
  module Ing
2
- VERSION = '0.1.1'
2
+ VERSION = '0.1.2'
3
3
  end
@@ -0,0 +1,6 @@
1
+ Dir[ File.expand_path('{actions,acceptance}/*.rb',
2
+ File.dirname(__FILE__))
3
+ ].each do |f|
4
+ puts "Loading tests: #{f.gsub(Dir.pwd,'.')}"
5
+ require f
6
+ end
data/todo.yml CHANGED
@@ -3,5 +3,4 @@
3
3
  - add Shell::Color
4
4
  - remove global Ing.shell_class, specify via color switch
5
5
  - incorporate gsub_file patch, patches to Shell
6
- - refactor common functionality out of built-in commands
7
6
  - add a generator base class for the common use-case
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,9 +11,20 @@ bindir: bin
11
11
  cert_chain: []
12
12
  date: 2012-09-16 00:00:00.000000000Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: minitest
16
+ requirement: &17352160 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *17352160
14
25
  - !ruby/object:Gem::Dependency
15
26
  name: fakeweb
16
- requirement: &12266780 !ruby/object:Gem::Requirement
27
+ requirement: &17351600 !ruby/object:Gem::Requirement
17
28
  none: false
18
29
  requirements:
19
30
  - - ! '>='
@@ -21,7 +32,7 @@ dependencies:
21
32
  version: '0'
22
33
  type: :development
23
34
  prerelease: false
24
- version_requirements: *12266780
35
+ version_requirements: *17351600
25
36
  description: ! "\nAn alternative to Rake and Thor, Ing has a command-line syntax similar
26
37
  to \nThor's, and it incorporates Thor's (Rails') generator methods and shell \nconventions.
27
38
  But unlike Thor or Rake, it does not define its own DSL. Your tasks\ncorrespond
@@ -51,11 +62,12 @@ files:
51
62
  - lib/ing/actions/empty_directory.rb
52
63
  - lib/ing/actions/file_manipulation.rb
53
64
  - lib/ing/actions/inject_into_file.rb
54
- - lib/ing/commands/boot.rb
65
+ - lib/ing/boot.rb
55
66
  - lib/ing/commands/generate.rb
56
67
  - lib/ing/commands/help.rb
57
68
  - lib/ing/commands/implicit.rb
58
69
  - lib/ing/commands/list.rb
70
+ - lib/ing/common_options.rb
59
71
  - lib/ing/dispatcher.rb
60
72
  - lib/ing/files.rb
61
73
  - lib/ing/lib_trollop.rb
@@ -90,6 +102,7 @@ files:
90
102
  - test/fixtures/task.ing.rb
91
103
  - test/fixtures/task.thor
92
104
  - test/spec_helper.rb
105
+ - test/suite.rb
93
106
  - test/test_helper.rb
94
107
  - todo.yml
95
108
  homepage: https://github.com/ericgj/ing
@@ -143,5 +156,6 @@ test_files:
143
156
  - test/fixtures/task.ing.rb
144
157
  - test/fixtures/task.thor
145
158
  - test/spec_helper.rb
159
+ - test/suite.rb
146
160
  - test/test_helper.rb
147
161
  has_rdoc:
@@ -1,76 +0,0 @@
1
- # Base class
2
-
3
- module Ing
4
- module Commands
5
- class Boot
6
-
7
- attr_accessor :options
8
- attr_writer :shell
9
-
10
- def shell
11
- @shell ||= ::Ing.shell_class.new
12
- end
13
-
14
- def initialize(options)
15
- self.options = options
16
- debug "#{__FILE__}:#{__LINE__} :: options #{options.inspect}"
17
- end
18
-
19
- # Runs after options initialized but before any processing of arguments
20
- # or dispatching the command.
21
- # Should be implemented in subclasses.
22
- def before(*args)
23
- end
24
-
25
- # Configure the command prior to dispatch.
26
- # Should be implemented in subclasses.
27
- # If you want to keep this default behavior setting the shell,
28
- # call +super+ first.
29
- def configure_command(cmd)
30
- cmd.shell = self.shell if cmd.respond_to?(:"shell=")
31
- end
32
-
33
- # Runs after dispatching the command.
34
- # Should be implemented in subclasses.
35
- def after
36
- end
37
-
38
- # Main processing of arguments and dispatch from command line (+Ing.run+)
39
- def call(*args)
40
- before *args
41
- ns = Ing::Util.to_class_names(options[:namespace] || 'object')
42
- classes = Ing::Util.to_class_names(args.shift)
43
- debug "#{__FILE__}:#{__LINE__} :: dispatch #{ns.inspect}, #{classes.inspect}, #{args.inspect}"
44
- Dispatcher.new(ns, classes, *args).dispatch do |cmd|
45
- configure_command cmd
46
- end
47
- after
48
- end
49
-
50
- # Dispatch from +Ing.invoke+
51
- def call_invoke(klass, meth, *args)
52
- before *args
53
- Dispatcher.invoke(klass, meth, *args) do |cmd|
54
- configure_command cmd
55
- end
56
- after
57
- end
58
-
59
- # Dispatch from +Ing.execute+
60
- def call_execute(klass, meth, *args)
61
- before *args
62
- Dispatcher.execute(klass, meth, *args) do |cmd|
63
- configure_command cmd
64
- end
65
- after
66
- end
67
-
68
- # Internal debugging -- define a :debug option in subclass if you want this
69
- def debug(*args)
70
- shell.debug(*args) if options[:debug]
71
- end
72
-
73
- end
74
-
75
- end
76
- end