simple_english 0.5.0 → 0.13.1
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/README.md +152 -90
- data/THIRD_PARTY_NOTICES.md +72 -0
- data/docs/RULES.md +87 -1
- data/lib/simple_english/cli.rb +19 -32
- data/lib/simple_english/client/daemon.rb +6 -7
- data/lib/simple_english/client/language_tool.rb +5 -13
- data/lib/simple_english/daemon/engine.rb +1 -1
- data/lib/simple_english/daemon/server.rb +24 -43
- data/lib/simple_english/lint/annotated_text.rb +8 -21
- data/lib/simple_english/lint/extractor.rb +49 -2
- data/lib/simple_english/lint/lint_plan.rb +1 -1
- data/lib/simple_english/lint/linter.rb +17 -0
- data/lib/simple_english/lint/markdown.rb +4 -7
- data/lib/simple_english/lint/utf16.rb +33 -0
- data/lib/simple_english/model_context_protocol.rb +17 -18
- data/lib/simple_english/setup/config.rb +30 -8
- data/lib/simple_english/setup/install.rb +26 -61
- data/lib/simple_english/setup/languagetool.rb +6 -213
- data/lib/simple_english/version.rb +1 -1
- data/lib/simple_english.rb +16 -28
- 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 +153 -2
- metadata +22 -14
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 93340f34e689001d1b7d4c1efd03ed23468f93811010ecf19749f09c753c7573
|
|
4
|
+
data.tar.gz: 2c243f1af37438e4223aa7b9ce6706394a9000cae96177ca1df97917371fcb2f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 61e26907b3efc837bf972f3c0da291146c626141c2e3c3225cb404de16bb66319f06eceda0da6dff6a6bfc92adf4c756cc333f6c454387ae471bb172fb6924f9
|
|
7
|
+
data.tar.gz: 818b641b03cb6c8227020ba879e85a334db14ce3894a2b26972f4c45063ea305aad1308d7736645ae050327460c241697d7ca4b294db2903016b850fbab2557e
|
data/README.md
CHANGED
|
@@ -4,25 +4,57 @@
|
|
|
4
4
|
|
|
5
5
|
# simple_english
|
|
6
6
|
|
|
7
|
-
> Write
|
|
7
|
+
> Write plain English for humans. Keep the agent honest.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
You can teach an agent plain-English prose with a skill or a
|
|
10
|
+
prompt. It writes clean prose in the first paragraph and slop again
|
|
11
|
+
by the third. This linter keeps the agent honest: it reads what the
|
|
12
|
+
agent wrote and names every broken rule. Send the findings back, and
|
|
13
|
+
the agent corrects its own text.
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
<table>
|
|
16
|
+
<tr>
|
|
17
|
+
<th width="50%">Before</th>
|
|
18
|
+
<th width="50%">After</th>
|
|
19
|
+
</tr>
|
|
20
|
+
<tr>
|
|
21
|
+
<td valign="top">
|
|
22
|
+
|
|
23
|
+
> Your API keys are rotated by the service every 90 days — you will need to update them if you get a 401; don't panic, simply re-run the setup command, which regenerates the credentials without any downtime. <!-- se: ignore -->
|
|
24
|
+
|
|
25
|
+
</td>
|
|
26
|
+
<td valign="top">
|
|
27
|
+
|
|
28
|
+
> The service rotates your API keys every 90 days. If you get a 401, update them. Do not panic. Re-run the setup command. It regenerates the credentials without any downtime.
|
|
22
29
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
30
|
+
</td>
|
|
31
|
+
</tr>
|
|
32
|
+
</table>
|
|
33
|
+
|
|
34
|
+
The linter covers Markdown prose plus code comments in Python, Ruby,
|
|
35
|
+
JavaScript, TypeScript, Go, Rust, Java, C, C++, and C#. It also
|
|
36
|
+
reads Objective-C, Kotlin, Swift, Scala, Dart, PHP, Perl, Elixir,
|
|
37
|
+
Lua, R, Haskell, Zig, SQL, and bash. It reads comments in config
|
|
38
|
+
formats and markup as well: YAML, TOML, INI, Makefile, Dockerfile,
|
|
39
|
+
HTML, and XML. Findings print as plain text, JSON, or SARIF.
|
|
40
|
+
|
|
41
|
+
If your language is not on the list, [open an issue](https://github.com/TonyCTHsu/simple-english/issues).
|
|
42
|
+
|
|
43
|
+
## Agent integrations
|
|
44
|
+
|
|
45
|
+
Plug the linter into your coding agent. It writes plain English on
|
|
46
|
+
the first pass and checks its own draft before you read the file.
|
|
47
|
+
|
|
48
|
+
| Coding agent | Ships as | Docs |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| `pi` | npm package `pi-simple-english` | [README](integrations/pi/README.md) |
|
|
51
|
+
| `claude-code` | plugin `simple-english` | [README](integrations/claude-code/README.md) |
|
|
52
|
+
| `codex` | plugin `simple-english` | [README](integrations/codex/README.md) |
|
|
53
|
+
| `cursor` | plugin folder `simple-english` | [README](integrations/cursor/README.md) |
|
|
54
|
+
| `opencode` | plugin `simple-english` | [README](integrations/opencode/README.md) |
|
|
55
|
+
| `vscode-copilot` | config wiring | [README](integrations/vscode-copilot/README.md) |
|
|
56
|
+
|
|
57
|
+
If your agent is not on the list, [open an issue](https://github.com/TonyCTHsu/simple-english/issues).
|
|
26
58
|
|
|
27
59
|
## The rules
|
|
28
60
|
|
|
@@ -36,53 +68,52 @@ plain text, JSON, or SARIF.
|
|
|
36
68
|
- **Code comments:** same pattern rules, with line and column range.
|
|
37
69
|
- **Counts (Markdown only):** 20 words per sentence in list items, 25 in paragraphs, six sentences per paragraph at most.
|
|
38
70
|
|
|
39
|
-
The full list, with a wrong and a right example for each rule
|
|
40
|
-
[docs/RULES.md](docs/RULES.md).
|
|
71
|
+
The full list, with a wrong and a right example for each rule [docs/RULES.md](docs/RULES.md).
|
|
41
72
|
|
|
42
73
|
## Install
|
|
43
74
|
|
|
44
|
-
|
|
45
|
-
Windows, or CI, you need Ruby 3.3 or newer and Java 11 or newer for
|
|
46
|
-
LanguageTool. The Docker image bundles both.
|
|
75
|
+
### Prerequisites
|
|
47
76
|
|
|
48
|
-
|
|
77
|
+
The gem needs Ruby 3.3 or newer. On a Mac, the system Ruby (2.6) is too
|
|
78
|
+
old. Install one, for example with Homebrew:
|
|
49
79
|
|
|
50
80
|
```bash
|
|
51
|
-
brew install
|
|
52
|
-
brew services start simple-english
|
|
81
|
+
brew install ruby
|
|
53
82
|
```
|
|
54
83
|
|
|
55
|
-
Homebrew
|
|
56
|
-
|
|
57
|
-
start downloads LanguageTool (about 300 MB), and later lints take
|
|
58
|
-
milliseconds. Run `brew services stop simple-english` to stop it.
|
|
59
|
-
|
|
60
|
-
### Ruby gem (Linux, Windows, CI)
|
|
84
|
+
Homebrew's Ruby is not on the `PATH` by default, and neither are gem
|
|
85
|
+
binaries. Put both in your shell profile:
|
|
61
86
|
|
|
62
87
|
```bash
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
88
|
+
echo 'export PATH="/opt/homebrew/opt/ruby/bin:$PATH"' >> ~/.zshrc
|
|
89
|
+
echo 'export GEM_HOME="$HOME/.gem"' >> ~/.zshrc
|
|
90
|
+
echo 'export PATH="$GEM_HOME/bin:$PATH"' >> ~/.zshrc
|
|
66
91
|
```
|
|
67
92
|
|
|
68
|
-
|
|
93
|
+
Then open a new terminal. A version manager such as `mise` or `rbenv`
|
|
94
|
+
works too.
|
|
69
95
|
|
|
70
|
-
###
|
|
96
|
+
### Ruby gem (macOS arm64, Linux x86-64 and arm64)
|
|
71
97
|
|
|
72
|
-
|
|
98
|
+
```bash
|
|
99
|
+
gem install simple_english
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Homebrew (macOS arm64)
|
|
73
103
|
|
|
74
104
|
```bash
|
|
75
|
-
|
|
105
|
+
brew install TonyCTHsu/tap/simple-english
|
|
76
106
|
```
|
|
77
107
|
|
|
78
|
-
###
|
|
108
|
+
### Container
|
|
79
109
|
|
|
80
|
-
|
|
110
|
+
```bash
|
|
111
|
+
docker run --rm -v "$PWD":/work ghcr.io/tonycthsu/simple-english .
|
|
112
|
+
```
|
|
81
113
|
|
|
82
114
|
## Usage
|
|
83
115
|
|
|
84
|
-
Lint files, directories, or stdin
|
|
85
|
-
run through `bin/se`:
|
|
116
|
+
Lint files, directories, or stdin:
|
|
86
117
|
|
|
87
118
|
```bash
|
|
88
119
|
se README.md
|
|
@@ -113,34 +144,72 @@ se --format sarif src/ > results.sarif
|
|
|
113
144
|
|
|
114
145
|
- `0`: no findings
|
|
115
146
|
- `1`: findings
|
|
116
|
-
- `2`:
|
|
147
|
+
- `2`: input, configuration, installation, or daemon error
|
|
148
|
+
|
|
149
|
+
### MCP server
|
|
150
|
+
|
|
151
|
+
Start an MCP stdio server with one tool, `lint`. Any MCP
|
|
152
|
+
client can call it.
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
se mcp
|
|
156
|
+
```
|
|
117
157
|
|
|
118
158
|
### CI
|
|
119
159
|
|
|
120
|
-
Gate the prose in
|
|
121
|
-
fails the build on findings, and the SARIF report puts them inline:
|
|
160
|
+
Gate the pull request's prose in GitHub Actions. The lint fails the build on findings:
|
|
122
161
|
|
|
123
162
|
```yaml
|
|
124
163
|
name: lint-docs
|
|
125
164
|
on: [pull_request]
|
|
126
|
-
permissions:
|
|
127
|
-
security-events: write
|
|
128
165
|
jobs:
|
|
129
166
|
lint:
|
|
130
167
|
runs-on: ubuntu-latest
|
|
131
168
|
steps:
|
|
132
169
|
- uses: actions/checkout@v7
|
|
133
|
-
- uses:
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
170
|
+
- uses: TonyCTHsu/simple-english@v0.13.1
|
|
171
|
+
with:
|
|
172
|
+
files: |
|
|
173
|
+
docs/
|
|
174
|
+
README.md
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
To see the findings inline in the pull request, lint with
|
|
178
|
+
`format: sarif` and upload the report. Add
|
|
179
|
+
`permissions: {security-events: write}` to the workflow:
|
|
180
|
+
|
|
181
|
+
```yaml
|
|
182
|
+
- uses: TonyCTHsu/simple-english@v0.13.1
|
|
183
|
+
with:
|
|
184
|
+
format: sarif
|
|
138
185
|
- uses: github/codeql-action/upload-sarif@v3
|
|
139
186
|
with:
|
|
140
|
-
sarif_file:
|
|
187
|
+
sarif_file: simple-english.sarif
|
|
141
188
|
if: always()
|
|
142
189
|
```
|
|
143
190
|
|
|
191
|
+
Any CI can run the lint. Install the gem, run `se lint .`, and fail the
|
|
192
|
+
build on exit code 1.
|
|
193
|
+
|
|
194
|
+
### Git hooks
|
|
195
|
+
|
|
196
|
+
Install the gem once, then wire your hook runner. The command to run
|
|
197
|
+
is `se lint`.
|
|
198
|
+
|
|
199
|
+
#### Pre-commit framework
|
|
200
|
+
|
|
201
|
+
```yaml
|
|
202
|
+
# .pre-commit-config.yaml
|
|
203
|
+
repos:
|
|
204
|
+
- repo: https://github.com/TonyCTHsu/simple-english
|
|
205
|
+
rev: v0.13.1
|
|
206
|
+
hooks:
|
|
207
|
+
- id: se-lint
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
For Husky with lint-staged, map every staged file to `se lint`. For
|
|
211
|
+
Lefthook, run `se lint {staged_files}` in a `pre-commit` command.
|
|
212
|
+
|
|
144
213
|
## Config and suppressions
|
|
145
214
|
|
|
146
215
|
### Config file
|
|
@@ -152,10 +221,27 @@ ignore:
|
|
|
152
221
|
- vendor/**
|
|
153
222
|
disabled-rules:
|
|
154
223
|
- SE_NO_EMDASH
|
|
224
|
+
rule-ignores:
|
|
225
|
+
SE_MODAL_RESTRICTED:
|
|
226
|
+
- .agents/skills/**
|
|
155
227
|
```
|
|
156
228
|
|
|
157
229
|
`ignore` globs: `**` crosses directories, `*` stays in one segment.
|
|
158
230
|
|
|
231
|
+
`disabled-rules` drops a rule from every file. `rule-ignores` drops
|
|
232
|
+
a rule only on the listed paths. The rule still fires everywhere
|
|
233
|
+
else. It covers prose that plays by different rules, like spec
|
|
234
|
+
text that quotes a standard's "SHOULD": <!-- se: ignore=SE_MODAL_RESTRICTED -->
|
|
235
|
+
|
|
236
|
+
```yaml
|
|
237
|
+
rule-ignores:
|
|
238
|
+
SE_MODAL_RESTRICTED:
|
|
239
|
+
- .agents/skills/**
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
With that config, `SE_MODAL_RESTRICTED` fires in `docs/` and the
|
|
243
|
+
README, and stays quiet under `.agents/skills/`.
|
|
244
|
+
|
|
159
245
|
### Inline suppressions
|
|
160
246
|
|
|
161
247
|
A line containing `se: ignore` suppresses findings reported on that
|
|
@@ -175,57 +261,33 @@ In a code comment:
|
|
|
175
261
|
# Don't touch this constant. se: ignore=SE_NO_CONTRACTIONS
|
|
176
262
|
```
|
|
177
263
|
|
|
178
|
-
## The background daemon
|
|
179
|
-
|
|
180
|
-
The CLI runs a small background server on your machine. The first
|
|
181
|
-
lint starts it, which takes about 15 seconds. Later lints take
|
|
182
|
-
milliseconds.
|
|
183
|
-
|
|
184
|
-
The first lint after a gem update prints a warning. Run `se serve --detached` then.
|
|
185
|
-
It stops the old daemon and starts the new one in the
|
|
186
|
-
background. You never talk to the daemon directly. Its HTTP
|
|
187
|
-
interface is internal and can change in any release.
|
|
188
|
-
|
|
189
|
-
## Scope
|
|
190
|
-
|
|
191
|
-
The rule set comes from the Plain-mode rules of the MIT-licensed
|
|
192
|
-
SimpleEnglish project. This tool does not check ASD-STE100 compliance.
|
|
193
|
-
This repo holds no ASD-STE100 text. If you need full compliance, read
|
|
194
|
-
the free standard at <https://www.asd-ste100.org/>.
|
|
195
|
-
|
|
196
264
|
## FAQ
|
|
197
265
|
|
|
198
|
-
### Have you thought about an agent skill?
|
|
199
|
-
|
|
200
|
-
The [SimpleEnglish project](https://github.com/AminBlg/SimpleEnglish)
|
|
201
|
-
ships one. Its skill guides an agent while it writes. This tool does
|
|
202
|
-
the other half of the work. It checks the result against fixed
|
|
203
|
-
rules. Use both: the skill helps the first draft, and the linter
|
|
204
|
-
catches what the agent missed.
|
|
205
|
-
|
|
206
266
|
### Why not Vale?
|
|
207
267
|
|
|
208
|
-
We ported
|
|
268
|
+
We ported rules to Vale and ran the corpus on both engines.
|
|
209
269
|
About 60 rules behave the same. Vale has no check for the em-dash
|
|
210
270
|
and semicolon rules: its checks see words, not punctuation. Its
|
|
211
271
|
tagger also mislabels verbs, so the condition-first rule stays
|
|
212
|
-
silent.
|
|
213
|
-
verifies. Closing the Vale gaps needs scripts or an external
|
|
272
|
+
silent. Closing the Vale gaps needs scripts or an external
|
|
214
273
|
tagger, and that erases Vale's main advantage: one binary with no
|
|
215
274
|
service behind it.
|
|
216
275
|
|
|
217
|
-
##
|
|
276
|
+
## Compliance
|
|
218
277
|
|
|
219
|
-
|
|
220
|
-
|
|
278
|
+
This tool does not check ASD-STE100 compliance. This repo holds no
|
|
279
|
+
ASD-STE100 text. For full compliance, read the free standard at
|
|
280
|
+
<https://www.asd-ste100.org/>.
|
|
221
281
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
282
|
+
The tool checks no external style standard. The rules are this repo's
|
|
283
|
+
own, but they draw on the [GOV.UK A to Z style
|
|
284
|
+
guide](https://guidance.publishing.service.gov.uk/writing-to-gov-uk-standards/style-guides/a-to-z-style-guide/)
|
|
285
|
+
and the [US plain language
|
|
286
|
+
guide](https://digital.gov/guides/plain-language/).
|
|
227
287
|
|
|
228
|
-
|
|
288
|
+
The rule sources are `rules/simple-english.xml` for pattern rules and
|
|
289
|
+
`lib/simple_english/lint/counts.rb` for counting rules. The full list
|
|
290
|
+
sits in [docs/RULES.md](docs/RULES.md).
|
|
229
291
|
|
|
230
292
|
## Develop
|
|
231
293
|
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
Files under `licenses/` carry the license texts and upstream notices
|
|
4
|
+
for third-party software distributed inside this gem. Simple English's
|
|
5
|
+
own code is MIT-licensed; see `LICENSE`.
|
|
6
|
+
|
|
7
|
+
## Lint engine
|
|
8
|
+
|
|
9
|
+
Each platform gem ships a compiled lint engine at
|
|
10
|
+
`libexec/simple_english/languagetool-server`. The binary is built with
|
|
11
|
+
GraalVM Community Edition 25.0.2 and contains code from the
|
|
12
|
+
components below. The authoritative list of components inside a given
|
|
13
|
+
binary is the CycloneDX SBOM published with each release
|
|
14
|
+
(`dist/languagetool-server-<platform>.sbom.json`).
|
|
15
|
+
|
|
16
|
+
| Component | License | Notice |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| LanguageTool 6.6 (`languagetool-core`, `languagetool-server`, `languagetool-gui-commons`, `language-en`, `language-ca`, `language-es`, `language-pt`), unmodified except for a build-time copy of `rules/simple-english.xml` into the English rules | LGPL-2.1 | `licenses/LGPL-2.1.txt` |
|
|
19
|
+
| English word-list and POS data (12dicts, AGID, Moby/WordNet POS) | upstream terms, public domain | `licenses/languagetool-resource-en/` |
|
|
20
|
+
| `at.favre.lib:bcrypt` 0.10.2 | Apache-2.0 | |
|
|
21
|
+
| `ch.qos.logback:logback-classic` 1.5.18 | EPL-1.0 or LGPL-2.1 | |
|
|
22
|
+
| `co.elastic.logging:logback-ecs-encoder` 1.3.2 | Apache-2.0 | |
|
|
23
|
+
| `com.fasterxml.jackson.core:jackson-databind` 2.18.0 | Apache-2.0 | |
|
|
24
|
+
| `commons-cli:commons-cli` 1.9.0 | Apache-2.0 | |
|
|
25
|
+
| `commons-codec:commons-codec` 1.17.1 | Apache-2.0 | |
|
|
26
|
+
| `edu.washington.cs.knowitall:opennlp-*` models 1.5 | Apache-2.0 | |
|
|
27
|
+
| `io.lettuce:lettuce-core` 6.5.4 | MIT | |
|
|
28
|
+
| `io.prometheus:simpleclient_*` 0.16.0 | Apache-2.0 | |
|
|
29
|
+
| `org.apache.opennlp:opennlp-tools` 1.9.4 | Apache-2.0 | |
|
|
30
|
+
| `org.mariadb.jdbc:mariadb-java-client` 3.4.1 | LGPL-2.1 | `licenses/LGPL-2.1.txt` |
|
|
31
|
+
| `org.mybatis:mybatis` 3.5.16 | Apache-2.0 | |
|
|
32
|
+
| `org.slf4j:slf4j-api` 2.0.16 | MIT | |
|
|
33
|
+
| GraalVM and OpenJDK runtime code | GPLv2 with the Classpath Exception | `licenses/OpenJDK-LICENSE.txt` |
|
|
34
|
+
|
|
35
|
+
The engine uses logback under its LGPL-2.1 option, not its EPL-1.0
|
|
36
|
+
option.
|
|
37
|
+
|
|
38
|
+
## LGPL 2.1 obligations
|
|
39
|
+
|
|
40
|
+
LanguageTool is licensed under the GNU Lesser General Public License
|
|
41
|
+
2.1. This gem distributes a binary statically linked with
|
|
42
|
+
LanguageTool, which LGPL 2.1 section 6 permits when recipients can
|
|
43
|
+
study, modify, and rebuild the LGPL part:
|
|
44
|
+
|
|
45
|
+
- The license text ships with every gem (`licenses/LGPL-2.1.txt`).
|
|
46
|
+
- The corresponding LanguageTool source is the `v6.6` tag at
|
|
47
|
+
https://github.com/languagetool-org/languagetool/tree/v6.6
|
|
48
|
+
- The gem's MIT license permits reverse engineering, so you may
|
|
49
|
+
debug the binary and your modifications to it.
|
|
50
|
+
- You can rebuild the engine against a modified LanguageTool: change
|
|
51
|
+
the version in `native/languagetool/pom.xml` and follow the
|
|
52
|
+
rebuild steps in `native/languagetool/README.md` under "Changing
|
|
53
|
+
the native engine".
|
|
54
|
+
|
|
55
|
+
Written offer under section 6(c): we give any recipient the
|
|
56
|
+
machine-readable materials that section 6(a) names, for at least three
|
|
57
|
+
years after each release, at no charge. Ask in an issue at
|
|
58
|
+
https://github.com/TonyCTHsu/simple-english/issues. The materials are
|
|
59
|
+
the LanguageTool `v6.6` source, the resolved classpath of
|
|
60
|
+
`native/languagetool/pom.xml` as Maven Central artifacts, the
|
|
61
|
+
reachability metadata under `native/languagetool/config/`, and the
|
|
62
|
+
build scripts `native/languagetool/build.rb` and `Rakefile` with the
|
|
63
|
+
`rules/simple-english.xml` overlay. You need them to modify
|
|
64
|
+
LanguageTool and relink a working engine.
|
|
65
|
+
|
|
66
|
+
## OpenJDK and GraalVM source
|
|
67
|
+
|
|
68
|
+
The binary embeds OpenJDK and GraalVM Community runtime code under
|
|
69
|
+
GPLv2 with the Classpath Exception. The corresponding source is
|
|
70
|
+
public: https://github.com/openjdk/jdk and
|
|
71
|
+
https://github.com/oracle/graal. The release SBOM names the versions
|
|
72
|
+
the binary embeds.
|
data/docs/RULES.md
CHANGED
|
@@ -50,7 +50,7 @@ Use the simple past. Say when it happened.
|
|
|
50
50
|
|
|
51
51
|
### SE_ING_AFTER_COMMA: No -ing after a comma
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
Write a new sentence, or put the condition first. A trailing -ing phrase hides who does what and when.
|
|
54
54
|
|
|
55
55
|
- Wrong: The tool runs, making it easy.
|
|
56
56
|
- Right: The tool runs. It is easy.
|
|
@@ -477,6 +477,92 @@ Delete it.
|
|
|
477
477
|
- Wrong: let's dive in. Read the log.
|
|
478
478
|
- Right: Read the log.
|
|
479
479
|
|
|
480
|
+
### SE_SLOP_EMPOWER: allow, not empower
|
|
481
|
+
|
|
482
|
+
Write allow.
|
|
483
|
+
|
|
484
|
+
- Wrong: The setting empowers the user to edit files.
|
|
485
|
+
- Right: The setting allows the user to edit files.
|
|
486
|
+
|
|
487
|
+
### SE_SLOP_COLLABORATE: work with, not collaborate or liaise
|
|
488
|
+
|
|
489
|
+
Write work with.
|
|
490
|
+
|
|
491
|
+
- Wrong: The team collaborates with the owners.
|
|
492
|
+
- Right: The team works with the owners.
|
|
493
|
+
|
|
494
|
+
### SE_SLOP_INITIATE: start, not initiate
|
|
495
|
+
|
|
496
|
+
Write start.
|
|
497
|
+
|
|
498
|
+
- Wrong: Initiate the build.
|
|
499
|
+
- Right: Start the build.
|
|
500
|
+
|
|
501
|
+
### SE_SLOP_GOING_FORWARD: from now on, not going forward
|
|
502
|
+
|
|
503
|
+
Write from now on.
|
|
504
|
+
|
|
505
|
+
- Wrong: Going forward, read the log.
|
|
506
|
+
- Right: From now on, read the log.
|
|
507
|
+
|
|
508
|
+
### SE_SLOP_TACKLE: solve, not tackle
|
|
509
|
+
|
|
510
|
+
Write solve or deal with.
|
|
511
|
+
|
|
512
|
+
- Wrong: The team tackled the problem.
|
|
513
|
+
- Right: The team solved the problem.
|
|
514
|
+
|
|
515
|
+
### SE_HIDDEN_VERB_DECISION: decide, not make a decision
|
|
516
|
+
|
|
517
|
+
Write decide.
|
|
518
|
+
|
|
519
|
+
- Wrong: Make a decision before the release.
|
|
520
|
+
- Right: Decide before the release.
|
|
521
|
+
|
|
522
|
+
### SE_HIDDEN_VERB_ASSISTANCE: help, not provide assistance
|
|
523
|
+
|
|
524
|
+
Write help.
|
|
525
|
+
|
|
526
|
+
- Wrong: The tool provides assistance to new users.
|
|
527
|
+
- Right: The tool helps new users.
|
|
528
|
+
|
|
529
|
+
### SE_HIDDEN_VERB_CONSIDERATION: consider, not take into consideration
|
|
530
|
+
|
|
531
|
+
Write consider.
|
|
532
|
+
|
|
533
|
+
- Wrong: Take the failure into consideration before you restart.
|
|
534
|
+
- Right: Consider the failure before you restart.
|
|
535
|
+
|
|
536
|
+
### SE_HIDDEN_VERB_ABLE: can, not is able to
|
|
537
|
+
|
|
538
|
+
Write can.
|
|
539
|
+
|
|
540
|
+
- Wrong: The tool is able to read the log.
|
|
541
|
+
- Right: The tool can read the log.
|
|
542
|
+
|
|
543
|
+
### SE_NUMBER_WORDS: numerals, not compound number words
|
|
544
|
+
|
|
545
|
+
#### spelled with a space
|
|
546
|
+
|
|
547
|
+
Write the numeral, such as 24.
|
|
548
|
+
|
|
549
|
+
- Wrong: The log keeps twenty four hours.
|
|
550
|
+
- Right: The log keeps 24 hours.
|
|
551
|
+
|
|
552
|
+
#### spelled with a hyphen
|
|
553
|
+
|
|
554
|
+
Write the numeral, such as 24.
|
|
555
|
+
|
|
556
|
+
- Wrong: The job runs for twenty-four hours.
|
|
557
|
+
- Right: The job runs for 24 hours.
|
|
558
|
+
|
|
559
|
+
#### standalone teens and tens
|
|
560
|
+
|
|
561
|
+
Write the numeral, such as 12.
|
|
562
|
+
|
|
563
|
+
- Wrong: The retry waits fifteen seconds.
|
|
564
|
+
- Right: The retry waits 15 seconds.
|
|
565
|
+
|
|
480
566
|
## Counting rules
|
|
481
567
|
|
|
482
568
|
These rules run in Ruby on Markdown text. Code comments do not use
|
data/lib/simple_english/cli.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# The command-line interface: Thor commands for lint
|
|
4
|
-
# setup. bin/se is a thin runner over this,
|
|
5
|
-
# gem's RubyGems shim can load it.
|
|
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
6
|
|
|
7
7
|
require "thor"
|
|
8
8
|
require_relative "../simple_english"
|
|
@@ -15,6 +15,10 @@ module SimpleEnglish
|
|
|
15
15
|
# names. Thor only falls back to the default task when the first
|
|
16
16
|
# argument is an option, so route them to lint explicitly.
|
|
17
17
|
def self.start(given_args = ARGV, config = {})
|
|
18
|
+
# GUI apps (Claude Desktop) and cron spawn this CLI without a
|
|
19
|
+
# locale, so Ruby reads stdin and files as US-ASCII and chokes on
|
|
20
|
+
# non-ASCII prose (issue 95). Prose is UTF-8 by spec.
|
|
21
|
+
Encoding.default_external = Encoding::UTF_8
|
|
18
22
|
first = given_args.first
|
|
19
23
|
if first && !all_commands.key?(first) &&
|
|
20
24
|
(first == "-" || !first.start_with?("-"))
|
|
@@ -32,10 +36,6 @@ module SimpleEnglish
|
|
|
32
36
|
start(argv)
|
|
33
37
|
end
|
|
34
38
|
|
|
35
|
-
# How each Install.java_source found its java, for `se setup`'s
|
|
36
|
-
# report line.
|
|
37
|
-
JAVA_SOURCES = {env: "SE_JAVA", path: "PATH", homebrew: "Homebrew fallback"}.freeze
|
|
38
|
-
|
|
39
39
|
default_task :lint
|
|
40
40
|
desc "lint FILE_OR_DIR...", "Lint Markdown prose and code comments (- reads stdin)"
|
|
41
41
|
method_option :format, type: :string, default: "text", enum: %w[text json sarif],
|
|
@@ -59,18 +59,22 @@ module SimpleEnglish
|
|
|
59
59
|
warn "error: file not readable: #{path}"
|
|
60
60
|
return 2
|
|
61
61
|
end
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
# The lintable gate in Linter reads lintable files itself. A
|
|
63
|
+
# non-lintable path must not cost a full read here.
|
|
64
|
+
findings =
|
|
65
|
+
if path == "-"
|
|
66
|
+
SimpleEnglish::Linter.lint_text($stdin.read, config: config)
|
|
67
|
+
else
|
|
68
|
+
SimpleEnglish::Linter.lint_file(path, config: config)
|
|
69
|
+
end
|
|
64
70
|
return 2 if findings.nil? # already warned why
|
|
65
|
-
|
|
66
|
-
results << [path, finding]
|
|
67
|
-
end
|
|
71
|
+
findings.each { |finding| results << [path, finding] }
|
|
68
72
|
end
|
|
69
73
|
self.class.report(results, options[:format])
|
|
70
74
|
results.empty? ? 0 : 1
|
|
71
75
|
end
|
|
72
76
|
|
|
73
|
-
desc "version", "Print the gem version
|
|
77
|
+
desc "version", "Print the gem version"
|
|
74
78
|
def version
|
|
75
79
|
puts SimpleEnglish::VERSION
|
|
76
80
|
0
|
|
@@ -112,26 +116,9 @@ module SimpleEnglish
|
|
|
112
116
|
2
|
|
113
117
|
end
|
|
114
118
|
|
|
115
|
-
desc "setup", "
|
|
119
|
+
desc "setup", "Do nothing; the lint engine ships with the gem"
|
|
116
120
|
def setup
|
|
117
|
-
|
|
118
|
-
lt = SimpleEnglish::LanguageTool.install(install.cache_dir)
|
|
119
|
-
return 2 unless lt
|
|
120
|
-
puts "LanguageTool #{SimpleEnglish::LanguageTool::LT_VERSION}: " \
|
|
121
|
-
"#{lt["downloaded"] ? "downloaded to" : "already present at"} #{lt["dir"]}"
|
|
122
|
-
unless install.java?
|
|
123
|
-
warn "error: #{install.java_message}"
|
|
124
|
-
return 2
|
|
125
|
-
end
|
|
126
|
-
puts "Java: #{install.java} (#{JAVA_SOURCES[install.java_source]})"
|
|
127
|
-
unless SimpleEnglish::LanguageTool.smoke(install)
|
|
128
|
-
warn "error: LanguageTool smoke test failed. The download may be corrupt. " \
|
|
129
|
-
"Delete #{lt["dir"]} and rerun `se setup`."
|
|
130
|
-
return 2
|
|
131
|
-
end
|
|
132
|
-
puts "Smoke test: passed"
|
|
133
|
-
puts
|
|
134
|
-
puts "se finds them automatically. Nothing to export."
|
|
121
|
+
puts "nothing to set up; the lint engine ships with the gem"
|
|
135
122
|
0
|
|
136
123
|
end
|
|
137
124
|
|
|
@@ -141,8 +141,8 @@ module SimpleEnglish
|
|
|
141
141
|
# Preflight everything the spawn needs: a missing prerequisite
|
|
142
142
|
# must fail fast with the real blocker named, not spawn a
|
|
143
143
|
# doomed child and wait out 90 s.
|
|
144
|
-
unless
|
|
145
|
-
warn
|
|
144
|
+
unless install.executable?
|
|
145
|
+
warn install.setup_error
|
|
146
146
|
return false
|
|
147
147
|
end
|
|
148
148
|
# One boot at a time: a concurrent lint that also found the
|
|
@@ -153,7 +153,7 @@ module SimpleEnglish
|
|
|
153
153
|
with_spawn_lock do
|
|
154
154
|
daemon = info
|
|
155
155
|
unless daemon
|
|
156
|
-
warn "se: daemon not running; starting it (first lint
|
|
156
|
+
warn "se: daemon not running; starting it (first lint may take a few seconds)..."
|
|
157
157
|
spawn_daemon
|
|
158
158
|
daemon = wait_for { info }
|
|
159
159
|
end
|
|
@@ -185,10 +185,9 @@ module SimpleEnglish
|
|
|
185
185
|
"(#{VERSION}). #{fix} Linting against it meanwhile."
|
|
186
186
|
end
|
|
187
187
|
|
|
188
|
-
# A per-user lock keyed by the port
|
|
189
|
-
#
|
|
190
|
-
#
|
|
191
|
-
# coordinate. flock releases when the block ends, even on
|
|
188
|
+
# A per-user lock keyed by the port: daemon ownership is scoped
|
|
189
|
+
# to the port, so concurrent lints coordinate across installs.
|
|
190
|
+
# flock releases when the block ends, even on
|
|
192
191
|
# failure.
|
|
193
192
|
def with_spawn_lock
|
|
194
193
|
dir = File.join(Dir.home, ".cache", "simple_english")
|