ehbrs-tools 0.3.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.
Files changed (158) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +13 -0
  3. data/exe/ehbrs +6 -0
  4. data/lib/ehbrs.rb +7 -0
  5. data/lib/ehbrs/executables.rb +28 -0
  6. data/lib/ehbrs/tools.rb +9 -0
  7. data/lib/ehbrs/tools/runner.rb +35 -0
  8. data/lib/ehbrs/tools/runner/vg.rb +26 -0
  9. data/lib/ehbrs/tools/runner/vg/ips.rb +90 -0
  10. data/lib/ehbrs/tools/runner/videos.rb +25 -0
  11. data/lib/ehbrs/tools/runner/videos/unsupported.rb +65 -0
  12. data/lib/ehbrs/tools/version.rb +7 -0
  13. data/lib/ehbrs/videos.rb +9 -0
  14. data/lib/ehbrs/videos/convert_job.rb +99 -0
  15. data/lib/ehbrs/videos/file.rb +70 -0
  16. data/lib/ehbrs/videos/profiles/base.rb +35 -0
  17. data/lib/ehbrs/videos/profiles/same_quality.rb +21 -0
  18. data/lib/ehbrs/videos/track.rb +27 -0
  19. data/lib/ehbrs/videos/unsupported/check_result.rb +24 -0
  20. data/lib/ehbrs/videos/unsupported/check_set.rb +43 -0
  21. data/lib/ehbrs/videos/unsupported/check_support.rb +68 -0
  22. data/lib/ehbrs/videos/unsupported/checks.rb +13 -0
  23. data/lib/ehbrs/videos/unsupported/checks/codec_extra_unlisted.rb +27 -0
  24. data/lib/ehbrs/videos/unsupported/checks/codec_extra_unsupported.rb +26 -0
  25. data/lib/ehbrs/videos/unsupported/checks/codec_unlisted.rb +23 -0
  26. data/lib/ehbrs/videos/unsupported/checks/codec_unsupported.rb +25 -0
  27. data/lib/ehbrs/videos/unsupported/checks/invalid_extension.rb +25 -0
  28. data/lib/ehbrs/videos/unsupported/file.rb +50 -0
  29. data/lib/ehbrs/videos/unsupported/file/fix.rb +45 -0
  30. data/lib/ehbrs/videos/unsupported/fix_profile.rb +56 -0
  31. data/lib/ehbrs/videos/unsupported/fixes/supported_codec.rb +36 -0
  32. data/lib/ehbrs/videos/unsupported/fixes/supported_container.rb +17 -0
  33. data/lib/ehbrs/videos/unsupported/profiles.rb +13 -0
  34. data/lib/ehbrs/videos/unsupported/profiles/base.rb +102 -0
  35. data/lib/ehbrs/videos/unsupported/profiles/philco.rb +27 -0
  36. data/lib/ehbrs/videos/unsupported/profiles/samsung.rb +32 -0
  37. data/lib/ehbrs/videos/unsupported/search.rb +72 -0
  38. data/lib/ehbrs/videos/unsupported/track.rb +32 -0
  39. data/vendor/eac_cli/Gemfile +5 -0
  40. data/vendor/eac_cli/eac_cli.gemspec +18 -0
  41. data/vendor/eac_cli/lib/eac_cli.rb +7 -0
  42. data/vendor/eac_cli/lib/eac_cli/default_runner.rb +22 -0
  43. data/vendor/eac_cli/lib/eac_cli/runner.rb +30 -0
  44. data/vendor/eac_cli/lib/eac_cli/runner/argument_option.rb +13 -0
  45. data/vendor/eac_cli/lib/eac_cli/runner/base_option.rb +22 -0
  46. data/vendor/eac_cli/lib/eac_cli/runner/boolean_option.rb +13 -0
  47. data/vendor/eac_cli/lib/eac_cli/runner/definition.rb +60 -0
  48. data/vendor/eac_cli/lib/eac_cli/runner/docopt_doc.rb +65 -0
  49. data/vendor/eac_cli/lib/eac_cli/runner/positional_argument.rb +15 -0
  50. data/vendor/eac_cli/lib/eac_cli/version.rb +5 -0
  51. data/vendor/eac_cli/spec/rubocop_spec.rb +7 -0
  52. data/vendor/eac_cli/spec/spec_helper.rb +100 -0
  53. data/vendor/eac_ruby_utils/Gemfile +16 -0
  54. data/vendor/eac_ruby_utils/MIT-LICENCE +16 -0
  55. data/vendor/eac_ruby_utils/README.rdoc +3 -0
  56. data/vendor/eac_ruby_utils/eac_ruby_utils.gemspec +25 -0
  57. data/vendor/eac_ruby_utils/lib/eac_ruby_utils.rb +23 -0
  58. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/arguments_consumer.rb +81 -0
  59. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/common_constructor.rb +133 -0
  60. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/configs.rb +82 -0
  61. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/configs/file.rb +66 -0
  62. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console.rb +5 -0
  63. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/configs.rb +135 -0
  64. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/docopt_runner.rb +39 -0
  65. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/docopt_runner/_class_methods.rb +18 -0
  66. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/docopt_runner/_doc.rb +25 -0
  67. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/docopt_runner/_settings.rb +19 -0
  68. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/docopt_runner/_subcommands.rb +139 -0
  69. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/speaker.rb +134 -0
  70. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/speaker/_class_methods.rb +39 -0
  71. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/speaker/list.rb +63 -0
  72. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/speaker/node.rb +25 -0
  73. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/contextualizable.rb +16 -0
  74. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/core_ext.rb +5 -0
  75. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs.rb +23 -0
  76. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/base_env.rb +28 -0
  77. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/command.rb +155 -0
  78. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/command/extra_options.rb +46 -0
  79. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/executable.rb +51 -0
  80. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/file.rb +22 -0
  81. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/local_env.rb +17 -0
  82. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/process.rb +19 -0
  83. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/envs/ssh_env.rb +72 -0
  84. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/filesystem_cache.rb +53 -0
  85. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/filesystem_traverser.rb +56 -0
  86. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/fs_cache.rb +11 -0
  87. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/listable.rb +17 -0
  88. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/listable/class_methods.rb +14 -0
  89. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/listable/instance_methods.rb +30 -0
  90. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/listable/integer_list.rb +23 -0
  91. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/listable/list.rb +89 -0
  92. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/listable/lists.rb +61 -0
  93. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/listable/string_list.rb +19 -0
  94. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/listable/value.rb +38 -0
  95. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/on_clean_ruby_environment.rb +23 -0
  96. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/options_consumer.rb +62 -0
  97. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patch.rb +11 -0
  98. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches.rb +4 -0
  99. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/class.rb +4 -0
  100. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/class/common_constructor.rb +9 -0
  101. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/hash.rb +5 -0
  102. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/hash/options_consumer.rb +10 -0
  103. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/hash/sym_keys_hash.rb +10 -0
  104. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/module.rb +4 -0
  105. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/module/console_speaker.rb +10 -0
  106. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/module/listable.rb +10 -0
  107. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/module/patch.rb +9 -0
  108. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/module/require_sub.rb +9 -0
  109. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/module/simple_cache.rb +10 -0
  110. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/object.rb +5 -0
  111. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/object/asserts.rb +14 -0
  112. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/object/if_present.rb +12 -0
  113. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/object/template.rb +16 -0
  114. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/paths_hash.rb +95 -0
  115. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/require_sub.rb +11 -0
  116. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/rspec.rb +9 -0
  117. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/rspec/conditional.rb +38 -0
  118. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/rspec/stubbed_ssh.rb +44 -0
  119. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/settings_provider.rb +65 -0
  120. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/simple_cache.rb +42 -0
  121. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/templates.rb +9 -0
  122. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/templates/directory.rb +104 -0
  123. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/templates/file.rb +101 -0
  124. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/templates/searcher.rb +55 -0
  125. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/version.rb +5 -0
  126. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/yaml.rb +13 -0
  127. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/arguments_consumer_spec.rb +17 -0
  128. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/common_constructor_spec.rb +36 -0
  129. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/configs_spec.rb +31 -0
  130. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/console/configs_spec.rb +14 -0
  131. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/console/docopt_runner_spec.rb +136 -0
  132. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/console/speaker_spec.rb +36 -0
  133. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/envs/executable_spec.rb +33 -0
  134. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/envs/ssh_env_spec.rb +25 -0
  135. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/filesystem_cache_spec.rb +32 -0
  136. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/listable_spec.rb +180 -0
  137. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/options_consumer_spec.rb +45 -0
  138. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/hash/options_consumer_spec.rb +17 -0
  139. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/hash/sym_keys_hash_spec.rb +13 -0
  140. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/module/console_speaker_spec.rb +13 -0
  141. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/module/listable_spec.rb +13 -0
  142. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/module/simple_cache_spec.rb +13 -0
  143. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/object/if_present_spec.rb +13 -0
  144. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/object/template_spec.rb +23 -0
  145. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/object/template_spec_files/path/my_stub_with_template +1 -0
  146. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/paths_hash_spec.rb +49 -0
  147. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/settings_provider_spec.rb +46 -0
  148. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/simple_cache_spec.rb +102 -0
  149. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/templates/file_spec.rb +34 -0
  150. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/templates/file_spec_files/expected_content +2 -0
  151. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/templates/file_spec_files/source.template +2 -0
  152. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/templates/searcher_spec.rb +30 -0
  153. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/templates/searcher_spec_files/path1/subdir1/file1.template +1 -0
  154. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/templates/searcher_spec_files/path1/subdir1/file2 +1 -0
  155. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/templates/searcher_spec_files/path2/subdir1/file3.template +1 -0
  156. data/vendor/eac_ruby_utils/spec/locales/pt-BR.yml +38 -0
  157. data/vendor/eac_ruby_utils/spec/spec_helper.rb +12 -0
  158. metadata +227 -0
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/common_constructor'
4
+ require 'eac_ruby_utils/configs'
5
+ require 'eac_ruby_utils/console/speaker'
6
+ require 'eac_ruby_utils/options_consumer'
7
+ require 'eac_ruby_utils/patches/object/asserts'
8
+ require 'eac_ruby_utils/simple_cache'
9
+
10
+ module EacRubyUtils
11
+ module Console
12
+ class Configs
13
+ include ::EacRubyUtils::Console::Speaker
14
+
15
+ class << self
16
+ def entry_key_to_envvar_name(entry_key)
17
+ path = if entry_key.is_a?(::Array)
18
+ entry_key
19
+ else
20
+ ::EacRubyUtils::PathsHash.parse_entry_key(entry_key)
21
+ end
22
+ path.join('_').gsub(/[^a-z0-9_]/i, '').gsub(/\A_+/, '').gsub(/_+\z/, '')
23
+ .gsub(/_{2,}/, '_').upcase
24
+ end
25
+ end
26
+
27
+ STORE_PASSWORDS_KEY = 'core.store_passwords'
28
+
29
+ attr_reader :configs
30
+
31
+ def initialize(configs_key, options = {})
32
+ options.assert_argument(::Hash, 'options')
33
+ @configs = ::EacRubyUtils::Configs.new(configs_key, options.merge(autosave: true))
34
+ end
35
+
36
+ def read_password(entry_key, options = {})
37
+ options = options.merge(noecho: true)
38
+ if store_passwords?
39
+ read_entry(entry_key, options)
40
+ else
41
+ looped_entry_value_from_input(entry_key, options)
42
+ end
43
+ end
44
+
45
+ def read_entry(entry_key, options = {})
46
+ options = ReadEntryOptions.new(options)
47
+ unless options[:noenv]
48
+ envvar_value = envvar_read_entry(entry_key)
49
+ return envvar_value if envvar_value.present?
50
+ end
51
+ stored_value = configs.read_entry(entry_key)
52
+ return stored_value if stored_value
53
+ return read_entry_from_console(entry_key, options) unless options[:noinput]
54
+
55
+ raise "No value found for entry \"#{entry_key}\"" if options[:required]
56
+ end
57
+
58
+ def store_passwords?
59
+ read_entry(
60
+ STORE_PASSWORDS_KEY,
61
+ before_input: -> { store_password_banner },
62
+ validator: ->(entry_value) { %w[yes no].include?(entry_value) }
63
+ ) == 'yes'
64
+ end
65
+
66
+ protected
67
+
68
+ def envvar_read_entry(entry_key)
69
+ ENV[self.class.entry_key_to_envvar_name(entry_key)]
70
+ end
71
+
72
+ def read_entry_from_console(entry_key, options)
73
+ options[:before_input].call if options[:before_input].present?
74
+ entry_value = looped_entry_value_from_input(entry_key, options)
75
+ configs.write_entry(entry_key, entry_value)
76
+ entry_value
77
+ end
78
+
79
+ def store_password_banner
80
+ infom 'Do you wanna to store passwords?'
81
+ infom "Warning: the passwords will be store in clear text in \"#{configs.storage_path}\""
82
+ infom 'Enter "yes" or "no"'
83
+ end
84
+
85
+ def looped_entry_value_from_input(entry_key, options)
86
+ loop do
87
+ entry_value = entry_value_from_input(entry_key, options)
88
+ next unless entry_value.present?
89
+ next if options[:validator] && !options[:validator].call(entry_value)
90
+
91
+ return entry_value
92
+ end
93
+ end
94
+
95
+ def entry_value_from_input(entry_key, options)
96
+ entry_value = request_input("Value for entry \"#{entry_key}\"",
97
+ options.request_input_options)
98
+ warn('Entered value is blank') if entry_value.blank?
99
+ entry_value
100
+ end
101
+
102
+ class ReadEntryOptions
103
+ include ::EacRubyUtils::SimpleCache
104
+ ::EacRubyUtils::CommonConstructor.new(:options).setup_class(self)
105
+
106
+ DEFAULT_VALUES = {
107
+ before_input: nil, bool: false, list: false, noecho: false, noenv: false, noinput: false,
108
+ required: true, validator: nil
109
+ }.freeze
110
+
111
+ def [](key)
112
+ values.fetch(key.to_sym)
113
+ end
114
+
115
+ def request_input_options
116
+ values.slice(:bool, :list, :noecho)
117
+ end
118
+
119
+ private
120
+
121
+ def values_uncached
122
+ consumer = ::EacRubyUtils::OptionsConsumer.new(options)
123
+ r = {}
124
+ DEFAULT_VALUES.each do |key, default_value|
125
+ value = consumer.consume(key)
126
+ value = default_value if value.nil?
127
+ r[key] = value
128
+ end
129
+ consumer.validate
130
+ r
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/hash/indifferent_access'
4
+ require 'active_support/core_ext/hash/slice'
5
+ require 'docopt'
6
+ require 'eac_ruby_utils/contextualizable'
7
+ require 'eac_ruby_utils/patches/hash/sym_keys_hash'
8
+ Dir["#{__dir__}/#{::File.basename(__FILE__, '.*')}/_*.rb"].sort.each do |partial|
9
+ require partial
10
+ end
11
+
12
+ module EacRubyUtils
13
+ module Console
14
+ class DocoptRunner
15
+ include ::EacRubyUtils::Contextualizable
16
+
17
+ attr_reader :settings
18
+
19
+ def initialize(settings = {})
20
+ @settings = settings.with_indifferent_access.freeze
21
+ check_subcommands
22
+ end
23
+
24
+ def options
25
+ @options ||= Docopt.docopt(target_doc, docopt_options)
26
+ end
27
+
28
+ def parent
29
+ settings[:parent]
30
+ end
31
+
32
+ protected
33
+
34
+ def docopt_options
35
+ settings.slice(:version, :argv, :help, :options_first).to_sym_keys_hash
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EacRubyUtils
4
+ module Console
5
+ class DocoptRunner
6
+ DOCOPT_ERROR_EXIT_CODE = 0x22220000
7
+
8
+ class << self
9
+ def run(options = {})
10
+ new(options).send(:run)
11
+ rescue Docopt::Exit => e
12
+ STDERR.write(e.message + "\n")
13
+ ::Kernel.exit(DOCOPT_ERROR_EXIT_CODE)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EacRubyUtils
4
+ module Console
5
+ class DocoptRunner
6
+ PROGRAM_MACRO = '__PROGRAM__'
7
+
8
+ def source_doc
9
+ setting_value(:doc)
10
+ end
11
+
12
+ def target_doc
13
+ source_doc.gsub(PROGRAM_MACRO, target_program_name).strip + "\n"
14
+ end
15
+
16
+ def source_program_name
17
+ setting_value(:program_name, false)
18
+ end
19
+
20
+ def target_program_name
21
+ [source_program_name, ENV['PROGRAM_NAME'], $PROGRAM_NAME].find(&:present?)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/settings_provider'
4
+
5
+ module EacRubyUtils
6
+ module Console
7
+ class DocoptRunner
8
+ include ::EacRubyUtils::SettingsProvider
9
+
10
+ attr_reader :settings
11
+
12
+ private
13
+
14
+ def setting_value(key, required = true)
15
+ super(key, required: required, order: %w[method settings_object constant])
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/string/inflections'
4
+ require 'shellwords'
5
+
6
+ module EacRubyUtils
7
+ module Console
8
+ class DocoptRunner
9
+ SUBCOMMAND_ARG = '<subcommand>'
10
+ SUBCOMMAND_ARGS_ARG = '<subcommand-args>'
11
+ SUBCOMMANDS_MACRO = '__SUBCOMMANDS__'
12
+
13
+ def subcommands?
14
+ source_doc.include?(SUBCOMMANDS_MACRO)
15
+ end
16
+
17
+ def check_subcommands
18
+ return unless subcommands?
19
+
20
+ singleton_class.include(SubcommandsSupport)
21
+ check_subcommands_arg
22
+ return if singleton_class.method_defined?(:run)
23
+
24
+ singleton_class.send(:alias_method, :run, :run_with_subcommand)
25
+ end
26
+
27
+ module SubcommandsSupport
28
+ def check_subcommands_arg
29
+ if subcommand_arg_as_list?
30
+ singleton_class.include(SubcommandsSupport::SubcommandArgAsList)
31
+ else
32
+ singleton_class.include(SubcommandsSupport::SubcommandArgAsArg)
33
+ end
34
+ end
35
+
36
+ def run_with_subcommand
37
+ if subcommand_name
38
+ check_valid_subcommand
39
+ subcommand.run
40
+ else
41
+ run_without_subcommand
42
+ end
43
+ end
44
+
45
+ def subcommand
46
+ @subcommand ||= subcommand_class_name(subcommand_name).constantize.new(
47
+ argv: subcommand_args,
48
+ program_name: subcommand_program,
49
+ parent: self
50
+ )
51
+ end
52
+
53
+ def target_doc
54
+ super.gsub(SUBCOMMANDS_MACRO,
55
+ "#{target_doc_subcommand_arg} [#{SUBCOMMAND_ARGS_ARG}...]") +
56
+ "\n" + subcommands_target_doc
57
+ end
58
+
59
+ def docopt_options
60
+ super.merge(options_first: true)
61
+ end
62
+
63
+ def subcommand_class_name(subcommand)
64
+ "#{self.class.name}::#{subcommand.underscore.camelize}"
65
+ end
66
+
67
+ def subcommand_arg_as_list?
68
+ setting_value(:subcommand_arg_as_list, false) || false
69
+ end
70
+
71
+ def subcommand_args
72
+ options.fetch(SUBCOMMAND_ARGS_ARG)
73
+ end
74
+
75
+ def subcommand_program
76
+ subcommand_name
77
+ end
78
+
79
+ def available_subcommands
80
+ (setting_value(:subcommands, false) || auto_available_subcommands).sort
81
+ end
82
+
83
+ def auto_available_subcommands
84
+ self.class.constants
85
+ .map { |name| self.class.const_get(name) }
86
+ .select { |c| c.instance_of? Class }
87
+ .select { |c| c < ::EacRubyUtils::Console::DocoptRunner }
88
+ .map { |c| c.name.demodulize.underscore.dasherize }
89
+ end
90
+
91
+ def run_without_subcommand
92
+ "Method #{__method__} should be overrided in #{self.class.name}"
93
+ end
94
+
95
+ protected
96
+
97
+ def check_valid_subcommand
98
+ return if available_subcommands.include?(subcommand_name)
99
+
100
+ raise ::Docopt::Exit, "\"#{subcommand_name}\" is not a valid subcommand" \
101
+ " (Valid: #{available_subcommands.join(', ')})"
102
+ end
103
+
104
+ module SubcommandArgAsArg
105
+ def target_doc_subcommand_arg
106
+ SUBCOMMAND_ARG
107
+ end
108
+
109
+ def subcommand_name
110
+ options.fetch(SUBCOMMAND_ARG)
111
+ end
112
+
113
+ def subcommands_target_doc
114
+ available_subcommands.inject("Subcommands:\n") do |a, e|
115
+ a + " #{e}\n"
116
+ end
117
+ end
118
+ end
119
+
120
+ module SubcommandArgAsList
121
+ def target_doc_subcommand_arg
122
+ '(' + available_subcommands.join('|') + ')'
123
+ end
124
+
125
+ def subcommand_name
126
+ available_subcommands.each do |subcommand|
127
+ return subcommand if options.fetch(subcommand)
128
+ end
129
+ nil
130
+ end
131
+
132
+ def subcommands_target_doc
133
+ "\n"
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'colorize'
4
+ require 'io/console'
5
+ require 'eac_ruby_utils/patches/hash/options_consumer'
6
+ require 'eac_ruby_utils/console/speaker/_class_methods'
7
+ require 'eac_ruby_utils/console/speaker/list'
8
+ require 'eac_ruby_utils/console/speaker/node'
9
+
10
+ module EacRubyUtils
11
+ module Console
12
+ # https://github.com/fazibear/colorize
13
+ module Speaker
14
+ def on_speaker_node(&block)
15
+ ::EacRubyUtils::Console::Speaker.on_node(&block)
16
+ end
17
+
18
+ def puts(string = '')
19
+ string.to_s.each_line do |line|
20
+ current_node.stderr.puts(current_node.stderr_line_prefix.to_s + line)
21
+ end
22
+ end
23
+
24
+ def out(string = '')
25
+ current_node.stdout.write(string.to_s)
26
+ end
27
+
28
+ def fatal_error(string)
29
+ puts "ERROR: #{string}".white.on_red
30
+ Kernel.exit 1
31
+ end
32
+
33
+ def title(string)
34
+ string = string.to_s
35
+ puts(('-' * (8 + string.length)).green)
36
+ puts("--- #{string} ---".green)
37
+ puts(('-' * (8 + string.length)).green)
38
+ puts
39
+ end
40
+
41
+ def info(string)
42
+ puts string.to_s.white
43
+ end
44
+
45
+ def infom(string)
46
+ puts string.to_s.light_yellow
47
+ end
48
+
49
+ def warn(string)
50
+ puts string.to_s.yellow
51
+ end
52
+
53
+ # Options:
54
+ # +bool+ ([Boolean], default: +false+): requires a answer "yes" or "no".
55
+ # +list+ ([Hash] or [Array], default: +nil+): requires a answer from a list.
56
+ # +noecho+ ([Boolean], default: +false+): does not output answer.
57
+ def request_input(question, options = {})
58
+ bool, list, noecho = options.to_options_consumer.consume_all(:bool, :list, :noecho)
59
+ if list
60
+ request_from_list(question, list, noecho)
61
+ elsif bool
62
+ request_from_bool(question, noecho)
63
+ else
64
+ request_string(question, noecho)
65
+ end
66
+ end
67
+
68
+ def infov(*args)
69
+ r = []
70
+ args.each_with_index do |v, i|
71
+ if i.even?
72
+ r << "#{v}: ".cyan
73
+ else
74
+ r.last << v.to_s
75
+ end
76
+ end
77
+ puts r.join(', ')
78
+ end
79
+
80
+ def success(string)
81
+ puts string.to_s.green
82
+ end
83
+
84
+ private
85
+
86
+ def list_value(list, input)
87
+ values = list_values(list)
88
+ return input, true unless values
89
+ return input, false unless values.include?(input)
90
+ end
91
+
92
+ def list_values(list)
93
+ if list.is_a?(::Hash)
94
+ list.keys.map(&:to_s)
95
+ elsif list.is_a?(::Array)
96
+ list.map(&:to_s)
97
+ end
98
+ end
99
+
100
+ def request_from_bool(question, noecho)
101
+ request_from_list(question, { yes: true, y: true, no: false, n: false }, noecho)
102
+ end
103
+
104
+ def request_from_list(question, list, noecho)
105
+ list = ::EacRubyUtils::Console::Speaker::List.build(list)
106
+ loop do
107
+ input = request_string("#{question} [#{list.valid_labels.join('/')}]", noecho)
108
+ return list.build_value(input) if list.valid_value?(input)
109
+
110
+ warn "Invalid input: \"#{input}\" (Valid: #{list.valid_labels.join(', ')})"
111
+ end
112
+ end
113
+
114
+ def request_string(question, noecho)
115
+ current_node.stderr.write "#{question}: ".to_s.yellow
116
+ noecho ? request_string_noecho : request_string_echo
117
+ end
118
+
119
+ def request_string_noecho
120
+ r = current_node.stdin.noecho(&:gets).chomp.strip
121
+ current_node.stderr.write("\n")
122
+ r
123
+ end
124
+
125
+ def request_string_echo
126
+ current_node.stdin.gets.chomp.strip
127
+ end
128
+
129
+ def current_node
130
+ ::EacRubyUtils::Console::Speaker.current_node
131
+ end
132
+ end
133
+ end
134
+ end