simple_english 0.6.0-x86_64-linux
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 +7 -0
- data/LICENSE +21 -0
- data/README.md +212 -0
- data/THIRD_PARTY_NOTICES.md +72 -0
- data/bin/se +6 -0
- data/docs/RULES.md +496 -0
- data/lib/simple_english/cli.rb +183 -0
- data/lib/simple_english/client/daemon.rb +233 -0
- data/lib/simple_english/client/language_tool.rb +95 -0
- data/lib/simple_english/daemon/engine.rb +40 -0
- data/lib/simple_english/daemon/http.rb +82 -0
- data/lib/simple_english/daemon/server.rb +285 -0
- data/lib/simple_english/lint/annotated_text.rb +117 -0
- data/lib/simple_english/lint/counts.rb +40 -0
- data/lib/simple_english/lint/extractor.rb +60 -0
- data/lib/simple_english/lint/finding.rb +24 -0
- data/lib/simple_english/lint/lint_plan.rb +22 -0
- data/lib/simple_english/lint/markdown.rb +121 -0
- data/lib/simple_english/lint/paragraph.rb +10 -0
- data/lib/simple_english/lint/plain_text.rb +30 -0
- data/lib/simple_english/lint/result.rb +18 -0
- data/lib/simple_english/lint/segment.rb +11 -0
- data/lib/simple_english/lint/span.rb +8 -0
- data/lib/simple_english/lint/suppressions.rb +37 -0
- data/lib/simple_english/model_context_protocol.rb +134 -0
- data/lib/simple_english/setup/config.rb +63 -0
- data/lib/simple_english/setup/fingerprint.rb +38 -0
- data/lib/simple_english/setup/install.rb +40 -0
- data/lib/simple_english/setup/languagetool.rb +23 -0
- data/lib/simple_english/version.rb +5 -0
- data/lib/simple_english.rb +60 -0
- data/libexec/simple_english/languagetool-server +4 -0
- data/libexec/simple_english/languagetool-server.sbom.json +9044 -0
- data/licenses/LGPL-2.1.txt +501 -0
- data/licenses/OpenJDK-LICENSE.txt +347 -0
- data/licenses/languagetool-resource-en/12dicts-readme.html +738 -0
- data/licenses/languagetool-resource-en/agid-readme.txt +340 -0
- data/licenses/languagetool-resource-en/pos-readme.txt +115 -0
- data/rules/simple-english.xml +621 -0
- metadata +185 -0
data/docs/RULES.md
ADDED
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
# Rules
|
|
2
|
+
|
|
3
|
+
Generated by `bin/render-rules`. Do not edit by hand. The source
|
|
4
|
+
of truth is `rules/simple-english.xml` and
|
|
5
|
+
`lib/simple_english/lint/counts.rb`.
|
|
6
|
+
|
|
7
|
+
## Pattern rules
|
|
8
|
+
|
|
9
|
+
### SE_NO_CONTRACTIONS: No contractions
|
|
10
|
+
|
|
11
|
+
Write the words in full. No contractions.
|
|
12
|
+
|
|
13
|
+
- Wrong: You don't need this file.
|
|
14
|
+
- Right: You do not need this file.
|
|
15
|
+
|
|
16
|
+
### SE_NO_SEMICOLON: No semicolons
|
|
17
|
+
|
|
18
|
+
Write two sentences, or name the relation.
|
|
19
|
+
|
|
20
|
+
- Wrong: Start the tool; then read the log.
|
|
21
|
+
- Right: Start the tool. Then read the log.
|
|
22
|
+
|
|
23
|
+
### SE_NO_EMDASH: No em-dashes
|
|
24
|
+
|
|
25
|
+
Write two sentences, or use a comma.
|
|
26
|
+
|
|
27
|
+
- Wrong: The tool is fast—it also works.
|
|
28
|
+
- Right: The tool is fast. It also works.
|
|
29
|
+
|
|
30
|
+
### SE_MODAL_RESTRICTED: Only can, will, must
|
|
31
|
+
|
|
32
|
+
Use can, will, or must. State the requirement exactly.
|
|
33
|
+
|
|
34
|
+
- Wrong: You should restart the service.
|
|
35
|
+
- Right: You must restart the service.
|
|
36
|
+
|
|
37
|
+
### SE_ACTIVE_VOICE: Active voice
|
|
38
|
+
|
|
39
|
+
Use the active voice. Say who does the action.
|
|
40
|
+
|
|
41
|
+
- Wrong: The log was written by the worker.
|
|
42
|
+
- Right: The worker wrote the log.
|
|
43
|
+
|
|
44
|
+
### SE_PRESENT_PERFECT: Simple tenses only
|
|
45
|
+
|
|
46
|
+
Use the simple past. Say when it happened.
|
|
47
|
+
|
|
48
|
+
- Wrong: The job has completed.
|
|
49
|
+
- Right: The job completed.
|
|
50
|
+
|
|
51
|
+
### SE_ING_AFTER_COMMA: No -ing after a comma
|
|
52
|
+
|
|
53
|
+
Start a new sentence instead of the -ing phrase.
|
|
54
|
+
|
|
55
|
+
- Wrong: The tool runs, making it easy.
|
|
56
|
+
- Right: The tool runs. It is easy.
|
|
57
|
+
|
|
58
|
+
### SE_KEEP_THAT: make sure that
|
|
59
|
+
|
|
60
|
+
Write "make sure that".
|
|
61
|
+
|
|
62
|
+
- Wrong: Make sure the file exists.
|
|
63
|
+
- Right: Make sure that the file exists.
|
|
64
|
+
|
|
65
|
+
### SE_CONDITION_FIRST: Condition before command
|
|
66
|
+
|
|
67
|
+
Put the condition first: "If the build fails, read the log."
|
|
68
|
+
|
|
69
|
+
- Wrong: Read the log if the build fails.
|
|
70
|
+
- Right: If the build fails, read the log.
|
|
71
|
+
|
|
72
|
+
### SE_SLOP_LEVERAGE: use, not leverage
|
|
73
|
+
|
|
74
|
+
Write use.
|
|
75
|
+
|
|
76
|
+
- Wrong: Utilize the registry file.
|
|
77
|
+
- Right: Use the registry file.
|
|
78
|
+
|
|
79
|
+
### SE_SLOP_IN_ORDER_TO: to, not in order to
|
|
80
|
+
|
|
81
|
+
Write to.
|
|
82
|
+
|
|
83
|
+
- Wrong: Run the tool in order to build the file.
|
|
84
|
+
- Right: Run the tool to build the file.
|
|
85
|
+
|
|
86
|
+
### SE_SLOP_PRIOR_TO: before, not prior to
|
|
87
|
+
|
|
88
|
+
Write before.
|
|
89
|
+
|
|
90
|
+
- Wrong: Read the file prior to the upgrade.
|
|
91
|
+
- Right: Read the file before the upgrade.
|
|
92
|
+
|
|
93
|
+
### SE_SLOP_ENSURE: make sure that, not ensure
|
|
94
|
+
|
|
95
|
+
Write make sure that.
|
|
96
|
+
|
|
97
|
+
- Wrong: Ensure the file exists.
|
|
98
|
+
- Right: Make sure that the file exists.
|
|
99
|
+
|
|
100
|
+
### SE_SLOP_FUNCTIONALITY: function, not functionality
|
|
101
|
+
|
|
102
|
+
Write function or feature.
|
|
103
|
+
|
|
104
|
+
- Wrong: Add the functionality first.
|
|
105
|
+
- Right: Add the function first.
|
|
106
|
+
|
|
107
|
+
### SE_SLOP_ENABLES_YOU: you can, not enables you to
|
|
108
|
+
|
|
109
|
+
Write you can.
|
|
110
|
+
|
|
111
|
+
- Wrong: The tool enables you to build the file.
|
|
112
|
+
- Right: You can build the file with the tool.
|
|
113
|
+
|
|
114
|
+
### SE_SLOP_FACILITATE: help, not facilitate
|
|
115
|
+
|
|
116
|
+
Write help or make possible.
|
|
117
|
+
|
|
118
|
+
- Wrong: The tool facilitates the build.
|
|
119
|
+
- Right: The tool helps the build.
|
|
120
|
+
|
|
121
|
+
### SE_SLOP_DELVE: read, not delve into
|
|
122
|
+
|
|
123
|
+
Write read or examine.
|
|
124
|
+
|
|
125
|
+
- Wrong: Delve into the config file.
|
|
126
|
+
- Right: Read the config file.
|
|
127
|
+
|
|
128
|
+
### SE_SLOP_WHEN_IT_COMES: for, not when it comes to
|
|
129
|
+
|
|
130
|
+
Write for.
|
|
131
|
+
|
|
132
|
+
- Wrong: When it comes to builds, use the tool.
|
|
133
|
+
- Right: For builds, use the tool.
|
|
134
|
+
|
|
135
|
+
### SE_SLOP_IN_THE_EVENT: if, not in the event that
|
|
136
|
+
|
|
137
|
+
Write if.
|
|
138
|
+
|
|
139
|
+
- Wrong: In the event that the build fails, read the log.
|
|
140
|
+
- Right: If the build fails, read the log.
|
|
141
|
+
|
|
142
|
+
### SE_SLOP_DUE_TO_FACT: because, not due to the fact that
|
|
143
|
+
|
|
144
|
+
Write because.
|
|
145
|
+
|
|
146
|
+
- Wrong: Due to the fact that the port is closed, the tool fails.
|
|
147
|
+
- Right: Because the port is not open, the tool fails.
|
|
148
|
+
|
|
149
|
+
### SE_SLOP_AND_OR: no and/or
|
|
150
|
+
|
|
151
|
+
Pick one. Or write "X, or Y, or both".
|
|
152
|
+
|
|
153
|
+
- Wrong: Set the flag and/or the port.
|
|
154
|
+
- Right: Set the flag, or the port, or both.
|
|
155
|
+
|
|
156
|
+
### SE_SLOP_LATIN: no Latin abbreviations
|
|
157
|
+
|
|
158
|
+
#### e.g.
|
|
159
|
+
|
|
160
|
+
Write "for example", or name the items.
|
|
161
|
+
|
|
162
|
+
- Wrong: Set the flag, e.g. the port.
|
|
163
|
+
- Right: Set the flag, for example the port.
|
|
164
|
+
|
|
165
|
+
#### i.e.
|
|
166
|
+
|
|
167
|
+
Write "that is", or name the items.
|
|
168
|
+
|
|
169
|
+
- Wrong: Set the flag, i.e. the port.
|
|
170
|
+
- Right: Set the flag, that is the port.
|
|
171
|
+
|
|
172
|
+
#### etc.
|
|
173
|
+
|
|
174
|
+
Name the items.
|
|
175
|
+
|
|
176
|
+
- Wrong: Set the flag, etc.
|
|
177
|
+
- Right: Set the flag or the port.
|
|
178
|
+
|
|
179
|
+
### SE_SLOP_OUT_OF_BOX: by default, not out of the box
|
|
180
|
+
|
|
181
|
+
Write by default.
|
|
182
|
+
|
|
183
|
+
- Wrong: The tool works out of the box.
|
|
184
|
+
- Right: The tool works by default.
|
|
185
|
+
|
|
186
|
+
### SE_SLOP_UNDER_HOOD: internally, not under the hood
|
|
187
|
+
|
|
188
|
+
Write internally.
|
|
189
|
+
|
|
190
|
+
- Wrong: Under the hood, the tool builds a file.
|
|
191
|
+
- Right: Internally, the tool builds a file.
|
|
192
|
+
|
|
193
|
+
### SE_SLOP_STREAMLINE: make simpler, not streamline
|
|
194
|
+
|
|
195
|
+
Write make simpler or make faster.
|
|
196
|
+
|
|
197
|
+
- Wrong: The tool streamlines the build.
|
|
198
|
+
- Right: The tool makes the build simpler.
|
|
199
|
+
|
|
200
|
+
### SE_SLOP_PLETHORA: many, not plethora
|
|
201
|
+
|
|
202
|
+
Write many.
|
|
203
|
+
|
|
204
|
+
- Wrong: The file has a plethora of rows.
|
|
205
|
+
- Right: The file has many rows.
|
|
206
|
+
|
|
207
|
+
### SE_SLOP_ADDRESSES: corrects, not addresses the issue
|
|
208
|
+
|
|
209
|
+
Write corrects the fault or removes the error.
|
|
210
|
+
|
|
211
|
+
- Wrong: The tool addresses the issue.
|
|
212
|
+
- Right: The tool corrects the fault.
|
|
213
|
+
|
|
214
|
+
### SE_SLOP_PIVOTAL: important, not pivotal
|
|
215
|
+
|
|
216
|
+
Write important.
|
|
217
|
+
|
|
218
|
+
- Wrong: The flag is crucial.
|
|
219
|
+
- Right: The flag is important.
|
|
220
|
+
|
|
221
|
+
### SE_SLOP_TAPESTRY: no tapestry, testament, synergy
|
|
222
|
+
|
|
223
|
+
Delete it. State the fact.
|
|
224
|
+
|
|
225
|
+
- Wrong: The design is a testament to the team.
|
|
226
|
+
- Right: The design shows the work of the team.
|
|
227
|
+
|
|
228
|
+
### SE_SLOP_INTERPLAY: interaction, not interplay
|
|
229
|
+
|
|
230
|
+
Write interaction, or delete it.
|
|
231
|
+
|
|
232
|
+
- Wrong: The interplay of the two tools is complex.
|
|
233
|
+
- Right: The interaction of the two tools is complex.
|
|
234
|
+
|
|
235
|
+
### SE_SLOP_INTRICATE: complex, not intricate
|
|
236
|
+
|
|
237
|
+
Write complex.
|
|
238
|
+
|
|
239
|
+
- Wrong: The config is intricate.
|
|
240
|
+
- Right: The config is complex.
|
|
241
|
+
|
|
242
|
+
### SE_SLOP_VIBRANT: delete vibrant, nuanced, multifaceted
|
|
243
|
+
|
|
244
|
+
Delete it, or name the parts.
|
|
245
|
+
|
|
246
|
+
- Wrong: The tool is nuanced.
|
|
247
|
+
- Right: The tool reads three file types.
|
|
248
|
+
|
|
249
|
+
### SE_SLOP_REALM: area, not realm or landscape
|
|
250
|
+
|
|
251
|
+
Write area.
|
|
252
|
+
|
|
253
|
+
- Wrong: In the realm of builds, use the tool.
|
|
254
|
+
- Right: In the area of builds, use the tool.
|
|
255
|
+
|
|
256
|
+
### SE_SLOP_GROUNDBREAKING: new, not groundbreaking
|
|
257
|
+
|
|
258
|
+
Write new, or delete it.
|
|
259
|
+
|
|
260
|
+
- Wrong: The tool is groundbreaking.
|
|
261
|
+
- Right: The tool is new.
|
|
262
|
+
|
|
263
|
+
### SE_SLOP_TRANSFORMATIVE: say what changes, not transformative
|
|
264
|
+
|
|
265
|
+
Delete it. Say what changes.
|
|
266
|
+
|
|
267
|
+
- Wrong: The tool is transformative.
|
|
268
|
+
- Right: The tool cuts the build time in half.
|
|
269
|
+
|
|
270
|
+
### SE_SLOP_REVOLUTIONIZE: change, not revolutionize
|
|
271
|
+
|
|
272
|
+
Write change.
|
|
273
|
+
|
|
274
|
+
- Wrong: The tool revolutionizes the build.
|
|
275
|
+
- Right: The tool changes the build.
|
|
276
|
+
|
|
277
|
+
### SE_SLOP_SHOWCASE: show, not showcase
|
|
278
|
+
|
|
279
|
+
Write show.
|
|
280
|
+
|
|
281
|
+
- Wrong: The log showcases the error.
|
|
282
|
+
- Right: The log shows the error.
|
|
283
|
+
|
|
284
|
+
### SE_SLOP_FOSTER: help, not foster
|
|
285
|
+
|
|
286
|
+
Write help, support, or let.
|
|
287
|
+
|
|
288
|
+
- Wrong: The tool fosters growth.
|
|
289
|
+
- Right: The tool supports growth.
|
|
290
|
+
|
|
291
|
+
### SE_SLOP_HARNESS: use, not harness
|
|
292
|
+
|
|
293
|
+
Write use.
|
|
294
|
+
|
|
295
|
+
- Wrong: Harness the API.
|
|
296
|
+
- Right: Use the API.
|
|
297
|
+
|
|
298
|
+
### SE_SLOP_ENHANCE: improve, not enhance
|
|
299
|
+
|
|
300
|
+
Write improve.
|
|
301
|
+
|
|
302
|
+
- Wrong: The tool enhances the build.
|
|
303
|
+
- Right: The tool improves the build.
|
|
304
|
+
|
|
305
|
+
### SE_SLOP_ELEVATE: increase, not elevate
|
|
306
|
+
|
|
307
|
+
Write increase.
|
|
308
|
+
|
|
309
|
+
- Wrong: The tool elevates the speed.
|
|
310
|
+
- Right: The tool increases the speed.
|
|
311
|
+
|
|
312
|
+
### SE_SLOP_FURTHERMORE: also, not furthermore
|
|
313
|
+
|
|
314
|
+
Write also.
|
|
315
|
+
|
|
316
|
+
- Wrong: Furthermore, the tool reads the log.
|
|
317
|
+
- Right: The tool also reads the log.
|
|
318
|
+
|
|
319
|
+
### SE_SLOP_EMBARK: start, not embark
|
|
320
|
+
|
|
321
|
+
Write start or try.
|
|
322
|
+
|
|
323
|
+
- Wrong: Embark on the build.
|
|
324
|
+
- Right: Start the build.
|
|
325
|
+
|
|
326
|
+
### SE_SLOP_METICULOUS: careful, not meticulous
|
|
327
|
+
|
|
328
|
+
Write careful or carefully.
|
|
329
|
+
|
|
330
|
+
- Wrong: The tool checks the file meticulously.
|
|
331
|
+
- Right: The tool checks the file carefully.
|
|
332
|
+
|
|
333
|
+
### SE_SLOP_HOLISTIC: full, not holistic
|
|
334
|
+
|
|
335
|
+
Write full.
|
|
336
|
+
|
|
337
|
+
- Wrong: The tool gives a holistic view.
|
|
338
|
+
- Right: The tool gives a full view.
|
|
339
|
+
|
|
340
|
+
### SE_SLOP_PARADIGM: model, not paradigm
|
|
341
|
+
|
|
342
|
+
Write model.
|
|
343
|
+
|
|
344
|
+
- Wrong: The tool changes the paradigm.
|
|
345
|
+
- Right: The tool changes the model.
|
|
346
|
+
|
|
347
|
+
### SE_SLOP_BOASTS: has, not boasts
|
|
348
|
+
|
|
349
|
+
Write has.
|
|
350
|
+
|
|
351
|
+
- Wrong: The tool boasts a log.
|
|
352
|
+
- Right: The tool has a log.
|
|
353
|
+
|
|
354
|
+
### SE_SLOP_NOTWITHSTANDING: but, not that being said
|
|
355
|
+
|
|
356
|
+
Write but.
|
|
357
|
+
|
|
358
|
+
- Wrong: The tool works. That being said, it is slow.
|
|
359
|
+
- Right: The tool works, but it is slow.
|
|
360
|
+
|
|
361
|
+
### SE_SLOP_NOTWITHSTANDING2: but, not notwithstanding
|
|
362
|
+
|
|
363
|
+
Write but.
|
|
364
|
+
|
|
365
|
+
- Wrong: Notwithstanding the log, the tool fails.
|
|
366
|
+
- Right: The log exists, but the tool fails.
|
|
367
|
+
|
|
368
|
+
### SE_SLOP_DELETE_ADVERBS: delete empty adverbs
|
|
369
|
+
|
|
370
|
+
Delete it. It carries no fact.
|
|
371
|
+
|
|
372
|
+
- Wrong: The tool works seamlessly.
|
|
373
|
+
- Right: The tool works.
|
|
374
|
+
|
|
375
|
+
### SE_SLOP_JUST: delete just
|
|
376
|
+
|
|
377
|
+
Delete it. It carries no fact.
|
|
378
|
+
|
|
379
|
+
- Wrong: The tool just works.
|
|
380
|
+
- Right: The tool works.
|
|
381
|
+
|
|
382
|
+
### SE_SLOP_DELETE_ADJ: delete empty adjectives
|
|
383
|
+
|
|
384
|
+
Delete it, or give the measurable property.
|
|
385
|
+
|
|
386
|
+
- Wrong: The tool is robust.
|
|
387
|
+
- Right: The tool retries three times, then stops.
|
|
388
|
+
|
|
389
|
+
### SE_SLOP_WORTH_NOTING: delete it is worth noting
|
|
390
|
+
|
|
391
|
+
Delete it. State the fact.
|
|
392
|
+
|
|
393
|
+
- Wrong: It is worth noting that the tool is slow.
|
|
394
|
+
- Right: The tool is slow.
|
|
395
|
+
|
|
396
|
+
### SE_SLOP_IMPORTANT_TO: delete it is important to
|
|
397
|
+
|
|
398
|
+
Delete it. State the fact.
|
|
399
|
+
|
|
400
|
+
- Wrong: It is important to read the log.
|
|
401
|
+
- Right: Read the log.
|
|
402
|
+
|
|
403
|
+
### SE_SLOP_DESIGNED_TO: delete is designed to
|
|
404
|
+
|
|
405
|
+
Say what the tool does.
|
|
406
|
+
|
|
407
|
+
- Wrong: The tool is designed to read logs.
|
|
408
|
+
- Right: The tool reads logs.
|
|
409
|
+
|
|
410
|
+
### SE_SLOP_AIMS_TO: delete aims to
|
|
411
|
+
|
|
412
|
+
Say what the tool does.
|
|
413
|
+
|
|
414
|
+
- Wrong: The tool aims to read logs.
|
|
415
|
+
- Right: The tool reads logs.
|
|
416
|
+
|
|
417
|
+
### SE_SLOP_AS_NEEDED: state the condition, not as needed
|
|
418
|
+
|
|
419
|
+
State the condition.
|
|
420
|
+
|
|
421
|
+
- Wrong: Restart the tool as needed.
|
|
422
|
+
- Right: Restart the tool every day.
|
|
423
|
+
|
|
424
|
+
### SE_SLOP_GRACEFULLY: say what it does, not gracefully handles
|
|
425
|
+
|
|
426
|
+
Say what the tool does: "retries three times, then stops".
|
|
427
|
+
|
|
428
|
+
- Wrong: The tool gracefully handles the error.
|
|
429
|
+
- Right: The tool retries three times, then stops.
|
|
430
|
+
|
|
431
|
+
### SE_SLOP_IN_CONCLUSION: delete in conclusion
|
|
432
|
+
|
|
433
|
+
Delete it. State the fact.
|
|
434
|
+
|
|
435
|
+
- Wrong: In conclusion, the tool works.
|
|
436
|
+
- Right: The tool works.
|
|
437
|
+
|
|
438
|
+
### SE_SLOP_IN_SUMMARY: delete in summary
|
|
439
|
+
|
|
440
|
+
Delete it. State the fact.
|
|
441
|
+
|
|
442
|
+
- Wrong: In summary, the tool works.
|
|
443
|
+
- Right: The tool works.
|
|
444
|
+
|
|
445
|
+
### SE_SLOP_AT_END_OF_DAY: delete at the end of the day
|
|
446
|
+
|
|
447
|
+
Delete it. State the fact.
|
|
448
|
+
|
|
449
|
+
- Wrong: At the end of the day, the tool works.
|
|
450
|
+
- Right: The tool works.
|
|
451
|
+
|
|
452
|
+
### SE_SLOP_NESTLED: give the location, not nestled
|
|
453
|
+
|
|
454
|
+
Give the location.
|
|
455
|
+
|
|
456
|
+
- Wrong: The file is nestled in the folder.
|
|
457
|
+
- Right: The file sits in the folder.
|
|
458
|
+
|
|
459
|
+
### SE_SLOP_BUSTLING: busy, not bustling
|
|
460
|
+
|
|
461
|
+
Write busy.
|
|
462
|
+
|
|
463
|
+
- Wrong: The bustling market has many files.
|
|
464
|
+
- Right: The busy market has many files.
|
|
465
|
+
|
|
466
|
+
### SE_SLOP_HOPE_HELPS: delete I hope this helps
|
|
467
|
+
|
|
468
|
+
Delete it.
|
|
469
|
+
|
|
470
|
+
- Wrong: I hope this helps. Read the log.
|
|
471
|
+
- Right: Read the log.
|
|
472
|
+
|
|
473
|
+
### SE_SLOP_DIVE_IN: delete let's dive in
|
|
474
|
+
|
|
475
|
+
Delete it.
|
|
476
|
+
|
|
477
|
+
- Wrong: let's dive in. Read the log.
|
|
478
|
+
- Right: Read the log.
|
|
479
|
+
|
|
480
|
+
## Counting rules
|
|
481
|
+
|
|
482
|
+
These rules run in Ruby on Markdown text. Code comments do not use
|
|
483
|
+
them. Procedural text is a list item. Descriptive text is every
|
|
484
|
+
other paragraph.
|
|
485
|
+
|
|
486
|
+
### SE_SENTENCE_TOO_LONG
|
|
487
|
+
|
|
488
|
+
A sentence with more than 20 words in
|
|
489
|
+
procedural text, or more than 25 words
|
|
490
|
+
in descriptive text.
|
|
491
|
+
|
|
492
|
+
### SE_PARAGRAPH_TOO_LONG
|
|
493
|
+
|
|
494
|
+
A paragraph with more than 6
|
|
495
|
+
sentences in descriptive text.
|
|
496
|
+
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# The command-line interface: Thor commands for lint and serve, plus
|
|
4
|
+
# a no-op setup for older callers. bin/se is a thin runner over this,
|
|
5
|
+
# so the installed gem's RubyGems shim can load it.
|
|
6
|
+
|
|
7
|
+
require "thor"
|
|
8
|
+
require_relative "../simple_english"
|
|
9
|
+
|
|
10
|
+
module SimpleEnglish
|
|
11
|
+
class CLI < Thor
|
|
12
|
+
def self.exit_on_failure? = true
|
|
13
|
+
|
|
14
|
+
# Bare file arguments and "-" (stdin) are lint targets, not command
|
|
15
|
+
# names. Thor only falls back to the default task when the first
|
|
16
|
+
# argument is an option, so route them to lint explicitly.
|
|
17
|
+
def self.start(given_args = ARGV, config = {})
|
|
18
|
+
first = given_args.first
|
|
19
|
+
if first && !all_commands.key?(first) &&
|
|
20
|
+
(first == "-" || !first.start_with?("-"))
|
|
21
|
+
given_args = ["lint", *given_args]
|
|
22
|
+
end
|
|
23
|
+
# Thor's own commands (help, tree) return junk like nil or a
|
|
24
|
+
# Hash, not an exit status. Contract: start always returns an
|
|
25
|
+
# Integer so every caller (bin/se, tests) can exit on it.
|
|
26
|
+
status = super
|
|
27
|
+
status.is_a?(Integer) ? status : 0
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# The test entry point. It keeps the old module interface.
|
|
31
|
+
def self.run(argv)
|
|
32
|
+
start(argv)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
default_task :lint
|
|
36
|
+
desc "lint FILE_OR_DIR...", "Lint Markdown prose and code comments (- reads stdin)"
|
|
37
|
+
method_option :format, type: :string, default: "text", enum: %w[text json sarif],
|
|
38
|
+
banner: "text|json|sarif"
|
|
39
|
+
def lint(*paths)
|
|
40
|
+
if paths.empty?
|
|
41
|
+
help("lint")
|
|
42
|
+
return 2
|
|
43
|
+
end
|
|
44
|
+
config =
|
|
45
|
+
begin
|
|
46
|
+
SimpleEnglish::Config.load
|
|
47
|
+
rescue SimpleEnglish::Config::ConfigError => e
|
|
48
|
+
warn "error: #{e.message}"
|
|
49
|
+
return 2
|
|
50
|
+
end
|
|
51
|
+
results = []
|
|
52
|
+
self.class.expand_paths(paths).each do |path|
|
|
53
|
+
next if path != "-" && SimpleEnglish::Config.ignore?(config, path)
|
|
54
|
+
unless path == "-" || File.readable?(path)
|
|
55
|
+
warn "error: file not readable: #{path}"
|
|
56
|
+
return 2
|
|
57
|
+
end
|
|
58
|
+
text = (path == "-") ? $stdin.read : File.read(path)
|
|
59
|
+
findings = SimpleEnglish.lint_file(path, text)
|
|
60
|
+
return 2 if findings.nil? # already warned why
|
|
61
|
+
SimpleEnglish::Config.filter(config, path, findings).each do |finding|
|
|
62
|
+
results << [path, finding]
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
self.class.report(results, options[:format])
|
|
66
|
+
results.empty? ? 0 : 1
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
desc "version", "Print the gem version"
|
|
70
|
+
def version
|
|
71
|
+
puts SimpleEnglish::VERSION
|
|
72
|
+
0
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
desc "mcp", "Run the MCP stdio server (one JSON-RPC message per line)"
|
|
76
|
+
def mcp
|
|
77
|
+
SimpleEnglish::ModelContextProtocol.run
|
|
78
|
+
0
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
desc "serve", "Run the lint daemon in the foreground"
|
|
82
|
+
method_option :port, type: :numeric, default: SimpleEnglish::Client::DEFAULT_PORT,
|
|
83
|
+
desc: "Port to listen on"
|
|
84
|
+
method_option :"dev-log", type: :string, banner: "PATH",
|
|
85
|
+
desc: "Write daemon stderr to PATH"
|
|
86
|
+
method_option :detached, type: :boolean,
|
|
87
|
+
desc: "Replace any running se daemon and run in the background"
|
|
88
|
+
def serve
|
|
89
|
+
if options[:detached]
|
|
90
|
+
daemon = SimpleEnglish::Server.start_detached(port: options[:port],
|
|
91
|
+
install: SimpleEnglish::Install.from_env, dev_log: options[:"dev-log"])
|
|
92
|
+
if daemon
|
|
93
|
+
puts "se daemon detached, pid #{daemon["pid"]}, " \
|
|
94
|
+
"on http://localhost:#{options[:port]}"
|
|
95
|
+
return 0
|
|
96
|
+
end
|
|
97
|
+
warn "error: detached daemon did not come up. " \
|
|
98
|
+
"Run `#{Client.runner} serve` and read its output."
|
|
99
|
+
return 2
|
|
100
|
+
end
|
|
101
|
+
log = options[:"dev-log"] ? File.open(options[:"dev-log"], "w") : $stderr
|
|
102
|
+
SimpleEnglish::Server.start(port: options[:port],
|
|
103
|
+
install: SimpleEnglish::Install.from_env, log: log)
|
|
104
|
+
0
|
|
105
|
+
rescue SimpleEnglish::Install::SetupError, SimpleEnglish::Server::ServerError,
|
|
106
|
+
SimpleEnglish::Config::ConfigError => e
|
|
107
|
+
warn "error: #{e.message}"
|
|
108
|
+
2
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
desc "setup", "Do nothing; the lint engine ships with the gem"
|
|
112
|
+
def setup
|
|
113
|
+
puts "nothing to set up; the lint engine ships with the gem"
|
|
114
|
+
0
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# "-" stays as-is for stdin. Directories expand to all lintable files.
|
|
118
|
+
# Glob output keeps a "./" prefix when the argument is ".". Strip it so
|
|
119
|
+
# paths and config ignore globs always see the same form.
|
|
120
|
+
# These trees hold third-party prose, not the user's. The tool lints
|
|
121
|
+
# what the user owns. Skipped only during directory expansion. An
|
|
122
|
+
# explicit path always lints.
|
|
123
|
+
# Dir.glob never returns dotfiles, so ".git" is inert today. It
|
|
124
|
+
# guards a future FNM_DOTMATCH from turning git internals back on.
|
|
125
|
+
# .gitignore is not read. Users put ignore: globs in the config for
|
|
126
|
+
# build output and generated files.
|
|
127
|
+
SKIPPED_DIRS = [".git", "node_modules", "vendor"].freeze
|
|
128
|
+
|
|
129
|
+
def self.expand_paths(argv)
|
|
130
|
+
extensions = (SimpleEnglish::Extractor::EXTENSION_LANGUAGES.keys.map { |e| e.delete_prefix(".") } + ["md"]).uniq.join(",")
|
|
131
|
+
argv.flat_map do |path|
|
|
132
|
+
if File.directory?(path)
|
|
133
|
+
Dir.glob(File.join(path, "**/*.{#{extensions}}"))
|
|
134
|
+
.reject { |p| p.split(File::SEPARATOR).any? { |s| SKIPPED_DIRS.include?(s) } }
|
|
135
|
+
.sort
|
|
136
|
+
else
|
|
137
|
+
path
|
|
138
|
+
end
|
|
139
|
+
end.map { |path| path.delete_prefix("./") }
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def self.report(results, format)
|
|
143
|
+
require "json"
|
|
144
|
+
case format
|
|
145
|
+
when "json"
|
|
146
|
+
puts JSON.pretty_generate(results.map do |path, finding|
|
|
147
|
+
{"path" => path, "line" => finding.line, "column" => finding.column,
|
|
148
|
+
"end_line" => finding.end_line, "end_column" => finding.end_column,
|
|
149
|
+
"rule" => finding.rule, "message" => finding.message}
|
|
150
|
+
end)
|
|
151
|
+
when "sarif"
|
|
152
|
+
puts JSON.pretty_generate(
|
|
153
|
+
"version" => "2.1.0",
|
|
154
|
+
"$schema" => "https://json.schemastore.org/sarif-2.1.0.json",
|
|
155
|
+
"runs" => [{
|
|
156
|
+
"columnKind" => "utf16CodeUnits",
|
|
157
|
+
"tool" => {"driver" => {"name" => "se"}},
|
|
158
|
+
"results" => results.map do |path, finding|
|
|
159
|
+
region = {"startLine" => finding.line}
|
|
160
|
+
if finding.column
|
|
161
|
+
region["startColumn"] = finding.column
|
|
162
|
+
if finding.end_line && finding.end_column
|
|
163
|
+
region["endLine"] = finding.end_line
|
|
164
|
+
region["endColumn"] = finding.end_column
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
{"ruleId" => finding.rule, "level" => "error",
|
|
168
|
+
"message" => {"text" => finding.message},
|
|
169
|
+
"locations" => [{"physicalLocation" => {
|
|
170
|
+
"artifactLocation" => {"uri" => path},
|
|
171
|
+
"region" => region
|
|
172
|
+
}}]}
|
|
173
|
+
end
|
|
174
|
+
}]
|
|
175
|
+
)
|
|
176
|
+
else
|
|
177
|
+
results.each do |path, finding|
|
|
178
|
+
puts finding.to_line(path)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|