i18n-tasks 0.7.13 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +11 -0
  3. data/Gemfile +5 -3
  4. data/README.md +27 -126
  5. data/bin/i18n-tasks +2 -45
  6. data/config/locales/en.yml +11 -14
  7. data/config/locales/ru.yml +0 -3
  8. data/i18n-tasks.gemspec +0 -1
  9. data/lib/i18n/tasks.rb +14 -2
  10. data/lib/i18n/tasks/cli.rb +195 -0
  11. data/lib/i18n/tasks/command/collection.rb +2 -2
  12. data/lib/i18n/tasks/command/commander.rb +4 -24
  13. data/lib/i18n/tasks/command/commands/data.rb +17 -19
  14. data/lib/i18n/tasks/command/commands/eq_base.rb +2 -2
  15. data/lib/i18n/tasks/command/commands/health.rb +2 -2
  16. data/lib/i18n/tasks/command/commands/meta.rb +2 -2
  17. data/lib/i18n/tasks/command/commands/missing.rb +22 -15
  18. data/lib/i18n/tasks/command/commands/tree.rb +31 -35
  19. data/lib/i18n/tasks/command/commands/usages.rb +10 -11
  20. data/lib/i18n/tasks/command/commands/xlsx.rb +3 -3
  21. data/lib/i18n/tasks/command/dsl.rb +22 -7
  22. data/lib/i18n/tasks/command/option_parsers/enum.rb +53 -0
  23. data/lib/i18n/tasks/command/option_parsers/locale.rb +48 -0
  24. data/lib/i18n/tasks/command/options/common.rb +21 -31
  25. data/lib/i18n/tasks/command/options/data.rb +91 -0
  26. data/lib/i18n/tasks/command/options/locales.rb +22 -42
  27. data/lib/i18n/tasks/data/file_system_base.rb +2 -2
  28. data/lib/i18n/tasks/data/tree/node.rb +3 -3
  29. data/lib/i18n/tasks/data/tree/nodes.rb +3 -2
  30. data/lib/i18n/tasks/data/tree/siblings.rb +0 -1
  31. data/lib/i18n/tasks/logging.rb +9 -5
  32. data/lib/i18n/tasks/scanners/base_scanner.rb +6 -7
  33. data/lib/i18n/tasks/scanners/relative_keys.rb +1 -1
  34. data/lib/i18n/tasks/version.rb +1 -1
  35. data/spec/commands/data_commands_spec.rb +4 -4
  36. data/spec/commands/tree_commands_spec.rb +5 -5
  37. data/spec/google_translate_spec.rb +2 -3
  38. data/spec/i18n_spec.rb +0 -1
  39. data/spec/i18n_tasks_spec.rb +44 -23
  40. data/spec/readme_spec.rb +1 -1
  41. data/spec/support/test_codebase.rb +21 -10
  42. data/templates/config/i18n-tasks.yml +51 -39
  43. data/templates/rspec/i18n_spec.rb +0 -1
  44. metadata +6 -23
  45. data/lib/i18n/tasks/command/dsl/cmd.rb +0 -19
  46. data/lib/i18n/tasks/command/dsl/cmd_opt.rb +0 -19
  47. data/lib/i18n/tasks/command/dsl/enum_opt.rb +0 -45
  48. data/lib/i18n/tasks/command/options/enum_opt.rb +0 -50
  49. data/lib/i18n/tasks/command/options/list_opt.rb +0 -11
  50. data/lib/i18n/tasks/command/options/trees.rb +0 -81
  51. data/lib/i18n/tasks/slop_command.rb +0 -41
@@ -1,6 +1,6 @@
1
1
  require 'i18n/tasks/command/options/common'
2
2
  require 'i18n/tasks/command/options/locales'
3
- require 'i18n/tasks/command/options/trees'
3
+ require 'i18n/tasks/command/options/data'
4
4
 
5
5
  module I18n::Tasks
6
6
  module Command
@@ -10,7 +10,7 @@ module I18n::Tasks
10
10
  include Command::DSL
11
11
  include Command::Options::Common
12
12
  include Command::Options::Locales
13
- include Command::Options::Trees
13
+ include Command::Options::Data
14
14
  end
15
15
  end
16
16
  end
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
- require 'i18n/tasks/slop_command'
2
+ require 'i18n/tasks/cli'
3
3
  require 'i18n/tasks/reports/terminal'
