sloplint 0.4.0 → 0.6.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 +4 -4
- data/CHANGELOG.md +295 -1
- data/README.md +37 -9
- data/docs/SPEC.md +44 -8
- data/exe/sloplint +13 -0
- data/lib/sloplint/cli.rb +35 -12
- data/lib/sloplint/rules.rb +1885 -15
- data/lib/sloplint/version.rb +1 -1
- metadata +4 -4
- data/bin/sloplint +0 -5
data/lib/sloplint/cli.rb
CHANGED
|
@@ -10,7 +10,8 @@ require_relative "output"
|
|
|
10
10
|
module Sloplint
|
|
11
11
|
# Command-line shell: optparse, subcommands, exit codes. See docs/SPEC.md.
|
|
12
12
|
#
|
|
13
|
-
# Exit codes: 0 ran/no notes, 1 ran/notes found, 2 bad arguments.
|
|
13
|
+
# Exit codes: 0 ran/no notes, 1 ran/notes found, 2 bad arguments. Empty
|
|
14
|
+
# input is a 2 as well: an unread draft must not report as a clean one.
|
|
14
15
|
module CLI
|
|
15
16
|
module_function
|
|
16
17
|
|
|
@@ -33,9 +34,9 @@ module Sloplint
|
|
|
33
34
|
when "version" then out.puts(VERSION); 0
|
|
34
35
|
when "help" then out.puts(parser.help); 0
|
|
35
36
|
else
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
# Anything else is a path or "-": `sloplint FILE`, `sloplint -`.
|
|
38
|
+
# A mistyped command lands here too, and fails as a missing file.
|
|
39
|
+
cmd_check(argv.unshift(command), opts, out:, err:, stdin:)
|
|
39
40
|
end
|
|
40
41
|
rescue OptionParser::ParseError => e
|
|
41
42
|
err.puts("sloplint: #{e.message}")
|
|
@@ -68,20 +69,38 @@ module Sloplint
|
|
|
68
69
|
paths = argv.empty? ? ["-"] : argv
|
|
69
70
|
by_path = paths.reject { |x| x == "-" }.size > 1
|
|
70
71
|
|
|
71
|
-
|
|
72
|
+
sources = []
|
|
72
73
|
paths.each do |path|
|
|
74
|
+
# Read as UTF-8 whatever the locale says. A sandbox with no LANG set
|
|
75
|
+
# leaves Ruby's default external encoding at US-ASCII, and then the
|
|
76
|
+
# first em dash raises "invalid byte sequence in US-ASCII" -- on prose
|
|
77
|
+
# that is perfectly valid UTF-8. Prose is the only input sloplint
|
|
78
|
+
# takes, so UTF-8 is the assumption, not the locale's guess.
|
|
73
79
|
text =
|
|
74
80
|
if path == "-"
|
|
75
|
-
stdin.read
|
|
81
|
+
stdin.read.force_encoding(Encoding::UTF_8)
|
|
76
82
|
else
|
|
77
83
|
unless File.file?(path)
|
|
78
84
|
err.puts("sloplint: no such file: #{path}")
|
|
79
85
|
return 2
|
|
80
86
|
end
|
|
81
|
-
File.read(path)
|
|
87
|
+
File.read(path, encoding: Encoding::UTF_8)
|
|
82
88
|
end
|
|
83
|
-
|
|
84
|
-
|
|
89
|
+
sources << [path == "-" ? "-" : path, text]
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Tested on the raw text, before --markdown blanks code and URLs: a file
|
|
93
|
+
# that holds only a fenced code block did arrive, and scanning it clean
|
|
94
|
+
# is right. Nothing arriving at all is the trap -- the same one a
|
|
95
|
+
# mistyped rule id sets, and it exits 2 for the same reason.
|
|
96
|
+
if sources.all? { |_, text| text.strip.empty? }
|
|
97
|
+
names = sources.map { |label, _| label == "-" ? "stdin" : label }
|
|
98
|
+
err.puts("sloplint: empty input: nothing to check in #{names.join(", ")}")
|
|
99
|
+
return 2
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
all_notes = sources.flat_map do |label, text|
|
|
103
|
+
Engine.scan(text, rules:, markdown:, path: label)
|
|
85
104
|
end
|
|
86
105
|
|
|
87
106
|
case opts[:format]
|
|
@@ -93,7 +112,10 @@ module Sloplint
|
|
|
93
112
|
end
|
|
94
113
|
|
|
95
114
|
all_notes.empty? ? 0 : 1
|
|
96
|
-
|
|
115
|
+
# Invalid UTF-8 reaches this two ways: String#strip in the empty check
|
|
116
|
+
# raises Encoding::CompatibilityError, the engine's regexes raise
|
|
117
|
+
# ArgumentError. Both are the same thing to the reader.
|
|
118
|
+
rescue ArgumentError, Encoding::CompatibilityError => e
|
|
97
119
|
err.puts("sloplint: invalid input: #{e.message}")
|
|
98
120
|
2
|
|
99
121
|
end
|
|
@@ -187,13 +209,14 @@ module Sloplint
|
|
|
187
209
|
|
|
188
210
|
# Recommended for agents:
|
|
189
211
|
cat FILE | sloplint check --markdown -o json -
|
|
190
|
-
# exit 0 = clean, 1 = notes found, >1 = error
|
|
212
|
+
# exit 0 = clean, 1 = notes found, >1 = error (empty input is an error)
|
|
191
213
|
# each note: {path,line,column,severity,rule,category,message,excerpt,context,rationale,suggestion}
|
|
192
214
|
|
|
193
|
-
usage: sloplint [-o full|json]
|
|
215
|
+
usage: sloplint [-o full|json] [command] [args]
|
|
194
216
|
|
|
195
217
|
commands:
|
|
196
218
|
check scan paths (or stdin) for AI-slop tells and report notes [default]
|
|
219
|
+
a first argument that is not a command name is taken as a path
|
|
197
220
|
rules list the rule catalog (add --json for the machine-readable form)
|
|
198
221
|
explain ID print one rule's message, rationale, and a bad/ok example
|
|
199
222
|
version print the sloplint version
|