escort 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +8 -8
  2. data/.travis.yml +8 -0
  3. data/README.md +365 -14
  4. data/TODO.md +157 -44
  5. data/escort.gemspec +1 -0
  6. data/examples/{1_1_basic.rb → attic/1_1_basic.rb} +0 -0
  7. data/examples/{1_2_basic_requires_arguments.rb → attic/1_2_basic_requires_arguments.rb} +0 -0
  8. data/examples/{2_2_command.rb → attic/2_2_command.rb} +0 -0
  9. data/examples/{2_2_command_requires_arguments.rb → attic/2_2_command_requires_arguments.rb} +0 -0
  10. data/examples/{2_3_nested_commands.rb → attic/2_3_nested_commands.rb} +0 -0
  11. data/examples/{3_validations.rb → attic/3_validations.rb} +0 -0
  12. data/examples/{4_1_config_file.rb → attic/4_1_config_file.rb} +0 -0
  13. data/examples/{argument_handling → attic/argument_handling}/basic.rb +0 -0
  14. data/examples/{argument_handling → attic/argument_handling}/basic_command.rb +0 -0
  15. data/examples/{argument_handling → attic/argument_handling}/no_arguments.rb +0 -0
  16. data/examples/{argument_handling → attic/argument_handling}/no_arguments_command.rb +0 -0
  17. data/examples/{command_aliases → attic/command_aliases}/app.rb +0 -0
  18. data/examples/{config_file → attic/config_file}/.apprc2 +0 -0
  19. data/examples/{config_file → attic/config_file}/app.rb +0 -0
  20. data/examples/{config_file → attic/config_file}/sub_commands.rb +0 -0
  21. data/examples/{default_command → attic/default_command}/app.rb +0 -0
  22. data/examples/{sub_commands → attic/sub_commands}/app.rb +0 -0
  23. data/examples/{validation_basic → attic/validation_basic}/app.rb +0 -0
  24. data/examples/basic +10 -0
  25. data/examples/basic_conflicts +17 -0
  26. data/examples/basic_depends_on +25 -0
  27. data/examples/basic_flags +15 -0
  28. data/examples/basic_options +14 -0
  29. data/examples/basic_options_multi +15 -0
  30. data/examples/basic_require_arguments +17 -0
  31. data/examples/basic_texts +21 -0
  32. data/examples/basic_validations +21 -0
  33. data/examples/command +19 -0
  34. data/examples/commands/example_command.rb +13 -0
  35. data/lib/escort/action_command/base.rb +4 -0
  36. data/lib/escort/app.rb +33 -11
  37. data/lib/escort/formatter/borderless_table.rb +4 -0
  38. data/lib/escort/formatter/command.rb +87 -0
  39. data/lib/escort/formatter/commands.rb +36 -0
  40. data/lib/escort/formatter/default_help_formatter.rb +68 -73
  41. data/lib/escort/formatter/global_command.rb +17 -0
  42. data/lib/escort/formatter/option.rb +138 -0
  43. data/lib/escort/formatter/options.rb +17 -3
  44. data/lib/escort/formatter/shell_command_executor.rb +49 -0
  45. data/lib/escort/formatter/terminal.rb +17 -9
  46. data/lib/escort/formatter/terminal_formatter.rb +6 -0
  47. data/lib/escort/logger.rb +4 -4
  48. data/lib/escort/option_dependency_validator.rb +83 -0
  49. data/lib/escort/option_parser.rb +11 -1
  50. data/lib/escort/setup/configuration/reader.rb +0 -2
  51. data/lib/escort/setup/configuration/writer.rb +0 -2
  52. data/lib/escort/setup/dsl/command.rb +2 -7
  53. data/lib/escort/setup/dsl/global.rb +2 -9
  54. data/lib/escort/setup/dsl/options.rb +56 -0
  55. data/lib/escort/setup_accessor.rb +23 -6
  56. data/lib/escort/trollop.rb +4 -3
  57. data/lib/escort/validator.rb +4 -1
  58. data/lib/escort/version.rb +1 -1
  59. data/lib/escort.rb +8 -1
  60. data/spec/integration/basic_conflicts_spec.rb +47 -0
  61. data/spec/integration/basic_depends_on_spec.rb +275 -0
  62. data/spec/integration/basic_options_spec.rb +9 -21
  63. data/spec/integration/basic_options_with_multi_spec.rb +30 -0
  64. data/spec/integration/basic_spec.rb +5 -6
  65. data/spec/integration/basic_validations_spec.rb +77 -0
  66. data/spec/integration/basic_with_arguments_spec.rb +33 -0
  67. data/spec/integration/basic_with_text_fields_spec.rb +21 -0
  68. data/spec/lib/escort/formatter/command_spec.rb +238 -0
  69. data/spec/lib/escort/formatter/global_command_spec.rb +50 -0
  70. data/spec/lib/escort/formatter/option_spec.rb +300 -0
  71. data/spec/lib/escort/formatter/shell_command_executor_spec.rb +59 -0
  72. data/spec/lib/escort/formatter/string_splitter_spec.rb +12 -0
  73. data/spec/lib/escort/formatter/terminal_spec.rb +19 -0
  74. data/spec/lib/escort/setup_accessor_spec.rb +1 -0
  75. data/spec/spec_helper.rb +9 -3
  76. data/spec/support/integration_helpers.rb +2 -0
  77. data/spec/{helpers/execute_action_matcher.rb → support/matchers/execute_action_for_command_matcher.rb} +3 -3
  78. data/spec/support/matchers/execute_action_with_arguments_matcher.rb +25 -0
  79. data/spec/support/matchers/execute_action_with_options_matcher.rb +29 -0
  80. data/spec/support/matchers/exit_with_code_matcher.rb +29 -0
  81. data/spec/support/shared_contexts/integration_setup.rb +34 -0
  82. metadata +86 -28
  83. data/examples/basic/app.rb +0 -16
  84. data/lib/escort/formatter/common.rb +0 -58
  85. data/spec/helpers/exit_with_code_matcher.rb +0 -21
  86. 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