4
4
  require 'i18n/tasks/reports/spreadsheet'
5
5
 
@@ -12,29 +12,13 @@ module I18n::Tasks
12
12
  @i18n = i18n
13
13
  end
14
14
 
15
- def safe_run(name, opts)
16
- begin
17
- coloring_was = Term::ANSIColor.coloring?
18
- Term::ANSIColor.coloring = ENV['I18N_TASKS_COLOR'] || STDOUT.isatty
19
- run name, opts
20
- rescue CommandError => e
21
- log_error e.message
22
- log_verbose e.backtrace * "\n"
23
- exit 78
24
- ensure
25
- Term::ANSIColor.coloring = coloring_was
26
- end
27
- end
28
-
29
15
  def run(name, opts = {})
30
16
  name = name.to_sym
31
17
  public_name = name.to_s.tr '_', '-'
32
- SlopCommand.parse_opts! opts, self.class.cmds[name][:opt], self
33
- if opts.empty?
34
- log_verbose "run #{public_name} without arguments"
18
+ log_verbose "task: #{public_name}(#{opts.map { |k, v| "#{k}: #{v.inspect}" } * ', '})"
19
+ if opts.empty? || method(name).arity.zero?
35
20
  send name
36
21
  else
37
- log_verbose "run #{public_name} with #{opts.map { |k, v| "#{k}=#{v}" } * ' '}"
38
22
  send name, opts
39
23
  end
40
24
  end
@@ -53,15 +37,11 @@ module I18n::Tasks
53
37
  @spreadsheet_report ||= I18n::Tasks::Reports::Spreadsheet.new(i18n)
54
38
  end
55
39
 
56
- def desc(name)
57
- self.class.cmds.try(:[], name).try(:desc)
58
- end
59
-
60
40
  def i18n
61
41
  @i18n ||= I18n::Tasks::BaseTask.new
62
42
  end
63
43
 
64
- delegate :base_locale, :t, to: :i18n
44
+ delegate :base_locale, :locales, :t, to: :i18n
65
45
  end
66
46
  end
67
47
  end
@@ -4,60 +4,58 @@ module I18n::Tasks
4
4
  module Data
5
5
  include Command::Collection
6
6
 
7
- cmd_opt :pattern_router, {
8
- short: :p,
9
- long: :pattern_router,
10
- desc: t('i18n_tasks.cmd.args.desc.pattern_router'),
11
- conf: {argument: false, optional: true}
12
- }
7
+ arg :pattern_router,
8
+ '-p',
9
+ '--pattern_router',
10
+ t('i18n_tasks.cmd.args.desc.pattern_router')
13
11
 
14
12
  cmd :normalize,
15
- args: '[locale ...]',
13
+ pos: '[locale ...]',
16
14
  desc: t('i18n_tasks.cmd.desc.normalize'),
17
- opt: cmd_opts(:locales, :pattern_router)
15
+ args: [:locales, :pattern_router]
18
16
 
19
17
  def normalize(opt = {})
20
18
  i18n.normalize_store! opt[:locales], opt[:pattern_router]
21
19
  end
22
20
 
23
21
  cmd :data,
24
- args: '[locale ...]',
22
+ pos: '[locale ...]',
25
23
  desc: t('i18n_tasks.cmd.desc.data'),
26
- opt: cmd_opts(:locales, :out_format)
24
+ args: [:locales, :out_format]
27
25
 
28
26
  def data(opt = {})
29
27
  print_forest i18n.data_forest(opt[:locales]), opt
30
28
  end
31
29
 
32
30
  cmd :data_merge,
33
- args: '[tree ...]',
31
+ pos: '[tree ...]',
34
32
  desc: t('i18n_tasks.cmd.desc.data_merge'),
35
- opt: cmd_opts(:data_format, :nostdin)
33
+ args: [:data_format, :nostdin]
36
34
 
37
35
  def data_merge(opt = {})
38
- forest = opt_forests_merged_stdin_args!(opt)
36
+ forest = merge_forests_stdin_and_pos!(opt)
39
37
  merged = i18n.data.merge!(forest)
40
38
  print_forest merged, opt
41
39
  end
42
40
 
43
41
  cmd :data_write,
44
- args: '[tree]',
42
+ pos: '[tree]',
45
43
  desc: t('i18n_tasks.cmd.desc.data_write'),
