avm-tools 0.75.1 → 0.79.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/lib/avm/files/formatter.rb +8 -4
  3. data/lib/avm/git/auto_commit_path.rb +2 -4
  4. data/lib/avm/git/auto_commit_path/ruby.rb +20 -0
  5. data/lib/avm/patches/class/i18n.rb +31 -0
  6. data/lib/avm/patches/object/i18n.rb +2 -10
  7. data/lib/avm/projects/stereotypes/ruby_gem/update.rb +4 -1
  8. data/lib/avm/projects/stereotypes/ruby_gem/version_bump.rb +1 -2
  9. data/lib/avm/tools/runner/eac_redmine_base0/project_rename.rb +7 -16
  10. data/lib/avm/tools/runner/files/format.rb +3 -2
  11. data/lib/avm/tools/runner/git/auto_commit.rb +11 -0
  12. data/lib/avm/tools/runner/git/subrepo/clone.rb +84 -0
  13. data/lib/avm/tools/version.rb +1 -1
  14. data/template/avm/eac_redmine_base0/deploy/config/install.sh.template +12 -0
  15. data/vendor/eac_cli/eac_cli.gemspec +1 -1
  16. data/vendor/eac_cli/lib/eac_cli/definition.rb +49 -22
  17. data/vendor/eac_cli/lib/eac_cli/definition/alternative.rb +83 -0
  18. data/vendor/eac_cli/lib/eac_cli/definition/base_option.rb +17 -1
  19. data/vendor/eac_cli/lib/eac_cli/{parser/options_collection.rb → definition/help_formatter.rb} +20 -49
  20. data/vendor/eac_cli/lib/eac_cli/definition/positional_argument.rb +21 -4
  21. data/vendor/eac_cli/lib/eac_cli/docopt/doc_builder.rb +18 -40
  22. data/vendor/eac_cli/lib/eac_cli/docopt/doc_builder/alternative.rb +50 -0
  23. data/vendor/eac_cli/lib/eac_cli/docopt/runner_extension.rb +1 -0
  24. data/vendor/eac_cli/lib/eac_cli/parser.rb +21 -3
  25. data/vendor/eac_cli/lib/eac_cli/parser/alternative.rb +88 -0
  26. data/vendor/eac_cli/lib/eac_cli/parser/alternative/argv.rb +17 -0
  27. data/vendor/eac_cli/lib/eac_cli/parser/alternative/double_dash.rb +24 -0
  28. data/vendor/eac_cli/lib/eac_cli/parser/alternative/options.rb +58 -0
  29. data/vendor/eac_cli/lib/eac_cli/parser/alternative/positionals.rb +30 -0
  30. data/vendor/eac_cli/lib/eac_cli/parser/collector.rb +4 -0
  31. data/vendor/eac_cli/lib/eac_cli/patches/object/runner_with.rb +2 -1
  32. data/vendor/eac_cli/lib/eac_cli/runner.rb +6 -2
  33. data/vendor/eac_cli/lib/eac_cli/runner_with/help.rb +1 -1
  34. data/vendor/eac_cli/lib/eac_cli/runner_with/output_file.rb +5 -1
  35. data/vendor/eac_cli/lib/eac_cli/runner_with/subcommands.rb +96 -0
  36. data/vendor/eac_cli/lib/eac_cli/version.rb +1 -1
  37. data/vendor/eac_cli/spec/lib/eac_cli/definition/alternative_spec.rb +14 -0
  38. data/vendor/eac_cli/spec/lib/eac_cli/docopt/runner_extension_spec.rb +35 -0
  39. data/vendor/eac_cli/spec/lib/eac_cli/parser/alternative_spec.rb +140 -0
  40. data/vendor/eac_cli/spec/lib/eac_cli/runner_spec.rb +57 -40
  41. data/vendor/eac_cli/spec/lib/eac_cli/runner_with/output_file_spec.rb +53 -0
  42. data/vendor/eac_cli/spec/lib/eac_cli/runner_with/subcommands_spec.rb +57 -0
  43. data/vendor/eac_ruby_base0/lib/eac_ruby_base0/application.rb +32 -1
  44. data/vendor/eac_ruby_base0/lib/eac_ruby_base0/runner.rb +1 -1
  45. data/vendor/eac_ruby_base0/lib/eac_ruby_base0/version.rb +1 -1
  46. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/abstract_methods.rb +60 -0
  47. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/common_constructor.rb +53 -0
  48. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/configs.rb +4 -69
  49. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/configs/entry_reader.rb +81 -0
  50. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/configs/password_entry_reader.rb +18 -0
  51. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/configs/read_entry_options.rb +7 -2
  52. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/configs/store_passwords_entry_reader.rb +27 -0
  53. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/enumerator.rb +4 -0
  54. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/enumerator/current.rb +9 -0
  55. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/enumerator/stopped.rb +14 -0
  56. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/module/abstract_methods.rb +10 -0
  57. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/object/debug.rb +17 -0
  58. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/version.rb +1 -1
  59. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/yaml.rb +3 -2
  60. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/abstract_methods_spec.rb +28 -0
  61. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/common_constructor_spec.rb +66 -8
  62. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/enumerator/current_spec.rb +26 -0
  63. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/enumerator/stopped_spec.rb +32 -0
  64. metadata +31 -5
  65. data/vendor/eac_cli/lib/eac_cli/parser/parse_result.rb +0 -21
  66. data/vendor/eac_cli/lib/eac_cli/parser/positional_collection.rb +0 -49
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4600b008c9ecc3f3aaa220ec18cac2199559787186710d80e6cd1fda6f39cf97
4
- data.tar.gz: a8f6c806934616363ef26f4acc6e486a0f3fd215867e013c588256c20e077086
3
+ metadata.gz: eec96ee906113345d8ef2b32945ccf9140141b63cdeaccb7b2f351762f338e82
4
+ data.tar.gz: 8f25aaa99149329fc034c040f45609b8eb078b2c547ab88d99c89dfd2b607135
5
5
  SHA512:
