quiet_quality 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
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