bovem 3.0.5 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -3
  3. data/.rubocop.yml +82 -0
  4. data/.travis-gemfile +4 -5
  5. data/.travis.yml +8 -6
  6. data/CHANGELOG.md +12 -0
  7. data/Gemfile +9 -8
  8. data/README.md +1 -1
  9. data/Rakefile +22 -6
  10. data/bovem.gemspec +5 -5
  11. data/doc/Bovem.html +10 -10
  12. data/doc/Bovem/Application.html +670 -318
  13. data/doc/Bovem/Command.html +1447 -1125
  14. data/doc/Bovem/CommandMethods.html +4 -4
  15. data/doc/Bovem/CommandMethods/Children.html +173 -179
  16. data/doc/Bovem/CommandMethods/Help.html +9 -9
  17. data/doc/Bovem/Configuration.html +239 -24
  18. data/doc/Bovem/Console.html +267 -128
  19. data/doc/Bovem/ConsoleMethods.html +4 -4
  20. data/doc/Bovem/ConsoleMethods/Interactions.html +57 -70
  21. data/doc/Bovem/ConsoleMethods/Interactions/ClassMethods.html +9 -9
  22. data/doc/Bovem/ConsoleMethods/Logging.html +258 -298
  23. data/doc/Bovem/ConsoleMethods/Logging/ClassMethods.html +8 -8
  24. data/doc/Bovem/ConsoleMethods/Output.html +96 -118
  25. data/doc/Bovem/ConsoleMethods/StyleHandling.html +8 -8
  26. data/doc/Bovem/ConsoleMethods/StyleHandling/ClassMethods.html +26 -39
  27. data/doc/Bovem/Errors.html +4 -4
  28. data/doc/Bovem/Errors/Error.html +4 -4
  29. data/doc/Bovem/Errors/InvalidConfiguration.html +4 -4
  30. data/doc/Bovem/Errors/InvalidLogger.html +4 -4
  31. data/doc/Bovem/I18n.html +175 -0
  32. data/doc/Bovem/Logger.html +95 -83
  33. data/doc/Bovem/Option.html +669 -862
  34. data/doc/Bovem/Parser.html +10 -10
  35. data/doc/Bovem/ParserMethods.html +4 -4
  36. data/doc/Bovem/ParserMethods/General.html +4 -4
  37. data/doc/Bovem/ParserMethods/General/ClassMethods.html +26 -38
  38. data/doc/Bovem/Shell.html +169 -48
  39. data/doc/Bovem/ShellMethods.html +4 -4
  40. data/doc/Bovem/ShellMethods/Directories.html +46 -62
  41. data/doc/Bovem/ShellMethods/Execute.html +51 -99
  42. data/doc/Bovem/ShellMethods/General.html +4 -445
  43. data/doc/Bovem/ShellMethods/Read.html +56 -61
  44. data/doc/Bovem/ShellMethods/Write.html +22 -242
  45. data/doc/Bovem/Version.html +6 -6
  46. data/doc/_index.html +18 -18
  47. data/doc/class_list.html +6 -2
  48. data/doc/css/style.css +1 -0
  49. data/doc/file.README.html +5 -5
  50. data/doc/file_list.html +5 -1
  51. data/doc/frames.html +1 -1
  52. data/doc/index.html +5 -5
  53. data/doc/js/full_list.js +4 -1
  54. data/doc/method_list.html +161 -157
  55. data/doc/top-level-namespace.html +4 -4
  56. data/lib/bovem.rb +3 -4
  57. data/lib/bovem/application.rb +47 -39
  58. data/lib/bovem/command.rb +175 -193
  59. data/lib/bovem/configuration.rb +28 -29
  60. data/lib/bovem/console.rb +244 -171
  61. data/lib/bovem/errors.rb +1 -1
  62. data/lib/bovem/i18n.rb +18 -0
  63. data/lib/bovem/logger.rb +26 -26
  64. data/lib/bovem/option.rb +49 -58
  65. data/lib/bovem/parser.rb +174 -222
  66. data/lib/bovem/shell.rb +272 -320
  67. data/lib/bovem/version.rb +2 -2
  68. data/locales/en.yml +39 -38
  69. data/locales/it.yml +39 -38
  70. data/spec/bovem/application_spec.rb +6 -5
  71. data/spec/bovem/command_spec.rb +23 -23
  72. data/spec/bovem/console_spec.rb +101 -102
  73. data/spec/bovem/i18n_spec.rb +21 -0
  74. data/spec/bovem/logger_spec.rb +4 -4
  75. data/spec/bovem/option_spec.rb +43 -43
  76. data/spec/bovem/parser_spec.rb +13 -13
  77. data/spec/bovem/shell_spec.rb +106 -115
  78. data/spec/spec_helper.rb +19 -6
  79. metadata +14 -13
  80. data/doc/Bovem/Localizer.html +0 -376
  81. data/lib/bovem/localizer.rb +0 -27
  82. data/spec/coverage_helper.rb +0 -20
@@ -9,47 +9,32 @@ module Bovem
9
9
  module ShellMethods
10
10
  # General methods.
11
11
  module General
12
- # Handles general failure of a file/directory method.
13
- #
14
- # @param e [Exception] The occurred exception.
15
- # @param access_error [String|Symbol] The message to show in case of access errors.
16
- # @param not_found_error [String|Symbol] The message to show in case of a not found entry.
17
- # @param general_error [String|Symbol] The message to show in case of other errors.
18
- # @param entries [Array] The list of entries which failed.
19
- # @param fatal [Boolean] If quit in case of fatal errors.
20
- # @param show_errors [Boolean] Whether to show errors.
12
+ private
13
+
14
+ # :nodoc:
21
15
  def handle_failure(e, access_error, not_found_error, general_error, entries, fatal, show_errors)