6
- metadata.gz: d10aa9242ee96189a7f43ab7ba1d1dc8cda2c7bb9961566ed7c2bf2a2a33d4c285eb1a42eb747342e2a6d2a1f5130e4681871dbc92cf9716978914216c922a12
7
- data.tar.gz: 6eab4907c7e01156c4a7394e0ffa1503a1a8cdc3dce4e4f05aabd105b66c0576baecd6b30f0779e01565c78db3603614e8e75426b3cead19751d7bef2de582db
6
+ metadata.gz: 1790d224e7b049c1aca352e2d4859ae9d48d80df3664aa2741654a56c70491e065380936e1d62f542b449aaf8de3e7e5d609985da830ebef6a24e4e392a75f99
7
+ data.tar.gz: 4e658ff31fcb8044695f44a20a8f0777eda5eb580ddaad93d7e63f1ecfb4676e3f284e8e8578a0c3d2db1b978f0a3754ec3c0709fbb7e80c50a903c718dd408b
@@ -10,7 +10,11 @@ module Avm
10
10
  require_sub __FILE__
11
11
  enable_simple_cache
12
12
  enable_console_speaker
13
- common_constructor :source_paths, :options
13
+ enable_listable
14
+ lists.add_symbol :option, :apply, :recursive, :verbose
15
+ common_constructor :source_paths, :options, default: [{}] do
16
+ options.assert_valid_keys(self.class.lists.option.values)
17
+ end
14
18
 
15
19
  FORMATS = %w[ruby php html python xml json generic_plain].freeze
16
20
 
@@ -27,7 +31,7 @@ module Avm
27
31
  infom "Applying #{@formats_files.count} format(s)... "
28
32
  @formats_files.each do |format, files|
29
33
  infom "Applying format #{format.name} (Files matched: #{files.count})..."
30
- next unless options.fetch(:apply)
34
+ next unless options[OPTION_APPLY]
31
35
 
32
36
  @result += format.apply(files)
33
37
  end
@@ -35,7 +39,7 @@ module Avm
35
39
 
