quiet_quality 1.4.0 → 1.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 81e7296beb4ced635f0e6e0d1b5521adb6481b3ca4d027e86e76ad1ee8682643
4
- data.tar.gz: 27dfab991d21f98536860a0fdbeed31faa1ea5b65a2af0941e0cc286fe6dcbc1
3
+ metadata.gz: 7ff5a82876936d746842d76e055475ba19e78d0bfff7967b2f179a2262cb5d7e
4
+ data.tar.gz: 529ed1d29fdf3c3c6ba381e7ab71cbf006bc44c8d608858e8ec84d67c2efb267
5
5
  SHA512:
6
- metadata.gz: b84bb256a178326bc76143952098db02723fcfa792ed6e86f9b6b63a0c602d87eb270d81d93e34742c2026abd7fd2118964b3a039eb8e3968863a8d1e5fe1697
7
- data.tar.gz: 76fc65f2ce473f91a8cb98bc32c62e98ecc154aef519ab8d9e908f7def8330306b76ee2c54ed99a57bfba4b5997065b6d953747756b9a0b83e9e557c96de1d23
6
+ metadata.gz: 1b840cfe8d90929c0fcc32fdc1370310924a46464006b39afa5dceff69b8c24254d701002e77f33a845baaa7fe5373243486b5d1422a3beea4fd45a50e65ec8b
7
+ data.tar.gz: e3176f406a5de5a027cae5a2edcbd897395a0191dad1a6cb402bf48fb005f9dce3783d8e6778f91e7d05c03b3f12f473ee23438b9235ed5eedd5e4d588a58526
@@ -6,7 +6,7 @@ jobs:
6
6
  QuietQuality:
7
7
  runs-on: ubuntu-latest
8
8
  steps:
9
- - uses: actions/checkout@v3
9
+ - uses: actions/checkout@v4
10
10
  with:
11
11
  fetch-depth: 0
12
12
 
@@ -6,7 +6,7 @@ jobs:
6
6
  StandardRB:
7
7
  runs-on: ubuntu-latest
8
8
  steps:
9
- - uses: actions/checkout@v3
9
+ - uses: actions/checkout@v4
10
10
 
11
11
  - name: Set up ruby
12
12
  uses: ruby/setup-ruby@v1
@@ -11,7 +11,7 @@ jobs:
11
11
  ruby-version: ['2.7', '3.0', '3.1', '3.2', 'head']
12
12
 
13
13
  steps:
14
- - uses: actions/checkout@v3
14
+ - uses: actions/checkout@v4
15
15
 
16
16
  - name: Set up ruby
17
17
  uses: ruby/setup-ruby@v1
data/.quiet_quality.yml CHANGED
@@ -6,3 +6,4 @@ changed_files: false
6
6
  filter_messages: false
7
7
  logging: light
8
8
  colorize: true
9
+ message_format: "%lcyan10tool| [%myellow40rule] %bred60loc %e-90body"
data/.standard.yml ADDED
@@ -0,0 +1,3 @@
1
+ ---
2
+ format: progress
3
+ ruby_version: 2.7
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## Release 1.5.0
4
+
5
+ * Update to comply with current standardrb rules, and use checkout@v4
6
+ * Add a `-X/--exec` argument that allows you to let qq craft the command, but
7
+ then actually exec the command instead of running it and handling its output.
8
+ Especially useful for things like `rspec`, where the output it gives you about
9
+ failing tests is very useful, and qq is mostly only helpful for determining
10
+ what specs to run.
11
+ * Add a `--message-format` argument and `message_format` config file option,
12
+ which allow for a fairly complex configuration of the output format for
13
+ messages, so they can be displayed in various colorized/tabular formats.
14
+
3
15
  ## Release 1.4.0
4
16
 
5
17
  * Support specifying `excludes` per-tool, so that certain files won't be passed
data/README.md CHANGED
@@ -151,6 +151,9 @@ The configuration file supports the following _global_ options (top-level keys):
151
151
  * `colorize`: by default, `bin/qq` will include color codes in its output, to
152
152
  make failing tools easier to spot, and messages easier to read. But you can
153
153
  supply `colorize: false` to tell it not to do that if you don't want them.