22
- error_type, locale, final_entries = setup_error_handling(entries, fatal)
16
+ error_type, final_entries = setup_error_handling(entries, fatal)
23
17
 
24
18
  case e.class.to_s
25
- when "Errno::EACCES" then @console.send(error_type, locale.send(access_error, final_entries))
26
- when "Errno::ENOENT" then @console.send(error_type, locale.send(not_found_error, final_entries))
27
- else show_general_failure(e, general_error, entries, fatal) if show_errors
19
+ when "Errno::EACCES" then @console.send(error_type, i18n.send(access_error, final_entries))
20
+ when "Errno::ENOENT" then @console.send(error_type, i18n.send(not_found_error, final_entries))
21
+ else show_general_failure(e, general_error, entries, fatal) if show_errors
28
22
  end
29
23
  end
30
24
 
31
- # Setups error handling.
32
- #
33
- # @param entries [Array] The list of entries which failed.
34
- # @param fatal [Boolean] If quit in case of fatal errors.
35
- # @return [Array] Variables for error handling
25
+ # :nodoc:
36
26
  def setup_error_handling(entries, fatal)
37
- [fatal ? :fatal : :error, i18n.shell, entries.length == 1 ? entries[0] : entries]
27
+ [fatal ? :fatal : :error, entries.length == 1 ? entries[0] : entries]
38
28
  end
39
29
 
40
- # Shows errors when a directory creation failed.
41
- #
42
- # @param e [Exception] The occurred exception.
43
- # @param entries [Array] The list of entries which failed.
44
- # @param fatal [Boolean] If quit in case of fatal errors.
30
+ # :nodoc:
45
31
  def show_general_failure(e, general_error, entries, fatal)
46
- locale = i18n.shell
47
-
48
- @console.error(locale.send(general_error))
32
+ @console.error(i18n.send(general_error))
49
33
  @console.with_indentation(11) do
50
- entries.each do |entry| @console.write(entry) end
34
+ entries.each { |entry| @console.write(entry) }
51
35
  end
52
- @console.write(locale.error(e.class.to_s, e), "\n", 5)
36
+
37
+ @console.write(i18n.error(e.class.to_s, e), suffix: "\n", indented: 5)
53
38
  Kernel.exit(-1) if fatal
54
39
  end
55
40
  end
@@ -58,55 +43,56 @@ module Bovem
58
43
  module Read
59
44
  # Tests a path against a list of test.
60
45
  #
61
- # Valid tests are every method available in http://www.ruby-doc.org/core-1.9.3/FileTest.html (plus `read`, `write`, `execute`, `exec`, `dir`). Trailing question mark can be omitted.
46
+ # Valid tests are every method available in http://www.ruby-doc.org/core-2.3.0/FileTest.html (plus `read`, `write`, `execute`, `exec`, `dir`).
47
+ # Trailing question mark can be omitted. Unrecognized tests will make the check fail.
62
48
  #
63
49
  # @param path [String] The path to test.
64
50
  # @param tests [Array] The list of tests to perform.
65
- def check(path, tests)
51
+ def check(path, *tests)
66
52
  path = path.ensure_string
67
53
 
68
- tests.ensure_array.all? { |test|
54
+ tests.ensure_array(no_duplicates: true, compact: true, flatten: true).all? do |test|
69
55
  # Adjust test name
70
56
  test = test.ensure_string.strip
71
57
 
72
- test = case test
58
+ test =
59
+ case test
73
60
  when "read" then "readable"
74
61
  when "write" then "writable"
75
62
  when "execute", "exec" then "executable"
76
63
  when "dir" then "directory"
77
64
  else test
78
- end
65
+ end
79
66
 
80
67
  # Execute test
81
68
  test += "?" if test !~ /\?$/
82
69
  FileTest.respond_to?(test) ? FileTest.send(test, path) : nil
83
- }
70
+ end
84
71
  end
85
72
 
86
73
  # Find a list of files in directories matching given regexps or patterns.
87
74
  #
88
- # You can also pass a block to perform matching. The block will receive a single argument and the path will be considered matched if the blocks not evaluates to `nil` or `false`.
75
+ # You can also pass a block to perform matching. The block will receive a single argument and the path will be considered if return value is not falsey.
89
76
  #
90
77
  # Inside the block, you can call `Find.prune` to stop searching in the current directory.
91
78
  #
92
79
  # @param directories [String] A list of directories where to search files.
93
80
  # @param patterns [Array] A list of regexps or patterns to match files. If empty, every file is returned. Ignored if a block is provided.
94
- # @param by_extension [Boolean] If to only search in extensions. Ignored if a block is provided.
81
+ # @param extension_only [Boolean] If to only search in extensions. Ignored if a block is provided.
95
82
  # @param case_sensitive [Boolean] If the search is case sensitive. Only meaningful for string patterns.
96
83
  # @param block [Proc] An optional block to perform matching instead of pattern matching.
97
- def find(directories, patterns = [], by_extension = false, case_sensitive = false, &block)
84
+ def find(directories, patterns: [], extension_only: false, case_sensitive: false, &block)
98
85
  rv = []
99
86
 