46
- opt: cmd_opts(:data_format, :nostdin)
44
+ args: [:data_format, :nostdin]
47
45
 
48
46
  def data_write(opt = {})
49
- forest = opt_forest_arg_or_stdin!(opt)
47
+ forest = forest_pos_or_stdin!(opt)
50
48
  i18n.data.write forest
51
49
  print_forest forest, opt
52
50
  end
53
51
 
54
52
  cmd :data_remove,
55
- args: '[tree]',
53
+ pos: '[tree]',
56
54
  desc: t('i18n_tasks.cmd.desc.data_remove'),
57
- opt: cmd_opts(:data_format, :nostdin)
55
+ args: [:data_format, :nostdin]
58
56
 
59
57
  def data_remove(opt = {})
60
- removed = i18n.data.remove_by_key!(opt_forest_arg_or_stdin!(opt))
58
+ removed = i18n.data.remove_by_key!(forest_pos_or_stdin!(opt))
61
59
  log_stderr 'Removed:'
62
60
  print_forest removed, opt
63
61
  end
@@ -5,9 +5,9 @@ module I18n::Tasks
5
5
  include Command::Collection
6
6
 
7
7
  cmd :eq_base,
8
- args: '[locale ...]',
8
+ pos: '[locale ...]',
9
9
  desc: t('i18n_tasks.cmd.desc.eq_base'),
10
- opt: cmd_opts(:locales, :out_format)
10
+ args: [:locales, :out_format]
11
11
 
12
12
  def eq_base(opt = {})
13
13
  print_forest i18n.eq_base_keys(opt), opt, :eq_base_keys
@@ -5,9 +5,9 @@ module I18n::Tasks
5
5
  include Command::Collection
6
6
 
7
7
  cmd :health,
8
- args: '[locale ...]',
8
+ pos: '[locale ...]',
9
9
  desc: t('i18n_tasks.cmd.desc.health'),
10
- opt: cmd_opts(:locales, :out_format)
10
+ args: [:locales, :out_format]
11
11
 
12
12
  def health(opt = {})
13
13
  forest = i18n.data_forest(opt[:locales])
@@ -5,12 +5,12 @@ module I18n::Tasks
5
5
  include Command::Collection
6
6
 
7
7
  cmd :config,
8
- args: '[section ...]',
8
+ pos: '[section ...]',
9
9
  desc: t('i18n_tasks.cmd.desc.config')
10
10
 
11
11
  def config(opts = {})
12
12
  cfg = i18n.config_for_inspect
13
- cfg = cfg.slice(*opts[:arguments]) if opts[:arguments]
13
+ cfg = cfg.slice(*opts[:arguments]) if opts[:arguments].present?
14
14
  cfg = cfg.to_yaml
15
15
  cfg.sub! /\A---\n/, ''
16
16
  cfg.gsub! /^([^\s-].+?:)/, Term::ANSIColor.cyan(Term::ANSIColor.bold('\1'))
@@ -4,25 +4,30 @@ module I18n::Tasks
4
4
  module Missing
5
5
  include Command::Collection
6
6
 
7
- enum_opt :missing_types, I18n::Tasks::MissingKeys.missing_keys_types
8
- cmd_opt :missing_types, enum_list_opt_attr(
9
- :t, :types=, enum_opt(:missing_types),
10
- proc { |valid, default| t('i18n_tasks.cmd.args.desc.missing_types', valid: valid, default: default) },
11
- proc { |invalid, valid| t('i18n_tasks.cmd.errors.invalid_missing_type', invalid: invalid * ', ', valid: valid * ', ', count: invalid.length) })
7
+ missing_types = I18n::Tasks::MissingKeys.missing_keys_types
8
+ arg :missing_types,
9
+ '-t',
10
+ "--types #{missing_types * ','}",
11
+ Array,
12
+ t('i18n_tasks.cmd.args.desc.missing_types', valid: missing_types * ', '),
13
+ parser: OptionParsers::Enum::ListParser.new(
14
+ missing_types,
15
+ proc { |invalid, valid| I18n.t('i18n_tasks.cmd.errors.invalid_missing_type',
16
+ invalid: invalid * ', ', valid: valid * ', ', count: invalid.length) })
12
17
 
13
18
  cmd :missing,
14
- args: '[locale ...]',
19
+ pos: '[locale ...]',
15
20
  desc: t('i18n_tasks.cmd.desc.missing'),