154
+ * `message_format`: you can specify a format string with which to render the
155
+ messages, which interpolates values with various formatting flags. Details
156
+ given in the "Message Formatting" section below.
154
157
 
155
158
  And then each tool can have an entry, within which `changed_files` and
156
159
  `filter_messages` can be specified - the tool-specific settings override the
@@ -181,6 +184,40 @@ generated file like `db/schema.rb`, and that file doesn't meet your rubocop (or
181
184
  standardrb) rules, you'll get _told_ unless you exclude it at the quiet-quality
182
185
  level as well.
183
186
 
187
+ ### Message Formatting
188
+
189
+ You can supply a message-format string on the cli or in your config file, which
190
+ will override the default formatting for message output on the CLI. These format
191
+ strings are intended to be a single line containing "substitution tokens", which
192
+ each look like `%[lr]?[bem]?color?(Size)(Source)`.
193
+
194
+ * The first (optional) flag can be an "l", and "r", or be left off (which is the
195
+ same as "l"). This flag indicates the 'justification' - left or right.
196
+ * The second (optional) flag can be a "b", an "e", or an "m", defaulting to "e";
197
+ these stand for "beginning", "ending", and "middle", and represent what part
198
+ of the string should be truncated if it needs to be shortened.
199
+ * The third (optional) part is a color name, and can be any of "yellow", "red",
200
+ "green", "blue", "cyan", or "none" (leaving it off is the same as specifing
201
+ "none"). This is the color to use for the token in the output - note that any
202
+ color supplied here is used regardless of the '--colorize' flag.
203
+ * The fourth part of the token is required, and is the _size_ of the token. If a
204
+ positive integer is supplied, then the token will take up that much space, and
205
+ will be padded on the appropriate side if necessary; if a negative integer is
206
+ supplied, then the token will not be padded out, but will still get truncated
207
+ if it is too long. The value '0' is special, and indicates that the token
208
+ should be neither padded nor truncated.
209
+ * The last part of the token is a string indicating the _source_ data to
210
+ represent, and must be one of these values: "tool", "loc", "level", "path",
211
+ "lines", "rule", "body". Each of these represents one piece of data out of the
212
+ message object that can be rendered into the message line.
213
+
214
+ Some example message formats:
215
+
216
+ ```text
217
+ %lcyan8tool | %lmyellow30rule | %0loc
218
+ %le6tool [%mblue20rule] %b45loc %cyan-100body
219
+ ```
220
+
184
221
  ### CLI Options
185
222
 