100
- directories = directories.ensure_array(nil, true, true) {|d| File.expand_path(d.ensure_string) }
101
- patterns = normalize_patterns(patterns, by_extension, case_sensitive)
87
+ directories = directories.ensure_array(no_duplicates: true, compact: true, flatten: true) { |d| File.expand_path(d.ensure_string) }
88
+ patterns = normalize_patterns(patterns, extension_only, case_sensitive)
102
89
 
103
90
  directories.each do |directory|
104
- if check(directory, [:directory, :readable, :executable]) then
105
- Find.find(directory) do |entry|
106
- found = patterns.blank? ? true : match_pattern(entry, patterns, by_extension, &block)
91
+ next unless check(directory, [:directory, :readable, :executable])
92
+ Find.find(directory) do |entry|
93
+ found = patterns.blank? ? true : match_pattern(entry, patterns, extension_only, &block)
107
94
 
108
- rv << entry if found
109
- end
95
+ rv << entry if found
110
96
  end
111
97
  end
112
98
 
@@ -114,40 +100,33 @@ module Bovem
114
100
  end
115
101
 
116
102
  private
117
- # Normalizes a set of patterns to find.
118
- #
119
- # @param patterns [Array] A list of regexps or patterns to match files. If empty, every file is returned. Ignored if a block is provided.
120
- # @param by_extension [Boolean] If to only search in extensions. Ignored if a block is provided.
121
- # @param case_sensitive [Boolean] If the search is case sensitive. Only meaningful for string patterns.
122
- # @return [Array] The normalized patterns.
123
- def normalize_patterns(patterns, by_extension, case_sensitive)
124
- # Adjust patterns
125
- patterns = patterns.ensure_array(nil, true, true) {|p| p.is_a?(::Regexp) ? p : Regexp.new(Regexp.quote(p.ensure_string)) }
126
- patterns = patterns.map {|p| /(#{p.source})$/ } if by_extension
127
- patterns = patterns.map {|p| /#{p.source}/i } if !case_sensitive
128
- patterns
103
+
104
+ # :nodoc:
105
+ def normalize_patterns(patterns, by_extension, case_sensitive)
106
+ # Adjust patterns
107
+ patterns = patterns.ensure_array(no_duplicates: true, compact: true, flatten: true) do |p|
108
+ p.is_a?(::Regexp) ? p : Regexp.new(Regexp.quote(p.ensure_string))
129
109
  end
130
110
 
131
- # Matches an entry against a set of patterns or a procedure.
132
- #
133
- # @param entry [String] The entry to search.
134
- # @param patterns [Array] A list of regexps or patterns to match files. If empty, every file is returned. Ignored if a block is provided.
135
- # @param by_extension [Boolean] If to only search in extensions. Ignored if a block is provided.
136
- # @param block [Proc|nil] An optional block to run instead of pattern matching.
137
- # @return [Boolean] `true` if entry matched, `false` otherwise.
138
- def match_pattern(entry, patterns, by_extension, &block)
139
- catch(:found) do
140
- if block then
141
- throw(:found, true) if block.call(entry)
142
- else
143
- patterns.each do |pattern|
144
- throw(:found, true) if pattern.match(entry) && (!by_extension || !File.directory?(entry))
145
- end
146
- end
111
+ patterns = patterns.map { |p| /(#{p.source})$/ } if by_extension
112
+ patterns = patterns.map { |p| /#{p.source}/i } unless case_sensitive
113
+ patterns
114
+ end
147
115
 
148
- false
116
+ # :nodoc:
117
+ def match_pattern(entry, patterns, by_extension)
118
+ catch(:found) do
119
+ if block_given?
120
+ throw(:found, true) if yield(entry)
121
+ else
122
+ patterns.each do |pattern|
123
+ throw(:found, true) if pattern.match(entry) && (!by_extension || !File.directory?(entry))
124
+ end
149
125
  end
126
+
127
+ false
150
128
  end
129
+ end
151
130
  end
152
131
 
153
132
  # Methods to copy or move entries.
@@ -158,10 +137,10 @@ module Bovem
158
137
  # @param dst [String] The destination. **Any existing entries will be overwritten.** Any required directory will be created.
159
138
  # @param run [Boolean] If `false`, it will just print a list of message that would be copied or moved.
160
139
  # @param show_errors [Boolean] If show errors.
161
- # @param fatal [Boolean] If quit in case of fatal errors.
140
+ # @param fatal_errors [Boolean] If quit in case of fatal errors.
162
141
  # @return [Boolean] `true` if operation succeeded, `false` otherwise.
163
- def copy(src, dst, run = true, show_errors = false, fatal = true)
164
- copy_or_move(src, dst, :copy, run, show_errors, fatal)
142
+ def copy(src, dst, run: true, show_errors: false, fatal_errors: true)
143
+ copy_or_move(src, dst, operation: :copy, run: run, show_errors: show_errors, fatal_errors: fatal_errors)
165
144
  end
166
145
 
167
146
  # Moves a set of files or directory to another location.
@@ -170,26 +149,20 @@ module Bovem
170
149
  # @param dst [String] The destination. **Any existing entries will be overwritten.** Any required directory will be created.
171
150
  # @param run [Boolean] If `false`, it will just print a list of message that would be deleted.
172
151
  # @param show_errors [Boolean] If show errors.
173
- # @param fatal [Boolean] If quit in case of fatal errors.
152
+ # @param fatal_errors [Boolean] If quit in case of fatal errors.
174
153
  # @return [Boolean] `true` if operation succeeded, `false` otherwise.
175
- def move(src, dst, run = true, show_errors = false, fatal = true)
176
- copy_or_move(src, dst, :move, run, show_errors, fatal)
154
+ def move(src, dst, run: true, show_errors: false, fatal_errors: true)
155
+ copy_or_move(src, dst, operation: :move, run: run, show_errors: show_errors, fatal_errors: fatal_errors)
177
156
  end
178
157
 
179
- # Copies or moves a set of files or directory to another location.
180
- #
181
- # @param src [String|Array] The entries to copy or move. If is an Array, `dst` is assumed to be a directory.
182
- # @param dst [String] The destination. **Any existing entries will be overwritten.** Any required directory will be created.
183
- # @param operation [Symbol] The operation to perform. Valid values are `:copy` or `:move`.
184
- # @param run [Boolean] If `false`, it will just print a list of message that would be copied or moved.
185
- # @param show_errors [Boolean] If show errors.
186
- # @param fatal [Boolean] If quit in case of fatal errors.
187
- # @return [Boolean] `true` if operation succeeded, `false` otherwise.
158
+ private
159
+
160
+ # :nodoc:
188
161
  def copy_or_move(src, dst, operation, run = true, show_errors = true, fatal = true)
189
162
  rv = true
190
163
  operation, operation_s, single, src, dst = sanitize_copy_or_move(operation, src, dst)
191
164
 
192
- if !run then
165
+ if !run
193
166
  dry_run_copy_or_move(single, operation_s, src, dst)
194
167
  else
195
168
  rv = catch(:rv) do
@@ -203,135 +176,118 @@ module Bovem
203
176
  rv
204
177
  end
205
178
 
206
- private
207
- # Sanitizes arguments for copy or move.
208
- #
209
- # @param operation [String] The operation which will be executed.
210
- # @param src [String|Array] The entries to copy or move. If is an Array, `dst` is assumed to be a directory.
211
- # @param dst [String] The destination. **Any existing entries will be overwritten.** Any required directory will be created.
212
- # @return [Array] A list of sanitized arguments.
213
- def sanitize_copy_or_move(operation, src, dst)
214
- operation = :copy if operation != :move
215
- single = !src.is_a?(Array)
216
- src = single ? File.expand_path(src) : src.map {|s| File.expand_path(s) }
217
-
218
- [operation, i18n.shell.send(operation), single, src, File.expand_path(dst.ensure_string)]
179
+ # :nodoc:
180
+ def sanitize_copy_or_move(operation, src, dst)
181
+ operation = :copy if operation != :move
182
+ single = !src.is_a?(Array)
183
+ src = single ? File.expand_path(src) : src.map { |s| File.expand_path(s) }
184
+
185
+ [operation, i18n.send(operation), single, src, File.expand_path(dst.ensure_string)]
186
+ end
187
+
188
+ # :nodoc:
189
+ def dry_run_copy_or_move(single, operation, src, dst)
190
+ if single
191
+ dry_run_copy_or_move_single(src, dst, operation)
192
+ else
193
+ dry_run_copy_or_move_multi(src, dst, operation)
219
194
  end
195
+ end
220
196
 
221
- # Shows which copy or move operation are going to executed.
222
- #
223
- # @param single [Boolean] Whether `src` is a single file or directory.
224
- # @param operation [String] The operation which will be executed.
225
- # @param src [String|Array] The entries to copy or move. If is an Array, `dst` is assumed to be a directory.
226
- # @param dst [String] The destination. **Any existing entries will be overwritten.** Any required directory will be created.
227
- def dry_run_copy_or_move(single, operation, src, dst)
228
- locale = i18n.shell
229
-
230
- if single then
231
- @console.warn(locale.copy_move_single_dry(operation))
232
- @console.write(locale.copy_move_from(File.expand_path(src.ensure_string)), "\n", 11)
233
- @console.write(locale.copy_move_to(dst), "\n", 11)
234
- else
235
- @console.warn(locale.copy_move_multi_dry(operation))
236
- @console.with_indentation(11) do
237
- src.each do |s| @console.write(s) end
238
- end
239
- @console.write(locale.copy_move_to_multi(dst), "\n", 5)
197
+ # :nodoc:
198
+ def dry_run_copy_or_move_single(src, dst, operation)
199
+ @console.warn(i18n.copy_move_single_dry(operation))
200
+ @console.write(i18n.copy_move_from(File.expand_path(src.ensure_string)), suffix: "\n", indented: 11)
201
+ @console.write(i18n.copy_move_to(dst), suffix: "\n", indented: 11)
202
+ end
203
+
204
+ # :nodoc:
205
+ def dry_run_copy_or_move_multi(src, dst, operation)
206
+ @console.warn(i18n.copy_move_multi_dry(operation))
207
+ @console.with_indentation(11) do
208
+ src.each do |s|
209
+ @console.write(s)
240
210
  end
241
211
  end
212
+ @console.write(i18n.copy_move_to_multi(dst), suffix: "\n", indented: 5)
213
+ end
242
214
 
243
- # Prepares a destination directory for a copy or move.
244
- #
245
- # @param single [Boolean] Whether `src` is a single file or directory.
246
- # @param src [String|Array] The entries to copy or move. If is an Array, `dst` is assumed to be a directory.
247
- # @param dst [String] The destination. **Any existing entries will be overwritten.** Any required directory will be created.
248
- # @param operation [String] The operation which will be executed.
249
- # @param show_errors [Boolean] If show errors.
250
- # @param fatal [Boolean] If quit in case of fatal errors.
251
- # @return [String] The prepared destination.
252
- def prepare_destination(single, src, dst, operation, show_errors, fatal)
253
- dst_dir = single ? File.dirname(dst) : dst
254
- has_dir = check(dst_dir, :dir)
255
-
256
- # Create directory
257
- has_dir = create_directories(dst_dir, 0755, true, show_errors, fatal) if !has_dir
258
- throw(:rv, false) if !has_dir
259
-
260
- if single && check(dst, :dir) then
261
- @console.send(fatal ? :fatal : :error, i18n.shell.copy_move_single_to_directory(operation, src, dst))
262
- throw(:rv, false)
263
- end
215
+ # :nodoc:
216
+ def prepare_destination(single, src, dst, operation, show_errors, fatal)
217
+ dst_dir = single ? File.dirname(dst) : dst
218
+ has_dir = check(dst_dir, :dir)
264
219
 
265
- dst_dir
266
- end
220
+ # Create directory
221
+ has_dir = create_directories(dst_dir, mode: 0755, show_errors: show_errors, fatal_errors: fatal) unless has_dir
222
+ throw(:rv, false) unless has_dir
267
223
 
268
- # Checks every sources for a copy or move.
269
- #
270
- # @param src [String|Array] The entries to copy or move. If is an Array, `dst` is assumed to be a directory.
271
- # @param operation [String] The operation which will be executed.
272
- # @param fatal [Boolean] If quit in case of fatal errors.
273
- def check_sources(src, operation, fatal)
274
- # Check that every file is existing
275
- src.ensure_array.each do |s|
276
- if !check(s, :exists) then
277
- @console.send(fatal ? :fatal : :error, i18n.shell.copy_move_src_not_found(operation, s))
278
- throw(:rv, false)
279
- end
280
- end
224
+ # Check if the destination directory is a file in single mode
225
+ if single && check(dst, :dir)
226
+ @console.send(fatal ? :fatal : :error, i18n.copy_move_single_to_directory(operation, src, dst))
227
+ throw(:rv, false)
281
228
  end
282
229
 
283
- # Executes the copy or move operation.
284
- #
285
- # @param src [String|Array] The entries to copy or move. If is an Array, `dst` is assumed to be a directory.
286
- # @param dst [String] The destination. **Any existing entries will be overwritten.** Any required directory will be created.
287
- # @param dst_dir [String] The destination directory.
288
- # @param single [Boolean] Whether `src` is a single file or directory.
289
- # @param operation [Symbol] The operation to perform. Valid values are `:copy` or `:move`.
290
- # @param operation_s [String] The string representation of the operation to perform.
291
- # @param show_errors [Boolean] If show errors.
292
- # @param fatal [Boolean] If quit in case of fatal errors.
293
- def execute_copy_or_move(src, dst, dst_dir, single, operation, operation_s, show_errors, fatal)
294
- locale = i18n.shell
230
+ dst_dir
231
+ end
295
232
 
296
- begin
297
- FileUtils.send(operation == :move ? :mv : :cp_r, src, dst, {noop: false, verbose: false})
298
- rescue Errno::EACCES
299
- single_msg = locale.copy_move_dst_not_writable_single(operation_s, src, dst_dir)
300
- multi_msg = locale.copy_move_dst_not_writable_single(operation_s, dst)
301
- handle_copy_move_failure(single, src, show_errors, fatal, single_msg, multi_msg, nil)
302
- rescue => e
303
- single_msg = locale.copy_move_error_single(operation_s, src, dst_dir, e.class.to_s, e)
304
- multi_msg = locale.copy_move_error_multi(operation_s, dst)
305
- handle_copy_move_failure(single, src, show_errors, fatal, single_msg, multi_msg, locale.error(e.class.to_s, e))
233
+ # :nodoc:
234
+ def check_sources(src, operation, fatal)
235
+ # Check that every file is existing
236
+ src.ensure_array.each do |s|
237
+ unless check(s, :exists)
238
+ @console.send(fatal ? :fatal : :error, i18n.copy_move_src_not_found(operation, s))
239
+ throw(:rv, false)
306
240
  end
307
241
  end
242
+ end
308
243
 
309
- # Handles a failure on copy or move.
310
- #
311
- # @param single [Boolean] Whether `src` is a single file or directory.
312
- # @param src [String|Array] The entries to copy or move. If is an Array, `dst` is assumed to be a directory.
313
- # @param show_errors [Boolean] If show errors.
314
- # @param fatal [Boolean] If quit in case of fatal errors.
315
- # @param single_msg [String] The message to show in case of a single source.
316
- # @param multi_msg [String] The starting message to show in case of multiple sources.
317
- # @param error [String|nil] The ending message to show in case of multiple sources.
318
- def handle_copy_move_failure(single, src, show_errors, fatal, single_msg, multi_msg, error)
319
- if single then
320
- @console.send(fatal ? :fatal : :error, single_msg, "\n", 5) if fatal || show_errors
321
- else
322
- if show_errors then
323
- @console.error(multi_msg)
324
- @console.with_indentation(11) do
325
- src.each do |s| @console.write(s) end
326
- end
327
- @console.write(error, "\n", 5) if error
328
- end
244
+ # :nodoc:
245
+ def execute_copy_or_move(src, dst, dst_dir, single, operation, operation_s, show_errors, fatal)
246
+ FileUtils.send(operation == :move ? :mv : :cp_r, src, dst, {noop: false, verbose: false})
247
+ rescue Errno::EACCES
248
+ handle_copy_or_move_access_error(src, dst, dst_dir, single, operation_s, show_errors, fatal)
249
+ rescue => e
250
+ handle_copy_or_move_general_erorr(src, dst, dst_dir, single, e, operation_s, show_errors, fatal)
251
+ end
252
+
253
+ # :nodoc:
254
+ def handle_copy_or_move_general_erorr(src, dst, dst_dir, single, e, operation_s, show_errors, fatal)
255
+ single_msg = i18n.copy_move_error_single(operation_s, src, dst_dir, e.class.to_s, e)
256
+ multi_msg = i18n.copy_move_error_multi(operation_s, dst)
257
+ handle_copy_or_move_failure(single, src, show_errors, fatal, single_msg, multi_msg, i18n.error(e.class.to_s, e))
258
+ end
329
259
 
260
+ # :nodoc:
261
+ def handle_copy_or_move_access_error(src, dst, dst_dir, single, operation_s, show_errors, fatal)
262
+ single_msg = i18n.copy_move_dst_not_writable_single(operation_s, src, dst_dir)
263
+ multi_msg = i18n.copy_move_dst_not_writable_multi(operation_s, dst)
264
+ handle_copy_or_move_failure(single, src, show_errors, fatal, single_msg, multi_msg, nil)
265
+ end
266
+
267
+ # :nodoc:
268
+ def handle_copy_or_move_failure(single, src, show_errors, fatal, single_msg, multi_msg, error)
269
+ if fatal || show_errors
270
+ if single
271
+ @console.send(fatal ? :fatal : :error, single_msg, suffix: "\n", indented: 5)
272
+ else
273
+ show_copy_move_failed_files(src, error, multi_msg)
330
274
  Kernel.exit(-1) if fatal
331
275
  end
276
+ end
332
277
 
333
- throw(:rv, false)
278
+ throw(:rv, false)
279
+ end
280
+
281
+ # :nodoc:
282
+ def show_copy_move_failed_files(src, error, multi_msg)
283
+ @console.error(multi_msg)
284
+ @console.with_indentation(11) do
285
+ src.each do |s|
286
+ @console.write(s)
287
+ end
334
288
  end
289
+ @console.write(error, suffix: "\n", indented: 5) if error
290
+ end
335
291
  end
336
292
 
337
293
  # Methods to run commands or delete entries.
@@ -344,26 +300,23 @@ module Bovem
344
300
  # @param show_exit [Boolean] If show the exit status.
345
301
  # @param show_output [Boolean] If show command output.
346
302
  # @param show_command [Boolean] If show the command that will be run.
347
- # @param fatal [Boolean] If quit in case of fatal errors.
303
+ # @param fatal_errors [Boolean] If quit in case of fatal errors.
348
304
  # @return [Hash] An hash with `status` and `output` keys.
349
- def run(command, message = nil, run = true, show_exit = true, show_output = false, show_command = false, fatal = true)
305
+ def run(command, message = nil, run: true, show_exit: true, show_output: false, show_command: false, fatal_errors: true)
350
306
  rv = {status: 0, output: ""}
351
307
  command = command.ensure_string
352
- locale = i18n.shell
353
308
 
354
309
  # Show the command
355
310
  @console.begin(message) if message.present?
356
311
 
357
- if !run then # Print a message
358
- @console.warn(locale.run_dry(command))
359
- @console.status(:ok) if show_exit
312
+ if !run # Print a message
313
+ show_dry_run(command, show_exit)
360
314
  else # Run
361
315
  rv = execute_command(command, show_command, show_output)
362
316
  end
363
317
 
364
318
  # Return
365
- @console.status(rv[:status] == 0 ? :ok : :fail) if show_exit
366
- exit(rv[:status]) if fatal && rv[:status] != 0
319
+ handle_command_exit(rv, show_exit, fatal_errors)
367
320
  rv
368
321
  end
369
322
 
@@ -372,54 +325,73 @@ module Bovem
372
325
  # @param files [Array] The list of files to remove
373
326
  # @param run [Boolean] If `false`, it will just print a list of message that would be deleted.
374
327
  # @param show_errors [Boolean] If show errors.
375
- # @param fatal [Boolean] If quit in case of fatal errors.
328
+ # @param fatal_errors [Boolean] If quit in case of fatal errors.
376
329
  # @return [Boolean] `true` if operation succeeded, `false` otherwise.
377
- def delete(files, run = true, show_errors = false, fatal = true)
330
+ def delete(*files, run: true, show_errors: false, fatal_errors: true)
378
331
  rv = true
379
- locale = i18n.shell
380
- files = files.ensure_array(nil, true, true) {|f| File.expand_path(f.ensure_string) }
332
+ files = files.ensure_array(no_duplicates: true, compact: true, flatten: true) { |f| File.expand_path(f.ensure_string) }
381
333
 
382
- if !run then
383
- @console.warn(locale.remove_dry)
384
- @console.with_indentation(11) do
385
- files.each do |file| @console.write(file) end
386
- end
334
+ if !run
335
+ show_dry_delete(files)
387
336
  else
388
- rv = catch(:rv) do
389
- begin
390
- FileUtils.rm_r(files, {noop: false, verbose: false, secure: true})
391
- throw(:rv, true)
392
- rescue => e
393
- handle_failure(e, :remove_unwritable, :remove_not_found, :remove_error, files, fatal, show_errors)
394
- end
395
-
396
- false
397
- end
337
+ rv = perform_delete(files, show_errors, fatal_errors)
398
338
  end
399
339
 
400
340
  rv
401
341
  end
402
342
 
403
343
  private
404
- # Runs a command into the shell.
405
- #
406
- # @param command [String] The string to run.
407
- # @param show_command [Boolean] If show the command that will be run.
408
- # @param show_output [Boolean] If show command output.
409
- # @return [Hash] An hash with `status` and `output` keys.
410
- def execute_command(command, show_command, show_output)
411
- output = ""
412
-
413
- @console.info(i18n.shell.run(command)) if show_command
414
- status = ::Open4::popen4(command + " 2>&1") { |_, _, stdout, _|
415
- stdout.each_line do |line|
416
- output << line
417
- Kernel.print line if show_output
418
- end
419
- }.exitstatus
420
344
 
421
- {status: status, output: output}
345
+ # :nodoc:
346
+ def execute_command(command, show_command, show_output)
347
+ output = ""
348
+
349
+ @console.info(i18n.run(command)) if show_command
350
+ status = ::Open4.popen4(command + " 2>&1") do |_, _, stdout, _|
351
+ stdout.each_line do |line|
352
+ output << line
353
+ Kernel.print line if show_output
354
+ end
355
+ end
356
+
357
+ {status: status.exitstatus, output: output}
358
+ end
359
+
360
+ # :nodoc:
361
+ def handle_command_exit(rv, show_exit, fatal_errors)
362
+ @console.status(rv[:status] == 0 ? :ok : :fail) if show_exit
363
+ exit(rv[:status]) if fatal_errors && rv[:status] != 0
364
+ end
365
+
366
+ # :nodoc:
367
+ def show_dry_run(command, show_exit)
368
+ @console.warn(i18n.run_dry(command))
369
+ @console.status(:ok) if show_exit
370
+ end
371
+
372
+ # :nodoc:
373
+ def perform_delete(files, show_errors, fatal)
374
+ catch(:rv) do
375
+ begin
376
+ FileUtils.rm_r(files, {noop: false, verbose: false, secure: true})
377
+ throw(:rv, true)
378
+ rescue => e
379
+ handle_failure(e, :remove_unwritable, :remove_not_found, :remove_error, files, fatal, show_errors)
380
+ end
381
+
382
+ false
422
383
  end
384
+ end
385
+
386
+ # :nodoc:
387
+ def show_dry_delete(files)
388
+ @console.warn(i18n.remove_dry)
389
+ @console.with_indentation(11) do
390
+ files.each do |file|
391
+ @console.write(file)
392
+ end
393
+ end
394
+ end
423
395
  end
424
396
 
425
397
  # Methods to interact with directories.
@@ -430,15 +402,13 @@ module Bovem
430
402
  # @param restore [Boolean] If to restore the original working directory.
431
403
  # @param show_messages [Boolean] Show informative messages about working directory changes.
432
404
  # @return [Boolean] `true` if the directory was valid and the code executed, `false` otherwise.
433
- def within_directory(directory, restore = true, show_messages = false)
434
- locale = i18n.shell
435
-
405
+ def within_directory(directory, restore: true, show_messages: false)
436
406
  directory = File.expand_path(directory.ensure_string)
437
407
  original = Dir.pwd
438
408
 
439
- rv = enter_directory(directory, show_messages, locale.move_in(directory))
409
+ rv = enter_directory(directory, show_messages, i18n.move_in(directory))
440
410
  yield if rv && block_given?
441
- rv = enter_directory(original, show_messages, locale.move_out(directory)) if rv && restore
411
+ rv = enter_directory(original, show_messages, i18n.move_out(directory)) if rv && restore
442
412
 
443
413
  rv
444
414
  end
@@ -449,20 +419,20 @@ module Bovem
449
419
  # @param mode [Fixnum] Initial permissions for the new directories.
450
420
  # @param run [Boolean] If `false`, it will just print a list of directories that would be created.
451
421
  # @param show_errors [Boolean] If show errors.
452
- # @param fatal [Boolean] If quit in case of fatal errors.
422
+ # @param fatal_errors [Boolean] If quit in case of fatal errors.
453
423
  # @return [Boolean] `true` if operation succeeded, `false` otherwise.
454
- def create_directories(directories, mode = 0755, run = true, show_errors = false, fatal = true)
424
+ def create_directories(*directories, mode: 0755, run: true, show_errors: false, fatal_errors: true)
455
425
  rv = true
456
426
 
457
427
  # Adjust directory
458
- directories = directories.ensure_array(nil, true, true) {|d| File.expand_path(d.ensure_string) }
428
+ directories = directories.ensure_array(no_duplicates: true, compact: true, flatten: true) { |d| File.expand_path(d.ensure_string) }
459
429
 
460
- if !run then # Just print
430
+ if !run # Just print
461
431
  dry_run_directory_creation(directories)
462
432
  else
463
433
  directories.each do |directory|
464
- rv = rv && try_create_directory(directory, mode, fatal, directories, show_errors)
465
- break if !rv
434
+ rv &&= try_create_directory(directory, mode, fatal_errors, directories, show_errors)
435
+ break unless rv
466
436
  end
467
437
  end
468
438
 
@@ -470,76 +440,56 @@ module Bovem
470
440
  end
471
441
 
472
442
  private
473
- # Change current working directory.
474
- #
475
- # @param directory [String] The directory which move into.
476
- # @param show_message [Boolean] Whether to show or not message.
477
- # @param message [String] The message to show.
478
- # @return [Boolean] `true` if operation succeeded, `false` otherwise.
479
- def enter_directory(directory, show_message, message)
480
- begin
481
- raise ArgumentError if !check(directory, [:directory, :executable])
482
- @console.info(message) if show_message
483
- Dir.chdir(directory)
484
- true
485
- rescue
486
- false
487
- end
488
- end
489
443
 
490
- # Show which directory are going to be created.
491
- # @param directories [Array] The list of directories to create.
492
- def dry_run_directory_creation(directories)
493
- @console.warn(i18n.shell.mkdir_dry)
494
- @console.with_indentation(11) do
495
- directories.each do |directory| @console.write(directory) end
444
+ # :nodoc:
445
+ def enter_directory(directory, show_message, message)
446
+ raise ArgumentError unless check(directory, :directory, :executable)
447
+ @console.info(message) if show_message
448
+ Dir.chdir(directory)
449
+ true
450
+ rescue
451
+ false
452
+ end
453
+
454
+ # :nodoc:
455
+ def dry_run_directory_creation(directories)
456
+ @console.warn(i18n.mkdir_dry)
457
+ @console.with_indentation(11) do
458
+ directories.each do |directory|
459
+ @console.write(directory)
496
460
  end
497
461
  end
462
+ end
498
463
 
499
- # Tries to creates a directory.
500
- #
501
- # @param directory [String] The directory to create.
502
- # @param mode [Fixnum] Initial permissions for the new directories.
503
- # @param fatal [Boolean] If quit in case of fatal errors.
504
- # @param directories [Array] The list of directories to create.
505
- # @param show_errors [Boolean] If show errors.
506
- # @return [Boolean] `true` if operation succeeded, `false` otherwise.
507
- def try_create_directory(directory, mode, fatal, directories, show_errors)
508
- rv = false
509
- locale = i18n.shell
510
-
511
- # Perform tests
512
- if check(directory, :directory) then
513
- @console.send(fatal ? :fatal : :error, locale.mkdir_existing(directory))
514
- elsif check(directory, :exist) then
515
- @console.send(fatal ? :fatal : :error, locale.mkdir_file(directory))
516
- else
517
- rv = create_directory(directory, mode, fatal, directories, show_errors)
518
- end
464
+ # :nodoc:
465
+ def try_create_directory(directory, mode, fatal, directories, show_errors)
466
+ rv = false
519
467
 
520
- rv
468
+ # Perform tests
469
+ if check(directory, :directory)
470
+ @console.send(fatal ? :fatal : :error, i18n.mkdir_existing(directory))
471
+ elsif check(directory, :exist)
472
+ @console.send(fatal ? :fatal : :error, i18n.mkdir_file(directory))
473
+ else
474
+ rv = create_directory(directory, mode, fatal, directories, show_errors)
521
475
  end
522
476
 
523
- # Creates a directory.
524
- #
525
- # @param directory [String] The directory to create.
526
- # @param mode [Fixnum] Initial permissions for the new directories.
527
- # @param fatal [Boolean] If quit in case of fatal errors.
528
- # @param directories [Array] The list of directories to create.
529
- # @param show_errors [Boolean] If show errors.
530
- # @return [Boolean] `true` if operation succeeded, `false` otherwise.
531
- def create_directory(directory, mode, fatal, directories, show_errors)
532
- rv = false
533
-
534
- begin # Create directory
535
- FileUtils.mkdir_p(directory, {mode: mode, noop: false, verbose: false})
536
- rv = true
537
- rescue => e
538
- handle_failure(e, :mkdir_denied, nil, :mkdir_error, directories, fatal, show_errors)
539
- end
477
+ rv
478
+ end
479
+
480
+ # :nodoc:
481
+ def create_directory(directory, mode, fatal, directories, show_errors)
482
+ rv = false
540
483
 
541
- rv
484
+ begin # Create directory
485
+ FileUtils.mkdir_p(directory, {mode: mode, noop: false, verbose: false})
486
+ rv = true
487
+ rescue => e
488
+ handle_failure(e, :mkdir_denied, nil, :mkdir_error, directories, fatal, show_errors)
542
489
  end
490
+
491
+ rv
492
+ end
543
493
  end
544
494
  end
545
495
 
@@ -547,8 +497,9 @@ module Bovem
547
497
  #
548
498
  # @attribute console
549
499
  # @return [Console] A console instance.
500
+ # @attribute [r] i18n
501
+ # @return [I18n] A i18n helper.
550
502
  class Shell
551
- include Lazier::I18n
552
503
  include Bovem::ShellMethods::General
553
504
  include Bovem::ShellMethods::Read
554
505
  include Bovem::ShellMethods::Write
@@ -556,6 +507,7 @@ module Bovem
556
507
  include Bovem::ShellMethods::Directories
557
508
 
558
509
  attr_accessor :console
510
+ attr_reader :i18n
559
511
 
560
512
  # Returns a unique instance for Shell.
561
513
  #
@@ -567,7 +519,7 @@ module Bovem
567
519
  # Initializes a new Shell.
568
520
  def initialize
569
521
  @console = Bovem::Console.instance
570
- i18n_setup(:bovem, ::File.absolute_path(::Pathname.new(::File.dirname(__FILE__)).to_s + "/../../locales/"))
522
+ @i18n = Bovem::I18n.new(root: "bovem.shell", path: Bovem::Application::LOCALE_ROOT)
571
523
  end
572
524
  end
573
- end
525
+ end