escort 0.1.0 → 0.2.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.
- checksums.yaml +8 -8
- data/.travis.yml +8 -0
- data/README.md +365 -14
- data/TODO.md +157 -44
- data/escort.gemspec +1 -0
- data/examples/{1_1_basic.rb → attic/1_1_basic.rb} +0 -0
- data/examples/{1_2_basic_requires_arguments.rb → attic/1_2_basic_requires_arguments.rb} +0 -0
- data/examples/{2_2_command.rb → attic/2_2_command.rb} +0 -0
- data/examples/{2_2_command_requires_arguments.rb → attic/2_2_command_requires_arguments.rb} +0 -0
- data/examples/{2_3_nested_commands.rb → attic/2_3_nested_commands.rb} +0 -0
- data/examples/{3_validations.rb → attic/3_validations.rb} +0 -0
- data/examples/{4_1_config_file.rb → attic/4_1_config_file.rb} +0 -0
- data/examples/{argument_handling → attic/argument_handling}/basic.rb +0 -0
- data/examples/{argument_handling → attic/argument_handling}/basic_command.rb +0 -0
- data/examples/{argument_handling → attic/argument_handling}/no_arguments.rb +0 -0
- data/examples/{argument_handling → attic/argument_handling}/no_arguments_command.rb +0 -0
- data/examples/{command_aliases → attic/command_aliases}/app.rb +0 -0
- data/examples/{config_file → attic/config_file}/.apprc2 +0 -0
- data/examples/{config_file → attic/config_file}/app.rb +0 -0
- data/examples/{config_file → attic/config_file}/sub_commands.rb +0 -0
- data/examples/{default_command → attic/default_command}/app.rb +0 -0
- data/examples/{sub_commands → attic/sub_commands}/app.rb +0 -0
- data/examples/{validation_basic → attic/validation_basic}/app.rb +0 -0
- data/examples/basic +10 -0
- data/examples/basic_conflicts +17 -0
- data/examples/basic_depends_on +25 -0
- data/examples/basic_flags +15 -0
- data/examples/basic_options +14 -0
- data/examples/basic_options_multi +15 -0
- data/examples/basic_require_arguments +17 -0
- data/examples/basic_texts +21 -0
- data/examples/basic_validations +21 -0
- data/examples/command +19 -0
- data/examples/commands/example_command.rb +13 -0
- data/lib/escort/action_command/base.rb +4 -0
- data/lib/escort/app.rb +33 -11
- data/lib/escort/formatter/borderless_table.rb +4 -0
- data/lib/escort/formatter/command.rb +87 -0
- data/lib/escort/formatter/commands.rb +36 -0
- data/lib/escort/formatter/default_help_formatter.rb +68 -73
- data/lib/escort/formatter/global_command.rb +17 -0
- data/lib/escort/formatter/option.rb +138 -0
- data/lib/escort/formatter/options.rb +17 -3
- data/lib/escort/formatter/shell_command_executor.rb +49 -0
- data/lib/escort/formatter/terminal.rb +17 -9
- data/lib/escort/formatter/terminal_formatter.rb +6 -0
- data/lib/escort/logger.rb +4 -4
- data/lib/escort/option_dependency_validator.rb +83 -0
- data/lib/escort/option_parser.rb +11 -1
- data/lib/escort/setup/configuration/reader.rb +0 -2
- data/lib/escort/setup/configuration/writer.rb +0 -2
- data/lib/escort/setup/dsl/command.rb +2 -7
- data/lib/escort/setup/dsl/global.rb +2 -9
- data/lib/escort/setup/dsl/options.rb +56 -0
- data/lib/escort/setup_accessor.rb +23 -6
- data/lib/escort/trollop.rb +4 -3
- data/lib/escort/validator.rb +4 -1
- data/lib/escort/version.rb +1 -1
- data/lib/escort.rb +8 -1
- data/spec/integration/basic_conflicts_spec.rb +47 -0
- data/spec/integration/basic_depends_on_spec.rb +275 -0
- data/spec/integration/basic_options_spec.rb +9 -21
- data/spec/integration/basic_options_with_multi_spec.rb +30 -0
- data/spec/integration/basic_spec.rb +5 -6
- data/spec/integration/basic_validations_spec.rb +77 -0
- data/spec/integration/basic_with_arguments_spec.rb +33 -0
- data/spec/integration/basic_with_text_fields_spec.rb +21 -0
- data/spec/lib/escort/formatter/command_spec.rb +238 -0
- data/spec/lib/escort/formatter/global_command_spec.rb +50 -0
- data/spec/lib/escort/formatter/option_spec.rb +300 -0
- data/spec/lib/escort/formatter/shell_command_executor_spec.rb +59 -0
- data/spec/lib/escort/formatter/string_splitter_spec.rb +12 -0
- data/spec/lib/escort/formatter/terminal_spec.rb +19 -0
- data/spec/lib/escort/setup_accessor_spec.rb +1 -0
- data/spec/spec_helper.rb +9 -3
- data/spec/support/integration_helpers.rb +2 -0
- data/spec/{helpers/execute_action_matcher.rb → support/matchers/execute_action_for_command_matcher.rb} +3 -3
- data/spec/support/matchers/execute_action_with_arguments_matcher.rb +25 -0
- data/spec/support/matchers/execute_action_with_options_matcher.rb +29 -0
- data/spec/support/matchers/exit_with_code_matcher.rb +29 -0
- data/spec/support/shared_contexts/integration_setup.rb +34 -0
- metadata +86 -28
- data/examples/basic/app.rb +0 -16
- data/lib/escort/formatter/common.rb +0 -58
- data/spec/helpers/exit_with_code_matcher.rb +0 -21
- data/spec/helpers/give_option_to_action_with_value_matcher.rb +0 -22
@@ -0,0 +1,87 @@
|
|
1
|
+
module Escort
|
2
|
+
module Formatter
|
3
|
+
class Command
|
4
|
+
attr_reader :setup, :context, :name
|
5
|
+
|
6
|
+
def initialize(command_name, setup, context)
|
7
|
+
@setup = setup
|
8
|
+
@context = context
|
9
|
+
@name = command_name.to_sym
|
10
|
+
end
|
11
|
+
|
12
|
+
def name_with_aliases
|
13
|
+
[name, aliases].flatten.join(", ")
|
14
|
+
end
|
15
|
+
|
16
|
+
def outline
|
17
|
+
summary.empty? ? description : summary
|
18
|
+
end
|
19
|
+
|
20
|
+
def description
|
21
|
+
@description ||= setup.command_description_for(name, context) || ""
|
22
|
+
end
|
23
|
+
|
24
|
+
def summary
|
25
|
+
@summary ||= setup.command_summary_for(name, context) || ""
|
26
|
+
end
|
27
|
+
|
28
|
+
def aliases
|
29
|
+
@aliases ||= setup.command_aliases_for(name, context)
|
30
|
+
end
|
31
|
+
|
32
|
+
def has_aliases?
|
33
|
+
aliases && aliases.size > 0 ? true : false
|
34
|
+
end
|
35
|
+
|
36
|
+
def script_name
|
37
|
+
[canonical_script_name, context].flatten.join(" ")
|
38
|
+
end
|
39
|
+
|
40
|
+
def child_commands
|
41
|
+
@child_commands ||= setup.canonical_command_names_for(context) || []
|
42
|
+
end
|
43
|
+
|
44
|
+
def has_child_commands?
|
45
|
+
child_commands.length > 0
|
46
|
+
end
|
47
|
+
|
48
|
+
def requires_arguments?
|
49
|
+
@requires_arguments ||= setup.arguments_required_for(context)
|
50
|
+
end
|
51
|
+
|
52
|
+
def usage
|
53
|
+
[script_name_usage_string, parent_commands_usage_string, child_command_usage_string, arguments_usage_string].flatten.reject(&:empty?).join(" ")
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def script_name_usage_string
|
59
|
+
"#{canonical_script_name} [options]"
|
60
|
+
end
|
61
|
+
|
62
|
+
def parent_commands_usage_string
|
63
|
+
context.map{|command_name| command_with_options(command_name)}.join(" ")
|
64
|
+
end
|
65
|
+
|
66
|
+
def child_command_usage_string
|
67
|
+
has_child_commands? ? "command [command_options]" : ""
|
68
|
+
end
|
69
|
+
|
70
|
+
def arguments_usage_string
|
71
|
+
requires_arguments? ? "arguments" : "[arguments]"
|
72
|
+
end
|
73
|
+
|
74
|
+
def command_with_options(command_name)
|
75
|
+
"#{command_name} [#{command_name}_options]"
|
76
|
+
end
|
77
|
+
|
78
|
+
def canonical_script_name
|
79
|
+
File.basename($0)
|
80
|
+
end
|
81
|
+
|
82
|
+
def alias_string
|
83
|
+
@alias_string ||= aliases.join(", ") if has_aliases?
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Escort
|
2
|
+
module Formatter
|
3
|
+
class Commands
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def command_for(setup, context)
|
8
|
+
if context.empty?
|
9
|
+
GlobalCommand.new(setup)
|
10
|
+
else
|
11
|
+
Command.new(context.last, setup, context)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :setup, :context
|
17
|
+
|
18
|
+
def initialize(setup, context)
|
19
|
+
@setup = setup
|
20
|
+
@context = context
|
21
|
+
end
|
22
|
+
|
23
|
+
def each(&block)
|
24
|
+
setup.canonical_command_names_for(context).each do |command_name|
|
25
|
+
command = Command.new(command_name, setup, context)
|
26
|
+
block.call(command)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def count
|
31
|
+
setup.canonical_command_names_for(context).size
|
32
|
+
end
|
33
|
+
alias_method :size, :count
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,8 +1,6 @@
|
|
1
1
|
module Escort
|
2
2
|
module Formatter
|
3
3
|
class DefaultHelpFormatter
|
4
|
-
include Escort::Formatter::Common
|
5
|
-
|
6
4
|
attr_reader :setup, :context
|
7
5
|
|
8
6
|
def initialize(setup, context)
|
@@ -11,95 +9,92 @@ module Escort
|
|
11
9
|
end
|
12
10
|
|
13
11
|
def print(parser)
|
14
|
-
|
15
|
-
|
12
|
+
options = Options.new(parser, setup, context)
|
13
|
+
commands = Commands.new(setup, context)
|
14
|
+
current_command = Commands.command_for(setup, context)
|
16
15
|
|
17
16
|
TerminalFormatter.display($stdout, Terminal.width) do |d|
|
18
|
-
d
|
19
|
-
d
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
d.put(setup.description_for(context), :newlines => 2) if setup.description_for(context)
|
24
|
-
end
|
25
|
-
d.puts "USAGE"
|
26
|
-
d.indent(4) do
|
27
|
-
context_usage_part = context.map { |command_name| "#{command_name} [#{command_name} options]" }.join(" ")
|
28
|
-
context_usage_part ||= ""
|
29
|
-
nested_command_part = "command [command options]" if !setup.canonical_command_names_for(context).nil? && setup.canonical_command_names_for(context).length > 0
|
30
|
-
nested_command_part ||= ""
|
31
|
-
usage_string = "#{script_name} [options] #{context_usage_part} #{nested_command_part} [arguments...]".gsub(/\s+/, ' ')
|
32
|
-
d.put usage_string, :newlines => 2
|
33
|
-
end
|
34
|
-
if setup.version
|
35
|
-
d.puts "VERSION"
|
36
|
-
d.indent(4) {
|
37
|
-
d.put setup.version, :newlines => 2
|
38
|
-
}
|
39
|
-
end
|
40
|
-
if option_strings.keys.size > 0
|
41
|
-
d.puts "OPTIONS"
|
42
|
-
d.indent(4) {
|
43
|
-
d.table(:columns => 3, :newlines => 1) do |t|
|
44
|
-
option_strings.each_pair do |key, value|
|
45
|
-
t.row value[:string], '-', value[:desc] || ''
|
46
|
-
end
|
47
|
-
end
|
48
|
-
}
|
49
|
-
end
|
50
|
-
if command_strings.keys.size > 0
|
51
|
-
d.puts "COMMANDS"
|
52
|
-
d.indent(4) {
|
53
|
-
d.table(:columns => 3, :newlines => 1) do |t|
|
54
|
-
command_strings.each_pair do |command_name, values_array|
|
55
|
-
t.row values_array[0], '-', command_outline(values_array)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
}
|
59
|
-
end
|
17
|
+
name_help(current_command, d)
|
18
|
+
usage_help(current_command, d)
|
19
|
+
version_help(current_command, d)
|
20
|
+
options_help(options, d)
|
21
|
+
commands_help(commands, d)
|
60
22
|
end
|
61
23
|
end
|
62
24
|
|
63
|
-
|
64
25
|
private
|
65
26
|
|
66
|
-
def
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
27
|
+
def name_help(current_command, d)
|
28
|
+
d.puts "NAME"
|
29
|
+
d.indent(4) do
|
30
|
+
d.table(:columns => 3, :newlines => 1) do |t|
|
31
|
+
t.row current_command.script_name, '-', current_command.summary
|
32
|
+
end
|
33
|
+
d.put(setup.description_for(context), :newlines => 2) if setup.description_for(context)
|
34
|
+
end
|
71
35
|
end
|
72
36
|
|
73
|
-
def
|
74
|
-
|
37
|
+
def usage_help(current_command, d)
|
38
|
+
d.puts "USAGE"
|
39
|
+
d.indent(4) do
|
40
|
+
d.put current_command.usage, :newlines => 2
|
41
|
+
end
|
75
42
|
end
|
76
43
|
|
77
|
-
def current_command
|
78
|
-
|
44
|
+
def version_help(current_command, d)
|
45
|
+
if setup.version
|
46
|
+
d.puts "VERSION"
|
47
|
+
d.indent(4) {
|
48
|
+
d.put setup.version, :newlines => 2
|
49
|
+
}
|
50
|
+
end
|
79
51
|
end
|
80
52
|
|
81
|
-
def
|
82
|
-
|
83
|
-
|
84
|
-
|
53
|
+
def options_help(options, d)
|
54
|
+
if options.count > 0
|
55
|
+
d.puts "OPTIONS"
|
56
|
+
d.indent(4) {
|
57
|
+
d.table(:columns => 3, :newlines => 1) do |t|
|
58
|
+
options.each do |option|
|
59
|
+
t.row option.usage, '-', option.description
|
60
|
+
option_conflicts_help(option, t)
|
61
|
+
option_dependencies_help(option, t)
|
62
|
+
option_validations_help(option, t)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def option_conflicts_help(option, t)
|
70
|
+
if option.has_conflicts?
|
71
|
+
t.row '', '', "- #{option.conflicts}"
|
72
|
+
end
|
85
73
|
end
|
86
74
|
|
87
|
-
def
|
88
|
-
|
75
|
+
def option_dependencies_help(option, t)
|
76
|
+
if option.has_dependencies?
|
77
|
+
t.row '', '', "- #{option.dependencies}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def option_validations_help(option, t)
|
82
|
+
if option.has_validations?
|
83
|
+
t.row '', '', "- #{option.validations}"
|
84
|
+
end
|
89
85
|
end
|
90
86
|
|
91
|
-
def
|
92
|
-
commands
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
87
|
+
def commands_help(commands, d)
|
88
|
+
if commands.count > 0
|
89
|
+
d.puts "COMMANDS"
|
90
|
+
d.indent(4) {
|
91
|
+
d.table(:columns => 3, :newlines => 1) do |t|
|
92
|
+
commands.each do |command|
|
93
|
+
t.row command.name_with_aliases, '-', command.outline
|
94
|
+
end
|
95
|
+
end
|
96
|
+
}
|
101
97
|
end
|
102
|
-
commands
|
103
98
|
end
|
104
99
|
end
|
105
100
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Escort
|
2
|
+
module Formatter
|
3
|
+
class GlobalCommand < Command
|
4
|
+
def initialize(setup)
|
5
|
+
super(:global, setup, [])
|
6
|
+
end
|
7
|
+
|
8
|
+
def summary
|
9
|
+
@summary ||= setup.summary_for(context) || ""
|
10
|
+
end
|
11
|
+
|
12
|
+
def description
|
13
|
+
@description ||= setup.description_for(context) || ""
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module Escort
|
2
|
+
module Formatter
|
3
|
+
class Option
|
4
|
+
attr_reader :name, :details, :setup, :context
|
5
|
+
|
6
|
+
def initialize(name, details, setup, context)
|
7
|
+
@name = name.to_sym
|
8
|
+
@details = details
|
9
|
+
@setup = setup
|
10
|
+
@context = context
|
11
|
+
end
|
12
|
+
|
13
|
+
def usage
|
14
|
+
[long_string, short_string, type_string].select{|item| !item.empty?}.join(" ")
|
15
|
+
end
|
16
|
+
|
17
|
+
def description
|
18
|
+
[base_description_string, description_default_string].select{|item| !item.empty?}.join(" ")
|
19
|
+
end
|
20
|
+
|
21
|
+
def has_conflicts?
|
22
|
+
!conflicts_list.empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
def conflicts
|
26
|
+
has_conflicts? ? "conflicts with: #{conflicts_list.map{|option| "--#{option}"}.join(', ')}" : ''
|
27
|
+
end
|
28
|
+
|
29
|
+
def has_dependencies?
|
30
|
+
!dependencies_list.empty?
|
31
|
+
end
|
32
|
+
|
33
|
+
def dependencies
|
34
|
+
has_dependencies? ? "depends on: #{format_dependency_list(dependencies_list).join(', ')}" : ''
|
35
|
+
end
|
36
|
+
|
37
|
+
def has_validations?
|
38
|
+
!validations_list.empty?
|
39
|
+
end
|
40
|
+
|
41
|
+
def validations
|
42
|
+
has_validations? ? "#{validation_messages.join("\n- ")}" : ''
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
def validation_messages
|
47
|
+
validations_list.map{|validation| validation[:desc]}
|
48
|
+
end
|
49
|
+
|
50
|
+
def validations_list
|
51
|
+
setup.validations_for(context)[name] || []
|
52
|
+
end
|
53
|
+
|
54
|
+
def format_dependency_list(dependency_list)
|
55
|
+
dependencies_list.map do |option|
|
56
|
+
case option
|
57
|
+
when Hash
|
58
|
+
option.inject([]){|acc, (key, value)| acc << "--#{key}=#{value}"}.join(', ')
|
59
|
+
else
|
60
|
+
"--#{option}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def dependencies_list
|
66
|
+
setup.dependencies_for(context)[name] || []
|
67
|
+
end
|
68
|
+
|
69
|
+
def conflicts_list
|
70
|
+
setup.conflicting_options_for(context)[name] || []
|
71
|
+
end
|
72
|
+
|
73
|
+
def base_description_string
|
74
|
+
details[:desc] || details[:description] || ''
|
75
|
+
end
|
76
|
+
|
77
|
+
def description_default_string
|
78
|
+
if details[:default]
|
79
|
+
base_description_string =~ /\.$/ ? "(Default: #{default_string})" : "(default: #{default_string})"
|
80
|
+
else
|
81
|
+
""
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def default_string
|
86
|
+
case details[:default]
|
87
|
+
when $stdout; "<stdout>"
|
88
|
+
when $stdin; "<stdin>"
|
89
|
+
when $stderr; "<stderr>"
|
90
|
+
when Array
|
91
|
+
details[:default].join(", ")
|
92
|
+
else
|
93
|
+
details[:default].to_s
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def short_string
|
98
|
+
details[:short] && details[:short] != :none ? "-#{details[:short]}" : ""
|
99
|
+
end
|
100
|
+
|
101
|
+
def long_string
|
102
|
+
if flag_with_default_true?
|
103
|
+
"#{base_long_string}, --no-#{details[:long]}"
|
104
|
+
else
|
105
|
+
base_long_string
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def base_long_string
|
110
|
+
"--#{details[:long]}"
|
111
|
+
end
|
112
|
+
|
113
|
+
def type_string
|
114
|
+
case details[:type]
|
115
|
+
when :flag; ""
|
116
|
+
when :int; "<i>"
|
117
|
+
when :ints; "<i+>"
|
118
|
+
when :string; "<s>"
|
119
|
+
when :strings; "<s+>"
|
120
|
+
when :float; "<f>"
|
121
|
+
when :floats; "<f+>"
|
122
|
+
when :io; "<filename/uri>"
|
123
|
+
when :ios; "<filename/uri+>"
|
124
|
+
when :date; "<date>"
|
125
|
+
when :dates; "<date+>"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def flag_with_default_true?
|
130
|
+
flag? && details[:default]
|
131
|
+
end
|
132
|
+
|
133
|
+
def flag?
|
134
|
+
details[:type] == :flag
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -1,13 +1,27 @@
|
|
1
1
|
module Escort
|
2
2
|
module Formatter
|
3
3
|
class Options
|
4
|
-
|
4
|
+
include Enumerable
|
5
5
|
|
6
|
-
|
6
|
+
attr_reader :parser, :setup, :context
|
7
|
+
|
8
|
+
def initialize(parser, setup, context)
|
9
|
+
@parser = parser
|
7
10
|
@setup = setup
|
8
11
|
@context = context
|
9
|
-
@parser = parser
|
10
12
|
end
|
13
|
+
|
14
|
+
def each(&block)
|
15
|
+
parser.specs.each do |option_name, details|
|
16
|
+
option = Option.new(option_name, details, setup, context)
|
17
|
+
block.call(option)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def count
|
22
|
+
parser.specs.keys.size
|
23
|
+
end
|
24
|
+
alias_method :size, :count
|
11
25
|
end
|
12
26
|
end
|
13
27
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module Escort
|
4
|
+
module Formatter
|
5
|
+
class ShellCommandExecutor
|
6
|
+
attr_reader :command
|
7
|
+
|
8
|
+
def initialize(command)
|
9
|
+
@command = command
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute_in_current_shell(success_callback = nil, error_callback = nil)
|
13
|
+
begin
|
14
|
+
result = `#{command}`
|
15
|
+
process_status = $?
|
16
|
+
raise Escort::InternalError.new("Shell command exited with a non-zero (#{process_status.exitstatus}) exit code") if process_status.exitstatus != 0
|
17
|
+
success_callback.call(command, result) if success_callback
|
18
|
+
rescue => e
|
19
|
+
error_callback.call(command, e) if error_callback
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
#def execute_in_new_shell(success_callback = nil, error_callback = nil)
|
25
|
+
#stdin, stdout, stderr = nil, nil, nil
|
26
|
+
#begin
|
27
|
+
#stdin, stdout, stderr, thread = ensure_successful_exit do
|
28
|
+
#Open3.popen3(command)
|
29
|
+
#end
|
30
|
+
#success_callback.call(command, stdin, stdout, stderr) if success_callback
|
31
|
+
#rescue => e
|
32
|
+
#error_callback.call(command, e) if error_callback
|
33
|
+
#nil
|
34
|
+
#ensure
|
35
|
+
#[stdin, stdout, stderr].each {|io| io.close if io}
|
36
|
+
#end
|
37
|
+
#end
|
38
|
+
|
39
|
+
#private
|
40
|
+
|
41
|
+
#def ensure_successful_exit(&block)
|
42
|
+
#stdin, stdout, stderr, thread = block.call
|
43
|
+
#process_status = thread.value
|
44
|
+
#raise Escort::InternalError.new("Shell command exited with a non-zero (#{process_status.exitstatus}) exit code") if process_status.exitstatus != 0
|
45
|
+
#[stdin, stdout, stderr, thread]
|
46
|
+
#end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'curses'
|
2
|
-
|
3
1
|
module Escort
|
4
2
|
module Formatter
|
5
3
|
class Terminal
|
@@ -7,14 +5,24 @@ module Escort
|
|
7
5
|
|
8
6
|
class << self
|
9
7
|
def width
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
8
|
+
tput_width
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def tput_width
|
14
|
+
ShellCommandExecutor.new('/usr/bin/env tput cols').execute_in_current_shell(tput_cols_command_success_callback, tput_cols_command_error_callback) || DEFAULT_WIDTH
|
15
|
+
end
|
16
|
+
|
17
|
+
def tput_cols_command_success_callback
|
18
|
+
lambda {|command, result| result.to_i}
|
19
|
+
end
|
20
|
+
|
21
|
+
def tput_cols_command_error_callback
|
22
|
+
lambda do |command, e|
|
23
|
+
error_logger.debug {e}
|
24
|
+
error_logger.info {"Unable to find terminal width via '#{command}', using default of #{DEFAULT_WIDTH}"}
|
16
25
|
end
|
17
|
-
screen_size
|
18
26
|
end
|
19
27
|
end
|
20
28
|
end
|
@@ -1,3 +1,9 @@
|
|
1
|
+
#TODO rename to StreamOutputFormatter
|
2
|
+
#get rid of the display method, it doesn't really add anything
|
3
|
+
#the max_width should be max_line_width not terminal_columns, there should be no default max_width
|
4
|
+
#indent_count should be indent_width
|
5
|
+
#probably don't really need indent_char, we can assume it is a space
|
6
|
+
#this will only work well with ASCII chars only!!!
|
1
7
|
module Escort
|
2
8
|
module Formatter
|
3
9
|
class TerminalFormatter
|
data/lib/escort/logger.rb
CHANGED
@@ -41,20 +41,20 @@ module Escort
|
|
41
41
|
|
42
42
|
def basic_error_formatter
|
43
43
|
proc do |severity, datetime, progname, msg|
|
44
|
-
"
|
44
|
+
"#{msg2str(msg)}\n"
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
48
|
#"#{severity} [#{datetime.strftime("%d/%b/%Y %H:%M:%S")}] \"#{msg}\"\n"
|
49
49
|
def advanced_error_formatter
|
50
50
|
proc do |severity, datetime, progname, msg|
|
51
|
-
sprintf("%-8s
|
51
|
+
sprintf("%-8s #{msg2str(msg, 10)}\n", severity)
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
55
|
def output_formatter
|
56
56
|
proc do |severity, datetime, progname, msg|
|
57
|
-
"
|
57
|
+
"#{msg}\n"
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
@@ -64,7 +64,7 @@ module Escort
|
|
64
64
|
msg
|
65
65
|
when ::Exception
|
66
66
|
"#{msg.message} (#{ msg.class })\n" <<
|
67
|
-
(msg.backtrace || []).map{|line| sprintf("%#{backtrace_indent}s#{line}", "
|
67
|
+
(msg.backtrace || []).map{|line| sprintf("%#{backtrace_indent}s#{line}", "")}.join("\n")
|
68
68
|
else
|
69
69
|
msg.inspect
|
70
70
|
end
|