36
40
  def traverser_check_file(file)
37
41
  format = find_format(file)
38
- infov file, format ? format.class : '-' if options.fetch(:verbose)
42
+ infov file, format ? format.class : '-' if options[OPTION_VERBOSE]
39
43
  return unless format
40
44
 
41
45
  @formats_files[format] ||= []
@@ -79,7 +83,7 @@ module Avm
79
83
  end
80
84
 
81
85
  def traverser_recursive
82
- options.fetch(:recursive)
86
+ options[OPTION_RECURSIVE]
83
87
  end
84
88
  end
85
89
  end
@@ -5,6 +5,7 @@ require 'eac_ruby_utils/core_ext'
5
5
  module Avm
6
6
  module Git
7
7
  class AutoCommitPath
8
+ require_sub __FILE__, include_modules: true
8
9
  enable_console_speaker
9
10
  common_constructor :git, :path do
10
11
  self.path = path.to_pathname
@@ -31,10 +32,7 @@ module Avm
31
32
  end
32
33
 
33
34
  def class_name
34
- CLASS_NAME_PATTERNS.each do |pattern|
35
- pattern.if_match(relative_path.to_path, false) { |m| return m[1].camelize }
36
- end
37
- raise "No pattern matched \"#{relative_path}\""
35
+ ruby_class_name || relative_path.to_path
38
36
  end
39
37
 
40
38
  def commit_message
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module Avm
6
+ module Git
7
+ class AutoCommitPath
8
+ module Ruby
9
+ RUBY_CLASS_NAME_PATTERNS = [%r{lib/((?!.*/lib/).+)\.rb\z}, %r{app/[^/]+/(.+)\.rb\z}].freeze
10
+
11
+ def ruby_class_name
12
+ RUBY_CLASS_NAME_PATTERNS.each do |pattern|
13
+ pattern.if_match(relative_path.to_path, false) { |m| return m[1].camelize }
14
+ end
15
+ nil
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'avm/patches/i18n'
4
+
5
+ class Class
6
+ TRANSLATE_LOCALE_KEY = :__locale
7
+
8
+ def translate(entry_suffix, values = {})
9
+ on_i18n_locale(values.delete(TRANSLATE_LOCALE_KEY)) do
10
+ ::I18n.translate(translate_entry_full(entry_suffix), values)
11
+ end
12
+ end
13
+
14
+ def translate_entry_full(entry_suffix)
15
+ "#{translate_entry_self_prefix}.#{entry_suffix}"
16
+ end
17
+
18
+ def translate_entry_self_prefix
19
+ name.underscore.gsub('/', '.')
20
+ end
21
+
22
+ def on_i18n_locale(locale)
23
+ old_locale = ::I18n.locale
24
+ begin
25
+ ::I18n.locale = locale
26
+ yield
27
+ ensure
28
+ ::I18n.locale = old_locale
29
+ end
30
+ end
31
+ end
@@ -1,17 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'avm/patches/i18n'
3
+ require 'avm/patches/class/i18n'
4
4
 
5
5
  class Object
6
6
  def translate(entry_suffix, values = {})
7
- ::I18n.translate(translate_entry_full(entry_suffix), values)
8
- end
9
-
10
- def translate_entry_full(entry_suffix)
11
- "#{translate_entry_self_prefix}.#{entry_suffix}"
12
- end
13
-
14
- def translate_entry_self_prefix
15
- self.class.name.underscore.gsub('/', '.')
7
+ self.class.translate(entry_suffix, values)
16
8
  end
17
9
  end
@@ -1,12 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'eac_ruby_utils/core_ext'
4
+ require 'avm/patches/class/i18n'
4
5
 
5
6
  module Avm
6
7
  module Projects
7
8
  module Stereotypes
8
9
  class RubyGem
9
10
  class Update
11
+ TRANSLATE_CLASS = self
12
+
10
13
  enable_console_speaker
11
14
  common_constructor :instance
12
15
 
@@ -46,7 +49,7 @@ module Avm
46
49
  end
47
50
 
48
51
  def gemfile_lock_commit_message