- option_strings = option_output_strings(parser)
15
- command_strings = command_output_strings
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.puts "NAME"
19
- d.indent(4) do
20
- d.table(:columns => 3, :newlines => 1) do |t|
21
- t.row script_name_with_command, '-', current_command_summary
22
- end
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 script_name_with_command
67
- result = []
68
- result << script_name
69
- result << current_command unless context.empty?
70
- result.join(" ")
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 script_name
74
- File.basename($0)
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
- context.last || :global
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 command_outline(command_data)
82
- result = command_data[1] || ''
83
- result = command_data[2] || '' if result.nil? || result.empty?
84
- result
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 current_command_summary
88
- setup.summary_for(context) || ''
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 command_output_strings
92
- commands = {}
93
- setup.canonical_command_names_for(context).each do |command_name|
94
- command_description = setup.command_description_for(command_name, context) || ""
95
- command_summary = setup.command_summary_for(command_name, context) || ""
96
- command_aliases = setup.command_aliases_for(command_name, context)
97
- command_alias_string = command_aliases.join(", ") if command_aliases && command_aliases.size > 0
98
- command_string = (command_aliases && command_aliases.size > 0 ? "#{command_name}, #{command_alias_string}" : "#{command_name}" )
99
- command_name = command_name.to_s
100
- commands[command_name] = [command_string, command_summary, command_description]
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
- attr_reader :setup, :context, :parser
4
+ include Enumerable
5
5
 
6
- def initialize(setup, context, parser)
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
- screen_size = self::DEFAULT_WIDTH
11
- Curses.init_screen
12
- begin
13
- screen_size = Curses.cols
14
- ensure
15
- Curses.close_screen
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
- "\"#{msg2str(msg)}\"\n"
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 \"#{msg2str(msg, 10)}\"\n", severity)
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
- "\"#{msg}\"\n"
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}", " ")}.join("\n")
67
+ (msg.backtrace || []).map{|line| sprintf("%#{backtrace_indent}s#{line}", "")}.join("\n")
68
68
  else
69
69
  msg.inspect
70
70
  end