186
223
  To specify which _tools_ to run (and if any are specified, the `default_tools`
@@ -67,6 +67,7 @@ module QuietQuality
67
67
  setup_filter_messages_options(parser)
68
68
  setup_colorization_options(parser)
69
69
  setup_logging_options(parser)
70
+ setup_message_formatting_options(parser)
70
71
  setup_verbosity_options(parser)
71
72
  end
72
73
  end
@@ -100,6 +101,11 @@ module QuietQuality
100
101
  validate_value_from("executor", name, Executors::AVAILABLE)
101
102
  set_global_option(:executor, name.to_sym)
102
103
  end
104
+
105
+ parser.on("-X", "--exec TOOL", "Exec one tool instead of managing several") do |tool_name|
106
+ validate_value_from("tool", tool_name, Tools::AVAILABLE)
107
+ set_global_option(:exec_tool, tool_name.to_sym)
108
+ end
103
109
  end
104
110
 
105
111
  def setup_annotation_options(parser)
@@ -163,6 +169,12 @@ module QuietQuality
163
169
  end
164
170
  end
165
171
 
172
+ def setup_message_formatting_options(parser)
173
+ parser.on("-F", "--message-format FMT", "A format string with which to print messages") do |fmt|
174
+ set_global_option(:message_format, fmt)
175
+ end
176
+ end
177
+
166
178
  def setup_verbosity_options(parser)
167
179
  parser.on("-v", "--verbose", "Log more verbosely - multiple times is more verbose") do
168
180
  QuietQuality.logger.increase_level!
@@ -18,7 +18,7 @@ module QuietQuality
18
18
  log_no_tools_text
19
19
  else
20
20
  log_options
21
- executed
21
+ execute!
22
22
  log_results
23
23
  annotate_messages
24
24
  end
@@ -114,6 +114,26 @@ module QuietQuality
114
114
  @_executed = executor
115
115
  end
116
116
 
117
+ def exec_tool_options
118
+ @_exec_tool_options ||= options.tools
119
+ .detect { |topts| topts.tool_name == options.exec_tool.to_sym }
120
+ end
121
+
122
+ def execcer
123
+ @_execcer ||= QuietQuality::Executors::Execcer.new(
124
+ tool_options: exec_tool_options,
125
+ changed_files: changed_files
126
+ )
127
+ end
128
+
129
+ def execute!
130
+ if options.exec_tool
131
+ execcer.exec!
132
+ else
133
+ executed
134
+ end
135
+ end
136
+
117
137
  def annotate_messages
118
138
  return unless options.annotator
119
139
  info("Annotating with #{options.annotator}")
@@ -0,0 +1,190 @@
1
+ module QuietQuality
2
+ module Cli
3
+ class MessageFormatter
4
+ TOKEN_MATCHING_REGEX = %r{%[a-z]*-?\d+(?:tool|loc|level|path|lines|rule|body)}
5
+
6
+ def initialize(message_format:)
7
+ @message_format = message_format
8
+ end
9
+
10
+ def format(message)
11
+ formatted_tokens = parsed_tokens.map { |pt| FormattedToken.new(parsed_token: pt, message: message) }
12
+ formatted_tokens.reduce(message_format) do |interpolating, ftok|
13
+ interpolating.gsub(ftok.token, ftok.formatted_token)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :message_format
20
+
21
+ def tokens
22
+ @_tokens ||= message_format.scan(TOKEN_MATCHING_REGEX)
23
+ end
24
+
25
+ def parsed_tokens
26
+ @_parsed_tokens ||= tokens.map { |tok| ParsedToken.new(tok) }
27
+ end
28
+
29
+ class ParsedToken
30
+ TOKEN_PARSING_REGEX = %r{
31
+ % # start the interplation token
32
+ (?<just>[lr])? # specify the justification
33
+ (?<trunc>[bem])? # where to truncate from
34
+ (?<color>yellow|red|green|blue|cyan|none)? # what color
35
+ (?<size>-?\d+) # string size (may be negative)
36
+ (?<source>tool|loc|level|path|lines|rule|body) # data source name
37
+ }x
38
+
39
+ COLORS = {
40
+ "yellow" => :yellow,
41
+ "red" => :red,
42
+ "green" => :green,
43
+ "blue" => :light_blue,
44
+ "cyan" => :light_cyan,
45
+ "none" => nil
46
+ }.freeze
47
+
48
+ JUSTIFICATIONS = {"l" => :left, "r" => :right}.freeze
49
+ TRUNCATIONS = {"b" => :beginning, "m" => :middle, "e" => :ending}.freeze
50
+
51
+ def initialize(token)
52
+ @token = token
53
+ end
54
+
55
+ attr_reader :token
56
+
57
+ def justification
58
+ JUSTIFICATIONS.fetch(token_pieces[:just]&.downcase, :left)
59
+ end
60
+
61
+ def truncation
62
+ TRUNCATIONS.fetch(token_pieces[:trunc]&.downcase, :ending)
63
+ end
64
+
65
+ def color
66
+ COLORS.fetch(token_pieces[:color]&.downcase, nil)
67
+ end
68
+
69
+ def size
70
+ raw_size.abs
71
+ end
72
+
73
+ def source
74
+ token_pieces[:source]
75
+ end
76
+
77
+ def allow_pad?
78
+ raw_size.positive?
79
+ end
80
+
81
+ def allow_truncate?
82
+ !raw_size.zero?
83
+ end
84
+
85
+ private
86
+
87
+ def token_pieces
88
+ @_token_pieces ||= token.match(TOKEN_PARSING_REGEX)
89
+ end
90
+
91
+ def raw_size
92
+ @_raw_size ||= token_pieces[:size].to_i
93
+ end
94
+ end
95
+ private_constant :ParsedToken
96
+
97
+ class FormattedToken
98
+ def initialize(parsed_token:, message:)
99
+ @parsed_token = parsed_token
100
+ @message = message
101
+ end
102
+
103
+ def formatted_token
104
+ colorized(padded(truncated(base_string)))
105
+ end
106
+
107
+ def token
108
+ parsed_token.token
109
+ end
110
+
111
+ private
112
+
113
+ attr_reader :parsed_token, :message
114
+
115
+ def line_range
116
+ if message.start_line == message.stop_line
117
+ message.start_line.to_s
118
+ else
119
+ "#{message.start_line}-#{message.stop_line}"
120
+ end
121
+ end
122
+
123
+ def base_string
124
+ case parsed_token.source
125
+ when "tool" then message.tool_name
126
+ when "loc" then location_string
127
+ when "level" then message.level
128
+ when "path" then message.path
129
+ when "lines" then line_range
130
+ when "rule" then message.rule
131
+ when "body" then flattened_body
132
+ end
133
+ end
134
+
135
+ def location_string
136
+ "#{message.path}:#{line_range}"
137
+ end
138
+
139
+ def flattened_body
140
+ message.body.gsub(/ *\n */, "\\n")
141
+ end
142
+
143
+ def truncated(s)
144
+ return s unless parsed_token.allow_truncate?
145
+ return s if s.length <= parsed_token.size
146
+ size = parsed_token.size
147
+
148
+ case parsed_token.truncation
149
+ when :beginning then truncate_beginning(s, size)
150
+ when :middle then truncate_middle(s, size)
151
+ when :ending then truncate_ending(s, size)
152
+ end
153
+ end
154
+
155
+ def truncate_beginning(s, size)
156
+ "…" + s.slice(1 - size, size - 1)
157
+ end
158
+
159
+ def truncate_middle(s, size)
160
+ front_len = (size / 2.0).floor
161
+ back_len = (size / 2.0).ceil - 1
162
+ s.slice(0, front_len) + "…" + s.slice(-back_len, back_len)
163
+ end
164
+
165
+ def truncate_ending(s, size)
166
+ s.slice(0, size - 1) + "…"
167
+ end
168
+
169
+ def padded(s)
170
+ return s unless parsed_token.allow_pad?
171
+ return s if s.length >= parsed_token.size
172
+
173
+ case parsed_token.justification
174
+ when :left then s.ljust(parsed_token.size)
175
+ when :right then s.rjust(parsed_token.size)
176
+ end
177
+ end
178
+
179
+ def colorized(s)
180
+ if parsed_token.color.nil?
181
+ s
182
+ else
183
+ Colorize.colorize(s, color: parsed_token.color)
184
+ end
185
+ end
186
+ end
187
+ private_constant :FormattedToken
188
+ end
189
+ end
190
+ end
@@ -78,12 +78,28 @@ module QuietQuality
78
78
  s.gsub(/ *\n */, "\\n").slice(0, length)
79
79
  end
80
80
 
81
- def log_message(msg)
81
+ def locally_formatted_message(msg)
82
82
  tool = colorize(:yellow, msg.tool_name)
83
83
  line_range = line_range_for(msg)
84
84
  rule_string = msg.rule ? " [#{colorize(:yellow, msg.rule)}]" : ""
85
85
  truncated_body = reduce_text(msg.body, 120)
86
- stream.puts "#{tool} #{msg.path}:#{line_range}#{rule_string} #{truncated_body}"
86
+ "#{tool} #{msg.path}:#{line_range}#{rule_string} #{truncated_body}"
87
+ end
88
+
89
+ def loggable_message(msg)
90
+ if options.message_format
91
+ message_formatter.format(msg)
92
+ else
93
+ stream.puts locally_formatted_message(msg)
94
+ end
95
+ end
96
+
97
+ def log_message(msg)
98
+ stream.puts loggable_message(msg)
99
+ end
100
+
101
+ def message_formatter
102
+ @_message_formatter ||= MessageFormatter.new(message_format: options.message_format)
87
103
  end
88
104
  end
89
105
  end
@@ -1,5 +1,5 @@
1
- require_relative "./annotators"
2
- require_relative "./tools"
1
+ require_relative "annotators"
2
+ require_relative "tools"
3
3
 
4
4
  module QuietQuality
5
5
  module Cli
@@ -22,7 +22,7 @@ module QuietQuality
22
22
  Options.new.tap { |opts| opts.tools = tools }
23
23
  end
24
24
 
25
- def tool_names
25
+ def specified_tool_names
26
26
  if cli.tools.any?
27
27
  cli.tools
28
28
  elsif config_file&.tools&.any?
@@ -32,6 +32,14 @@ module QuietQuality
32
32
  end
33
33
  end
34
34
 
35
+ def exec_tool_name
36
+ cli.global_option(:exec_tool)
37
+ end
38
+
39
+ def tool_names
40
+ (specified_tool_names + [exec_tool_name]).compact.uniq
41
+ end
42
+
35
43
  def config_finder
36
44
  @_config_finder ||= Finder.new(from: ".")
37
45
  end
@@ -84,6 +92,7 @@ module QuietQuality
84
92
  def update_globals
85
93
  update_annotator
86
94
  update_executor
95
+ update_exec_tool
87
96
  update_comparison_branch
88
97
  update_logging
89
98
  end
@@ -100,6 +109,10 @@ module QuietQuality
100
109
  options.executor = Executors::AVAILABLE.fetch(executor_name)
101
110
  end
102
111
 
112
+ def update_exec_tool
113
+ set_unless_nil(options, :exec_tool, apply.global_option(:exec_tool))
114
+ end
115
+
103
116
  def update_comparison_branch
104
117
  set_unless_nil(options, :comparison_branch, apply.global_option(:comparison_branch))
105
118
  end
@@ -107,6 +120,7 @@ module QuietQuality
107
120
  def update_logging
108
121
  set_unless_nil(options, :logging, apply.global_option(:logging))
109
122
  set_unless_nil(options, :colorize, apply.global_option(:colorize))
123
+ set_unless_nil(options, :message_format, apply.global_option(:message_format))
110
124
  end
111
125
 
112
126
  # ---- update the tool options (apply global forms first) -------
@@ -7,12 +7,14 @@ module QuietQuality
7
7
  @annotator = nil
8
8
  @executor = Executors::ConcurrentExecutor
9
9
  @tools = nil
10
+ @exec_tool = nil
10
11
  @comparison_branch = nil
11
12
  @colorize = true
12
13
  @logging = :normal
14
+ @message_format = nil
13
15
  end
14
16
 
15
- attr_accessor :tools, :comparison_branch, :annotator, :executor
17
+ attr_accessor :tools, :comparison_branch, :annotator, :executor, :exec_tool, :message_format
16
18
  attr_reader :logging
17
19
  attr_writer :colorize
18
20
 
@@ -37,9 +39,11 @@ module QuietQuality
37
39
  {
38
40
  annotator: annotator,
39
41
  executor: executor.name,
42
+ exec_tool: exec_tool,
40
43
  comparison_branch: comparison_branch,
41
44
  colorize: colorize?,
42
45
  logging: logging,
46
+ message_format: message_format,
43
47
  tools: tool_hashes_by_name
44
48
  }
45
49
  end
@@ -8,9 +8,11 @@ module QuietQuality
8
8
  :config_path,
9
9
  :annotator,
10
10
  :executor,
11
+ :exec_tool,
11
12
  :comparison_branch,
12
13
  :colorize,
13
14
  :logging,
15
+ :message_format,
14
16
  :limit_targets,
15
17
  :filter_messages,
16
18
  :file_filter
@@ -48,6 +48,7 @@ module QuietQuality
48
48
  read_global_option(opts, :unfiltered, :filter_messages, as: :reversed_boolean)
49
49
  read_global_option(opts, :colorize, :colorize, as: :boolean)
50
50
  read_global_option(opts, :logging, :logging, as: :symbol, validate_from: Options::LOGGING_LEVELS)
51
+ read_global_option(opts, :message_format, :message_format, as: :string)
51
52
  end
52
53
 
53
54
  def store_tool_options(opts)
@@ -0,0 +1,46 @@
1
+ module QuietQuality
2
+ module Executors
3
+ class Execcer
4
+ include Logging
5
+
6
+ def initialize(tool_options:, changed_files: nil)
7
+ @tool_options = tool_options
8
+ @changed_files = changed_files
9
+ end
10
+
11
+ def exec!
12
+ if runner.exec_command
13
+ Kernel.exec(*runner.exec_command)
14
+ else
15
+ info <<~LOG_MESSAGE
16
+ This runner does not believe it needs to execute at all.
17
+ This typically means that it was told to target changed-files, but no relevant
18
+ files were changed.
19
+ LOG_MESSAGE
20
+ Kernel.exit(0)
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :tool_options, :changed_files
27
+
28
+ def limit_targets?
29
+ tool_options.limit_targets?
30
+ end
31
+
32
+ def runner
33
+ @_runner ||= tool_options.runner_class.new(
34
+ changed_files: limit_targets? ? changed_files : nil,
35
+ file_filter: tool_options.file_filter
36
+ ).tap { |r| log_runner(r) }
37
+ end
38
+
39
+ def log_runner(r)
40
+ command_string = r.exec_command ? "`#{r.exec_command.join(" ")}`" : "(skipped)"
41
+ info("Runner #{r.tool_name} exec_command: #{command_string}")
42
+ debug("Full exec_command for #{r.tool_name}", data: r.exec_command)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,4 +1,4 @@
1
- require_relative "./base_executor"
1
+ require_relative "base_executor"
2
2
 
3
3
  module QuietQuality
4
4
  module Executors
@@ -23,6 +23,10 @@ module QuietQuality
23
23
  fail(NoMethodError, "BaseRunner subclass must implement `command`")
24
24
  end
25
25
 
26
+ def exec_command
27
+ fail(NoMethodError, "BaseRunner subclass must implement `exec_command`")
28
+ end
29
+
26
30
  def success_status?(stat)
27
31
  stat.success?
28
32
  end
@@ -10,6 +10,10 @@ module QuietQuality
10
10
  ["brakeman", "-f", "json"]
11
11
  end
12
12
 
13
+ def exec_command
14
+ ["brakeman"]
15
+ end
16
+
13
17
  # These are specified in constants at the top of brakeman.rb:
14
18
  # https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman.rb#L6-L25
15
19
  def failure_status?(stat)
@@ -1,4 +1,4 @@
1
- require_relative "./rubocop"
1
+ require_relative "rubocop"
2
2
 
3
3
  module QuietQuality
4
4
  module Tools
@@ -14,6 +14,10 @@ module QuietQuality
14
14
  ["haml-lint", "--reporter", "json"]
15
15
  end
16
16
 
17
+ def base_exec_command
18
+ ["haml-lint"]
19
+ end
20
+
17
21
  def relevant_path?(path)
18
22
  path.end_with?(".haml")
19
23
  end
@@ -10,15 +10,21 @@ module QuietQuality
10
10
  "[]"
11
11
  end
12
12
 
13
- def command
13
+ def command(json: true)
14
14
  return nil if skip_execution?
15
+ base_command = ["mdl"]
16
+ base_command << "--json" if json
15
17
  if target_files.any?
16
- ["mdl", "--json"] + target_files.sort
18
+ base_command + target_files.sort
17
19
  else
18
- ["mdl", "--json", "."]
20
+ base_command + ["."]
19
21
  end
20
22
  end
21
23
 
24
+ def exec_command
25
+ command(json: false)
26
+ end
27
+
22
28
  def relevant_path?(path)
23
29
  path.end_with?(".md")
24
30
  end
@@ -1,4 +1,4 @@
1
- require_relative "./base_runner"
1
+ require_relative "base_runner"
2
2
 
3
3
  module QuietQuality
4
4
  module Tools
@@ -16,6 +16,11 @@ module QuietQuality
16
16
  base_command + target_files.sort
17
17
  end
18
18
 
19
+ def exec_command
20
+ return nil if skip_execution?
21
+ base_exec_command + target_files.sort
22
+ end
23
+
19
24
  def relevant_path?(path)
20
25
  fail(NoMethodError, "RelevantRunner subclass must implement `relevant_path?`")
21
26
  end
@@ -24,6 +29,10 @@ module QuietQuality
24
29
  fail(NoMethodError, "RelevantRunner subclass must implement either `command` or `base_command`")
25
30
  end
26
31
 
32
+ def base_exec_command
33
+ fail(NoMethodError, "RelevantRunner subclass must implement either `exec_command` or `base_exec_command`")
34
+ end
35
+
27
36
  def no_files_output
28
37
  fail(NoMethodError, "RelevantRunner subclass must implement `no_files_output`")
29
38
  end
@@ -14,6 +14,10 @@ module QuietQuality
14
14
  ["rspec", "-f", "json"]
15
15
  end
16
16
 
17
+ def base_exec_command
18
+ ["rspec"]
19
+ end
20
+
17
21
  def relevant_path?(path)
18
22
  path.end_with?("_spec.rb")
19
23
  end
@@ -14,6 +14,10 @@ module QuietQuality
14
14
  ["rubocop", "-f", "json"]
15
15
  end
16
16
 
17
+ def base_exec_command
18
+ ["rubocop"]
19
+ end
20
+
17
21
  def relevant_path?(path)
18
22
  path.end_with?(".rb")
19
23
  end
@@ -14,6 +14,10 @@ module QuietQuality
14
14
  ["standardrb", "-f", "json"]
15
15
  end
16
16
 
17
+ def base_exec_command
18
+ ["standardrb"]
19
+ end
20
+
17
21
  def relevant_path?(path)
18
22
  path.end_with?(".rb")
19
23
  end
@@ -1,4 +1,4 @@
1
- require_relative "./rubocop"
1
+ require_relative "rubocop"
2
2
 
3
3
  module QuietQuality
4
4
  module Tools
@@ -8,8 +8,8 @@ module QuietQuality
8
8
  end
9
9
  end
10
10
 
11
- require_relative "./tools/base_runner"
12
- require_relative "./tools/relevant_runner"
11
+ require_relative "tools/base_runner"
12
+ require_relative "tools/relevant_runner"
13
13
 
14
14
  glob = File.expand_path("../tools/*.rb", __FILE__)
15
15
  Dir.glob(glob).sort.each { |f| require f }
@@ -1,3 +1,3 @@
1
1
  module QuietQuality
2
- VERSION = "1.4.0"
2
+ VERSION = "1.5.0"
3
3
  end
data/lib/quiet_quality.rb CHANGED
@@ -16,7 +16,7 @@ module QuietQuality
16
16
  end
17
17
  end
18
18
 
19
- require_relative "./quiet_quality/logger"
20
- require_relative "./quiet_quality/logging"
19
+ require_relative "quiet_quality/logger"
20
+ require_relative "quiet_quality/logging"
21
21
  glob = File.expand_path("../quiet_quality/*.rb", __FILE__)
22
22
  Dir.glob(glob).sort.each { |f| require f }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quiet_quality
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Mueller
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-12 00:00:00.000000000 Z
11
+ date: 2023-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: git
@@ -184,6 +184,7 @@ files:
184
184
  - ".quiet_quality.yml"
185
185
  - ".rspec"
186
186
  - ".rubocop.yml"
187
+ - ".standard.yml"
187
188
  - CHANGELOG.md
188
189
  - Gemfile
189
190
  - LICENSE
@@ -199,6 +200,7 @@ files:
199
200
  - lib/quiet_quality/cli.rb
200
201
  - lib/quiet_quality/cli/arg_parser.rb
201
202
  - lib/quiet_quality/cli/entrypoint.rb
203
+ - lib/quiet_quality/cli/message_formatter.rb
202
204
  - lib/quiet_quality/cli/presenter.rb
203
205
  - lib/quiet_quality/colorize.rb
204
206
  - lib/quiet_quality/config.rb
@@ -212,6 +214,7 @@ files:
212
214
  - lib/quiet_quality/executors.rb
213
215
  - lib/quiet_quality/executors/base_executor.rb
214
216
  - lib/quiet_quality/executors/concurrent_executor.rb
217
+ - lib/quiet_quality/executors/execcer.rb
215
218
  - lib/quiet_quality/executors/pipeline.rb
216
219
  - lib/quiet_quality/executors/serial_executor.rb
217
220
  - lib/quiet_quality/logger.rb