49
- 'Todas as gems: atualiza.'
52
+ TRANSLATE_CLASS.translate(__method__, __locale: instance.locale)
50
53
  end
51
54
 
52
55
  def gemfile_lock_changed?
@@ -47,8 +47,7 @@ module Avm
47
47
  end
48
48
 
49
49
  def git_commit_message
50
- ::I18n.default_locale = instance.locale
51
- translate(__method__, version: target_version)
50
+ translate(__method__, version: target_version, __locale: instance.locale)
52
51
  end
53
52
 
54
53
  def changing_files
@@ -1,23 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'eac_cli/core_ext'
3
4
  require 'avm/eac_rails_base1/runner/code_runner'
4
- require 'eac_cli/default_runner'
5
5
 
6
6
  module Avm
7
7
  module Tools
8
8
  class Runner < ::EacRubyUtils::Console::DocoptRunner
9
9
  class EacRedmineBase0 < ::Avm::EacRailsBase1::Runner
10
- class ProjectRename < ::Avm::EacRailsBase1::Runner::CodeRunner
11
- include ::EacCli::DefaultRunner
12
-
13
- runner_definition do
10
+ class ProjectRename
11
+ runner_with ::Avm::EacRailsBase1::RunnerWith::Bundle do
14
12
  pos_arg :from
15
13
  pos_arg :to
16
14
  end
17
15
 
18
16
  def run
19
- start_banner
20
- command.system!
17
+ bundle_run
21
18
  end
22
19
 
23
20
  def start_banner
@@ -25,16 +22,10 @@ module Avm
25
22
  infov 'To', to
26
23
  end
27
24
 
28
- def from
29
- options.fetch('<from>')
30
- end
31
-
32
- def to
33
- options.fetch('<to>')
34
- end
25
+ delegate :from, :to, to: :parsed
35
26
 
36
- def command
37
- context(:instance).bundle('exec', 'rails', 'runner', code)
27
+ def bundle_args
28
+ %w[exec rails runner] + [code]
38
29
  end
39
30
 
40
31
  def code
@@ -32,8 +32,9 @@ module Avm
32
32
  end
33
33
 
34
34
  def formatter_options
35
- { apply: options.fetch('--apply'), recursive: !options.fetch('--no-recursive'),
36
- verbose: options.fetch('--verbose') }
35
+ { ::Avm::Files::Formatter::OPTION_APPLY => options.fetch('--apply'),
36
+ ::Avm::Files::Formatter::OPTION_RECURSIVE => !options.fetch('--no-recursive'),
37
+ ::Avm::Files::Formatter::OPTION_VERBOSE => options.fetch('--verbose') }
37
38
  end
38
39
 
39
40
  def git
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'avm/git/auto_commit_path'
4
+ require 'avm/files/formatter'
4
5
  require 'eac_cli/default_runner'
5
6
 
6
7
  module Avm
@@ -13,12 +14,14 @@ module Avm
13
14
  runner_definition do
14
15
  desc 'Commit with message based in content commited.'
15
16
  bool_opt '-d', '--dirty', 'Select dirty files.'
17
+ bool_opt '-f', '--format', 'Format files before commit.'
16
18
  pos_arg 'paths', repeat: true, optional: true
17
19
  end
18
20
 
19
21
  def run
20
22
  clear_stage
21
23
  banner
24
+ format_files
22
25
  run_paths
23
26
  end
24
27
 
@@ -39,6 +42,14 @@ module Avm
39
42
  context(:git).dirty_files.map { |d| context(:git).root_path.join / d.path }
40
43
  end
41
44
 
45
+ def format_files
46
+ return unless options.fetch('--format')
47
+
48
+ infom 'Formating files...'
49
+ ::Avm::Files::Formatter.new(paths.map(&:path),
50
+ ::Avm::Files::Formatter::OPTION_APPLY => true).run
51
+ end
52
+
42
53
  def paths_uncached