16
- opt: cmd_opts(:locales, :out_format, :missing_types)
21
+ args: [:locales, :out_format, :missing_types]
17
22
 
18
23
  def missing(opt = {})
19
24
  print_forest i18n.missing_keys(opt), opt, :missing_keys
20
25
  end
21
26
 
22
27
  cmd :translate_missing,
23
- args: '[locale ...]',
28
+ pos: '[locale ...]',
24
29
  desc: t('i18n_tasks.cmd.desc.translate_missing'),
25
- opt: cmd_opts(:locales, :locale_to_translate_from) << cmd_opt(:out_format).except(:short)
30
+ args: [:locales, :locale_to_translate_from, arg(:out_format).from(1)]
26
31
 
27
32
  def translate_missing(opt = {})
28
33
  missing = i18n.missing_diff_forest opt[:locales], opt[:from]
@@ -32,17 +37,19 @@ module I18n::Tasks
32
37
  print_forest translated, opt
33
38
  end
34
39
 
35
- DEFAULT_ADD_MISSING_VALUE = '%{value_or_human_key}'
36
-
37
40
  cmd :add_missing,
38
- args: '[locale ...]',
41
+ pos: '[locale ...]',
39
42
  desc: t('i18n_tasks.cmd.desc.add_missing'),
40
- opt: cmd_opts(:locales, :out_format) <<
41
- cmd_opt(:value).merge(desc: proc { "#{cmd_opt(:value)[:desc].call}. #{t('i18n_tasks.cmd.args.default_text', value: DEFAULT_ADD_MISSING_VALUE)}" })
43
+ args: [:locales, :out_format, arg(:value) + [{default: '%{value_or_human_key}'}]]
42
44
 
43
45
  def add_missing(opt = {})
44
- forest = i18n.missing_keys(opt).set_each_value!(opt[:value] || DEFAULT_ADD_MISSING_VALUE)
46
+ forest = i18n.missing_keys(opt).set_each_value!(opt[:value])
45
47
  i18n.data.merge! forest
48
+ # missing keys detected in the source are only returned in the base locale tree
49
+ # merge again in case such keys have been added to add them to other locales
50
+ forest_2 = i18n.missing_keys(opt).set_each_value!(opt[:value])
51
+ i18n.data.merge! forest_2
52
+ forest.merge! forest_2
46
53
  log_stderr t('i18n_tasks.add_missing.added', count: forest.leaves.count)
47
54
  print_forest forest, opt
48
55
  end
@@ -5,54 +5,50 @@ module I18n::Tasks
5
5
  include Command::Collection
6
6
 
7
7
  cmd :tree_translate,
8
- args: '[tree]',
8
+ pos: '[tree (or stdin)]',
9
9
  desc: t('i18n_tasks.cmd.desc.tree_translate'),
10
- opt: cmd_opts(:locale_to_translate_from) << cmd_opt(:data_format).except(:short)
10
+ args: [:locale_to_translate_from, arg(:data_format).from(1)]
11
11
 
12
12
  def tree_translate(opts = {})
13
- forest = opt_forest_arg_or_stdin!(opts)
14
- from = opts[:from]
15
- translated = i18n.google_translate_forest(forest, from)
16
- print_forest translated, opts
13
+ forest = forest_pos_or_stdin!(opts)
14
+ print_forest i18n.google_translate_forest(forest, opts[:from]), opts
17
15
  end
18
16
 
19
17
  cmd :tree_merge,
20
- args: '[tree ...]',
18
+ pos: '[[tree] [tree] ... (or stdin)]',
21
19
  desc: t('i18n_tasks.cmd.desc.tree_merge'),
22
- opt: cmd_opts(:data_format, :nostdin)
20
+ args: [:data_format, :nostdin]
23
21
 
24
22
  def tree_merge(opts = {})
25
- print_forest opt_forests_merged_stdin_args!(opts), opts
23
+ print_forest merge_forests_stdin_and_pos!(opts), opts
26
24
  end
27
25
 
28
26
  cmd :tree_filter,
29
- args: '[pattern] [tree]',
27
+ pos: '[pattern] [tree (or stdin)]',
30
28
  desc: t('i18n_tasks.cmd.desc.tree_filter'),
31
- opt: cmd_opts(:data_format, :pattern)
29
+ args: [:data_format, :pattern]
32
30
 
33
- def tree_filter(opt = {})
34
- pattern = opt_or_arg! :pattern, opt
35
- forest = opt_forest_arg_or_stdin!(opt)
31
+ def tree_filter(opts = {})
32
+ pattern = arg_or_pos! :pattern, opts
33
+ forest = forest_pos_or_stdin! opts
36
34
  unless pattern.blank?
37
35
  pattern_re = i18n.compile_key_pattern(pattern)
38
36
  forest = forest.select_keys { |full_key, _node| full_key =~ pattern_re }
39
37
  end
40
- print_forest forest, opt
38
+ print_forest forest, opts
41
39
  end
42
40
 
43
41
  cmd :tree_rename_key,
44
- args: '<key> <name> [tree]',
42
+ pos: 'KEY_PATTERN NAME [tree (or stdin)]',
45
43
  desc: t('i18n_tasks.cmd.desc.tree_rename_key'),
46
- opt: [cmd_opt(:pattern).merge(short: :k, long: :key=,
47
- desc: t('i18n_tasks.cmd.args.desc.key_pattern_to_rename')),
48
- cmd_opt(:pattern).merge(short: :n, long: :name=,
49
- desc: t('i18n_tasks.cmd.args.desc.new_key_name')),
50
- *cmd_opts(:data_format)]
44
+ args: [['-k', '--key KEY_PATTERN', t('i18n_tasks.cmd.args.desc.key_pattern_to_rename')],
45
+ ['-n', '--name NAME', t('i18n_tasks.cmd.args.desc.new_key_name')],
46
+ :data_format]
51
47
 
52
48
  def tree_rename_key(opt = {})
53
- key = opt_or_arg! :key, opt
54
- name = opt_or_arg! :name, opt
55
- forest = opt_forest_arg_or_stdin! opt
49
+ key = arg_or_pos! :key, opt
50
+ name = arg_or_pos! :name, opt
51
+ forest = forest_pos_or_stdin! opt
56
52
  raise CommandError.new('pass full key to rename (-k, --key)') if key.blank?
57
53
  raise CommandError.new('pass new name (-n, --name)') if name.blank?
58
54
  forest.rename_each_key!(key, name)
@@ -60,24 +56,24 @@ module I18n::Tasks
60
56
  end
61
57
 
62
58
  cmd :tree_subtract,
63
- args: '[tree A] [tree B ...]',
59
+ pos: '[[tree] [tree] ... (or stdin)]',
64
60
  desc: t('i18n_tasks.cmd.desc.tree_subtract'),
65
- opt: cmd_opts(:data_format, :nostdin)
61
+ args: [:data_format, :nostdin]
66
62
 
67
63
  def tree_subtract(opt = {})
68
- forests = opt_forests_stdin_args! opt, 2
64
+ forests = forests_stdin_and_pos! opt, 2
69
65
  forest = forests.reduce(:subtract_by_key) || empty_forest
70
66
  print_forest forest, opt
71
67
  end
72
68
 
73
69
  cmd :tree_set_value,
74
- args: '[value] [tree]',
70
+ pos: '[VALUE] [tree (or stdin)]',
75
71
  desc: t('i18n_tasks.cmd.desc.tree_set_value'),
76
- opt: cmd_opts(:value, :data_format, :nostdin, :pattern)
72
+ args: [:value, :data_format, :nostdin, :pattern]
77
73
 
78
74
  def tree_set_value(opt = {})
79
- value = opt_or_arg! :value, opt
80
- forest = opt_forest_arg_or_stdin!(opt)
75
+ value = arg_or_pos! :value, opt
76
+ forest = forest_pos_or_stdin!(opt)
81
77
  key_pattern = opt[:pattern]
82
78
  raise CommandError.new('pass value (-v, --value)') if value.blank?
83
79
  forest.set_each_value!(value, key_pattern)
@@ -85,13 +81,13 @@ module I18n::Tasks
85
81
  end
86
82
 
87
83
  cmd :tree_convert,
88
- args: '<tree>',
84
+ pos: '[tree (or stdin)]',
89
85
  desc: t('i18n_tasks.cmd.desc.tree_convert'),
90
- opt: [cmd_opt(:data_format).merge(short: :f, long: :from=),
91
- cmd_opt(:out_format).merge(short: :t, long: :to=)]
86
+ args: [arg(:data_format).dup.tap { |a| a[0..1] = ['-f', '--from FORMAT'] },
87
+ arg(:out_format).dup.tap { |a| a[0..1] = ['-t', '--to FORMAT'] }]
92
88
 