43
54
  (options.fetch('<paths>')
44
55
  .map { |p| p.to_pathname.expand_path } + dirty_paths)
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_cli/core_ext'
4
+ require 'eac_git/local'
5
+ require 'eac_ruby_utils/console/docopt_runner'
6
+
7
+ module Avm
8
+ module Tools
9
+ class Runner < ::EacRubyUtils::Console::DocoptRunner
10
+ class Git < ::EacRubyUtils::Console::DocoptRunner
11
+ class Subrepo < ::EacRubyUtils::Console::DocoptRunner
12
+ class Clone
13
+ runner_with :help do
14
+ desc 'Clone git-subrepo repositories.'
15
+ arg_opt '-b', '--branch', 'Branch.'
16
+ arg_opt '-d', '--parent-dir', 'Target path\'s parent directory.'
17
+ pos_arg :url
18
+ pos_arg :target_path, optional: true
19
+ end
20
+
21
+ def run
22
+ start_banner
23
+ clean
24
+ clone
25
+ end
26
+
27
+ private
28
+
29
+ def start_banner
30
+ infov 'URL', url
31
+ infov 'Subpath', target_path
32
+ infov 'Branch', branch
33
+ end
34
+
35
+ def clean
36
+ infom 'Cleaning...'
37
+ git.command('subrepo', 'clean', '--all', '--force').system!
38
+ end
39
+
40
+ def clone
41
+ infom 'Cloning...'
42
+ infov 'Clone arguments', clone_args
43
+ git.command(*clone_args).system!
44
+ end
45
+
46
+ delegate :branch, :url, to: :parsed
47
+
48
+ def git_uncached
49
+ ::EacGit::Local.new('.')
50
+ end
51
+
52
+ def clone_args
53
+ ['subrepo'] + branch.if_present([]) { |v| ['--branch', v] } +
54
+ if ::File.exist?(target_path)
55
+ ['init', target_path, '--remote', url]
56
+ else
57
+ ['clone', url, target_path, '--message', clone_message, '--force']
58
+ end
59
+ end
60
+
61
+ def clone_message
62
+ "Subrepo \"#{target_path}\" (#{url})."
63
+ end
64
+
65
+ def repos_name_from_url
66
+ %r{/([^/]+)\z}.if_match(url, false) { |m| m[1].gsub(/\.git\z/, '') }
67
+ end
68
+
69
+ def target_path
70
+ parsed.target_path || target_path_from_parent_dir ||
71
+ fatal_error('No target path specified')
72
+ end
73
+
74
+ def target_path_from_parent_dir
75
+ return nil unless parsed.parent_dir && repos_name_from_url
76
+
77
+ ::File.join(parsed.parent_dir, repos_name_from_url)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Avm
4
4
  module Tools
5
- VERSION = '0.75.1'
5
+ VERSION = '0.79.0'
6
6
  end
7
7
  end
@@ -12,3 +12,15 @@ fi
12
12
  export address_host='%%WEB.AUTHORITY%%'
13
13
  export address_path='%%WEB.PATH%%'
14
14
  export git_repositories_hierarchical_organisation=false
15
+
16
+ # Mail settings
17
+ export smtp_server='%%MAILER.SMTP.ADDRESS%%'
18
+ export smtp_port='%%MAILER.SMTP.PORT%%'
19
+ export smtp_domain='%%MAILER.SMTP.DOMAIN%%'
20
+ export smtp_tls='%%MAILER_SMTP_TLS%%'
21
+ export smtp_enable_starttls_auto='%%MAILER_SMTP_STARTTLS_AUTO%%'
22
+ export smtp_openssl_verify_mode='%%MAILER_SMTP_OPENSSL_VERIFY_MODE%%'
23
+ export smtp_authentication='%%MAILER.SMTP.AUTHENTICATION%%'
24
+ export smtp_username='%%MAILER.SMTP.USERNAME%%'
25
+ export smtp_password='%%MAILER.SMTP.PASSWORD%%'
26
+ export mail_from='%%MAILER.FROM%%'
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
12
12
 
13
13
  s.files = Dir['{lib}/**/*', 'Gemfile']
14
14
 