93
89
  def tree_convert(opt = {})
94
- forest = opt_forest_arg_or_stdin! opt.merge(format: opt[:from])
90
+ forest = forest_pos_or_stdin! opt.merge(format: opt[:from])
95
91
  print_forest forest, opt.merge(format: opt[:to])
96
92
  end
97
93
  end
@@ -4,16 +4,15 @@ module I18n::Tasks
4
4
  module Usages
5
5
  include Command::Collection
6
6
 
7
- cmd_opt :strict, {
8
- short: :s,
9
- long: :strict,
10
- desc: t('i18n_tasks.cmd.args.desc.strict')
11
- }
7
+ arg :strict,
8
+ '-s',
9
+ '--strict',
10
+ t('i18n_tasks.cmd.args.desc.strict')
12
11
 
13
12
  cmd :find,
14
- args: '[pattern]',
13
+ pos: '[pattern]',
15
14
  desc: t('i18n_tasks.cmd.desc.find'),
16
- opt: cmd_opts(:out_format, :pattern)
15
+ args: [:out_format, :pattern]
17
16
 
18
17
  def find(opt = {})
19
18
  opt[:filter] ||= opt.delete(:pattern) || opt[:arguments].try(:first)
@@ -21,18 +20,18 @@ module I18n::Tasks
21
20
  end
22
21
 
23
22
  cmd :unused,
24
- args: '[locale ...]',
23
+ pos: '[locale ...]',
25
24
  desc: t('i18n_tasks.cmd.desc.unused'),
26
- opt: cmd_opts(:locales, :out_format, :strict)
25
+ args: [:locales, :out_format, :strict]
27
26
 
28
27
  def unused(opt = {})
29
28
  print_forest i18n.unused_keys(opt), opt, :unused_keys
30
29
  end
31
30
 
32
31
  cmd :remove_unused,
33
- args: '[locale ...]',
32
+ pos: '[locale ...]',
34
33
  desc: t('i18n_tasks.cmd.desc.remove_unused'),
35
- opt: cmd_opts(:locales, :out_format, :strict, :confirm)
34
+ args: [:locales, :out_format, :strict, :confirm]
36
35
 
37
36
  def remove_unused(opt = {})
38
37
  unused_keys = i18n.unused_keys(opt)
@@ -5,10 +5,10 @@ module I18n::Tasks
5
5
  include Command::Collection
6
6
 
7
7
  cmd :xlsx_report,
8
- args: '[locale...]',
8
+ pos: '[locale...]',
9
9
  desc: t('i18n_tasks.cmd.desc.xlsx_report'),
10
- opt: [cmd_opt(:locales),
11
- {short: :p, long: :path=, desc: 'Destination path', conf: {default: 'tmp/i18n-report.xlsx'}}]
10
+ args: [:locales,
11
+ ['-p', '--path PATH', 'Destination path', default: 'tmp/i18n-report.xlsx']]
12
12
 
13
13
  def xlsx_report(opt = {})
14
14
  begin
@@ -1,7 +1,3 @@
1
- require 'i18n/tasks/command/dsl/cmd'
2
- require 'i18n/tasks/command/dsl/cmd_opt'
3
- require 'i18n/tasks/command/dsl/enum_opt'
4
-
5
1
  module I18n::Tasks
6
2
  module Command
7
3
  module DSL
@@ -19,9 +15,28 @@ module I18n::Tasks
19
15
  end
20
16
 
21
17
  module ClassMethods
22
- include DSL::Cmd
23
- include DSL::CmdOpt
24
- include DSL::EnumOpt
18
+ def cmd(name, conf = nil)
19
+ if conf
20
+ conf = conf.dup
21
+ conf[:args] = (args = conf[:args]) ? args.map { |arg| Symbol === arg ? arg(arg) : arg } : []
22
+
23
+ dsl(:cmds)[name] = conf
24
+ else
25
+ dsl(:cmds)[name]
26
+ end
27
+ end
28
+
29
+ def arg(ref, *args)
30
+ if args.present?
31
+ dsl(:args)[ref] = args
32
+ else
33
+ dsl(:args)[ref]
34
+ end
35
+ end
36
+
37
+ def cmds
38
+ dsl(:cmds)
39
+ end
25
40
 
26
41
  def dsl(key)
27
42
  @dsl[key]