15
- s.add_dependency 'eac_ruby_utils', '~> 0.45'
15
+ s.add_dependency 'eac_ruby_utils', '~> 0.50'
16
16
 
17
17
  s.add_development_dependency 'eac_ruby_gem_support', '~> 0.1', '>= 0.1.2'
18
18
  end
@@ -8,57 +8,66 @@ require 'eac_ruby_utils/core_ext'
8
8
  module EacCli
9
9
  class Definition
10
10
  require_sub __FILE__
11
+
12
+ MAIN_ALTERNATIVE_KEY = :main
13
+ SUBCOMMAND_NAME_ARG = 'subcommand'
14
+ SUBCOMMAND_ARGS_ARG = 'subcommand_args'
15
+
11
16
  attr_accessor :description
12
- attr_accessor :options_argument
13
17
 
14
18
  def initialize
15
19
  self.description = '-- NO DESCRIPTION SET --'
16
- self.options_argument = true
20
+ alternatives_set[MAIN_ALTERNATIVE_KEY] = main_alternative
17
21
  end
18
22
 
19
23
  def alt(&block)
20
- r = ::EacCli::Definition.new
24
+ r = ::EacCli::Definition::Alternative.new
21
25
  r.instance_eval(&block)
22
- alternatives << r
26
+ alternatives_set[new_alternative_key] = r
23
27
  r
24
28
  end
25
29
 
26
30
  def alternatives
27
- @alternatives ||= []
28
- end
29
-
30
- def arg_opt(short, long, description, option_options = {})
31
- options << ::EacCli::Definition::ArgumentOption.new(
32
- short, long, description, option_options
33
- )
31
+ alternatives_set.values
34
32
  end
35
33
 
36
- def bool_opt(short, long, description, option_options = {})
37
- options << ::EacCli::Definition::BooleanOption.new(short, long, description, option_options)
34
+ def alternative(key)
35
+ alternatives_set.fetch(key)
38
36
  end
39
37
 
40
38
  def desc(description)
41
39
  self.description = description
42
40
  end
43
41
 
42
+ def help_formatter
43
+ @help_formatter ||= ::EacCli::Definition::HelpFormatter.new(self)
44
+ end
45
+
46
+ def main_alternative
47
+ @main_alternative ||= begin
48
+ r = ::EacCli::Definition::Alternative.new
49
+ r.options_argument(true)
50
+ r
51
+ end
52
+ end
53
+
44
54
  def options_arg(options_argument)
45
55
  self.options_argument = options_argument
46
56
  end
47
57
 
48
- def options
49
- @options ||= []
58
+ def options_argument
59
+ main_alternative.options_argument?
50
60
  end
51
61
 
52
- def pos_arg(name, arg_options = {})
53
- positional << ::EacCli::Definition::PositionalArgument.new(name, arg_options)
62
+ def options_argument=(enable)
63
+ main_alternative.options_argument(enable)
54
64
  end
55
65
 
56
- def positional
57
- @positional ||= []
58
- end
66
+ delegate :arg_opt, :bool_opt, :options, :pos_arg,
67
+ :positional, :subcommands, to: :main_alternative
59
68
 
60
- def subcommands
61
- positional << ::EacCli::Definition::PositionalArgument.new('subcommand', subcommand: true)
69
+ def subcommands?
70
+ alternatives.any?(&:subcommands?)
62
71
  end
63
72
 
64
73
  def options_first(enable = true)
@@ -68,5 +77,23 @@ module EacCli
68
77
  def options_first?
69
78
  @options_first ? true : false
70
79
  end
80
+
81
+ private
82
+
83
+ def alternatives_set
84
+ @alternatives_set ||= ::ActiveSupport::HashWithIndifferentAccess.new
85
+ end
86
+
87
+ def new_alternative_key
88
+ @last_key ||= 0
89
+ loop do
90
+ @last_key += 1
91
+ break @last_key unless alternatives_set.key?(@last_key)
92
+ end
93
+ end
94
+
95
+ def pos_set
96
+ @pos_set ||= []
97
+ end
71
98
  end
72
99
  end