Skip to content

Irregular verbs#2285

Merged
elijah-potter merged 8 commits intoAutomattic:masterfrom
hippietrail:irregular-verbs
Dec 8, 2025
Merged

Irregular verbs#2285
elijah-potter merged 8 commits intoAutomattic:masterfrom
hippietrail:irregular-verbs

Conversation

@hippietrail
Copy link
Collaborator

Issues

N/A

Description

  • Provides a module that handles irregular verbs.
  • Adds a JSON file listing known irregular verbs.
  • JSON file supports comments as strings to note why certain words are omitted, etc.
  • JSON loading code is copied as closely as possible from the way that dictionary.dict and annotations.json are loaded.
  • Comes with a converted SimplePastToPastParticiple linter that uses it.
  • Will also be used with the in-progress WillNonLemma (feat: will ran → will run / ran work in progress #2268) and ExtraneousDidPast linters.
  • Will provide a model for implementing a similar module for irregular noun plurals.

How Has This Been Tested?

Unit tests are included for the one API so far needed.

Checklist

  • I have performed a self-review of my own code
  • I have added tests to cover my changes

Copy link
Collaborator

@elijah-potter elijah-potter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, I love this refactor. I just have a few comments related to discoverability. Thanks!

@@ -0,0 +1,120 @@
use lazy_static::lazy_static;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This module is not directly related to linting. Could we instead move it next to the dictionary or perhaps simply higher up in the hierarchy?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the dictionary/annotation/metadata logic seems to be in /src/ with some in /spell/. Since the latter would definitely be wrong I moved irregular_verbs.rs to /src/ - and it's now joined by irregular_nouns.rs

@@ -0,0 +1,127 @@
[
"// comments can appear in the line before an entry",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I adore the idea of having a dedicating file for this, similar to the dictionary. I'd like to centralize all data files, though. Would you mind moving this next to the dictionary.dict?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. And there's also irregular_nouns.json now.

Copy link
Collaborator

@elijah-potter elijah-potter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is so close. Love the addition of the noun stuff.

(*NOUNS).clone()
}

pub fn get_plural_for_singular(&self, singular: &str) -> Option<&str> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect that we'll want to eventually have versions of these plugins that accept and return char arrays. I think we're fine for now, but it's something to think about.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I've been thinking of various things that can be added but adding when they're needed seems pragmatic.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I've been thinking of various things that can be added but adding when they're needed seems pragmatic.

Ok(Self { verbs })
}

pub fn get() -> Arc<Self> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we name this function similarly to the curated dictionary's equivalent?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did start with the same curated() which I didn't think made sense for this. But then again they are actually curated!

pub mod expr;
mod fat_token;
mod ignored_lints;
pub mod irregular_nouns;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just export the structs directly. Having the extra layer of indirection is redundant.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just export the structs directly. Having the extra layer of indirection is redundant.

At first I wasn't sure what this meant, and neither was the LLM. But have a look - I think I got it how you want it.

Copy link
Collaborator

@elijah-potter elijah-potter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Thanks!

@elijah-potter elijah-potter added this pull request to the merge queue Dec 8, 2025
Merged via the queue into Automattic:master with commit 66f3e84 Dec 8, 2025
11 checks passed
@hippietrail hippietrail deleted the irregular-verbs branch December 8, 2025 17:19
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Dec 12, 2025
⚠️ **CAUTION: this is a major update, indicating a breaking change!** ⚠️

This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [Automattic/harper/harper-ls](https://github.com/Automattic/harper) | major | `v0.73.0` -> `v1.2.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>Automattic/harper (Automattic/harper/harper-ls)</summary>

### [`v1.2.0`](https://github.com/Automattic/harper/releases/tag/v1.2.0)

[Compare Source](Automattic/harper@v1.1.0...v1.2.0)

#### What's Changed

- feat(core): many new rules by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2292](Automattic/harper#2292)
- fix: flag "piece of advise" by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2266](Automattic/harper#2266)
- fix(web): problems with the title casing page by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2293](Automattic/harper#2293)
- feat: implement [#&#8203;1135](Automattic/harper#1135) missing "be" by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2296](Automattic/harper#2296)
- fix(core): add `canonicalize` to the dictionary by [@&#8203;claydugo](https://github.com/claydugo) in [#&#8203;2294](Automattic/harper#2294)
- feat: implement [#&#8203;1036](Automattic/harper#1036) join prefix to word by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2299](Automattic/harper#2299)
- feat(core): create rule to title-case headings by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2297](Automattic/harper#2297)
- build(deps): bump unicode-script from 0.5.7 to 0.5.8 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2305](Automattic/harper#2305)
- build(deps): bump criterion from 0.8.0 to 0.8.1 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2306](Automattic/harper#2306)
- build(deps): bump tree-sitter-bash from 0.25.0 to 0.25.1 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2304](Automattic/harper#2304)
- fix(ls): prevent panic when workspace/configuration is unsupported by [@&#8203;mcecode](https://github.com/mcecode) in [#&#8203;2309](Automattic/harper#2309)
- Irregular verbs by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2285](Automattic/harper#2285)
- Fascinated about by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2319](Automattic/harper#2319)
- feat(obsidian): add button to disable rules from within popup by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2300](Automattic/harper#2300)
- chore: add weigh/weight to noun/verb confusion by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2315](Automattic/harper#2315)
- refactor: made a new `lint_group` from two mass noun linters by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2290](Automattic/harper#2290)
- feat: typo every → ever by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2311](Automattic/harper#2311)
- doc(core): clarify difference between chunker NPs and pattern NPs by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2312](Automattic/harper#2312)
- feat: PIN number → PIN / personal identification number etc. by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2318](Automattic/harper#2318)
- feat: brandish→brand by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2325](Automattic/harper#2325)
- feat: wreck havoc→wreak havoc by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2321](Automattic/harper#2321)
- fix(chrome-ext): text in dark mode not legible by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2326](Automattic/harper#2326)
- feat: adding prefixes to dictionary by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2212](Automattic/harper#2212)

**Full Changelog**: <Automattic/harper@v1.1.0...v1.2.0>

### [`v1.1.0`](https://github.com/Automattic/harper/releases/tag/v1.1.0)

[Compare Source](Automattic/harper@v1.0.0...v1.1.0)

#### What's Changed

- build(deps): bump tracing from 0.1.41 to 0.1.43 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2271](Automattic/harper#2271)
- build(deps): bump indexmap from 2.12.0 to 2.12.1 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2274](Automattic/harper#2274)
- build(deps): bump criterion from 0.7.0 to 0.8.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2272](Automattic/harper#2272)
- refactor: upgrade `Expatriate` to `phrase_set_corrections` by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2265](Automattic/harper#2265)
- build(deps): bump tracing-subscriber from 0.3.20 to 0.3.22 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2273](Automattic/harper#2273)
- fix(dict): update webpack entry by [@&#8203;mcecode](https://github.com/mcecode) in [#&#8203;2278](Automattic/harper#2278)
- fix(core): address edge cases in `title_case` module by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2284](Automattic/harper#2284)
- fix(chrome-ext): return focus to source element when `SuggestionBox` is closed by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2282](Automattic/harper#2282)
- fix(core): ignore inflections of `be` in compound noun rule by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2281](Automattic/harper#2281)
- fix(core): add `bypassable` to the dictionary by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2280](Automattic/harper#2280)
- feat: copywritten → copyrighted by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2276](Automattic/harper#2276)
- feat: add `chroot` to dictionary by [@&#8203;jvoisin](https://github.com/jvoisin) in [#&#8203;2270](Automattic/harper#2270)
- refactor: new `SequenceExpr` and `CharStringExt` methods by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2269](Automattic/harper#2269)
- feat(ls): add `octo` as a supported filetype by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2279](Automattic/harper#2279)
- fix(core): issues with spell check by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2288](Automattic/harper#2288)
- feat: wish x can → wish x could by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2291](Automattic/harper#2291)
- fix(core): ensure `news` isn't corrected to `news` by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2289](Automattic/harper#2289)
- fix(core): fix problems with the `NeedToNoun` rule by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2287](Automattic/harper#2287)

**Full Changelog**: <Automattic/harper@v1.0.0...v1.1.0>

### [`v1.0.0`](https://github.com/Automattic/harper/releases/tag/v1.0.0)

[Compare Source](Automattic/harper@v0.73.0...v1.0.0)

### Harper Turns 1.0 Today

Today, we published [Harper's `1.0.0` release](https://github.com/Automattic/harper/releases/tag/v1.0.0). It's a huge milestone, and in this post I'd like to discuss why it took so long, why we're doing it now, and what's next for the project.

#### A Round of Applause, Please

As I mentioned: This is a huge step for the project. Before I say anything else, I want to take a moment to appreciate the collective work of our many contributors. It has taken many iterations to get to where we are today, and it wouldn't be possible without the community's effort and feedback.

<figure class="wp-block-image"><img src="https://contrib.rocks/image?repo=automattic/harper" alt=""/></figure>

#### Why Now?

Until today, I've kept Harper in a pre-1.0 state for one reason: I wanted to move fast. More specifically, I wanted the freedom to build and break things as many times as I needed to. I knew that it would take many cycles of building and rebuilding arrive at a robust system that addresses the people's need for a private writing tool. I believe that building something good can often mean taking the bad parts out. Once a project is "1.0", it becomes much harder to remove things. Naturally, that pushed me to hold off on "going 1.0".

Of course, that didn't stop us from getting the software into the hands of users. Today, tens of thousands of people benefit from Harper's fast and private grammar checking in Chrome, Obsidian, VS Code, and Neovim (among many others). We've racked up hundreds of thousands of downloads before ever slapping anything other than zero before the first decimal point of our version number.

I'm sure your thinking: "Elijah! Get to the point!" Fine. The reason we're doing this now, rather than earlier or later, is because our priorities have just recently changed.

For one, Harper's API has been rock-solid for a few months now, which means we can safely say that our need to move fast in that area has diminished. The opportunity cost of abiding by a stable API has gone down.

Secondly, I've been hearing progressively more interest from potential contributors and consumers who want to put Harper directly into their own apps or services. They have the desire to help make Harper more widespread, but they can't commit to it unless Harper commits to a stable API. That's what we're doing today.

I can imagine a future where Harper is natively integrated everywhere: learning management systems, document editors, messaging platforms, or even operating systems. But great things take time. Today, we're taking a huge step in setting Harper up for the long-term.

#### What Do I Need to Know?

As an end-user, not much changes. From here on out, we'll be pushing quality-of-life tweaks and bugfixes at a faster rate, all while improving Harper's capabilities across the board.

As a contributor, the patch review process might get a little bit more strict. We'll be focusing more on improving the quality of our code, rather than the amount. If your MRs are likely to result in a breaking change, expect copious notes and possible delays before we hit "merge".

As an integrator, you win more than anyone. If you'd like to include Harper in your application, let us know and we'll do our best to make it easy for you. Take a look at [our versioning policy](https://writewithharper.com/docs/about#Versioning-Policy) if that sort of thing gives you peace of mind.

#### Where Can I Get Further Updates?

That depends on the level of verbosity your interested in. For those who want to know about everything I'm currently working, subscribe to [my blog](https://elijahpotter.dev/). For everyone else, our [patch notes in GitHub](https://github.com/automattic/harper/releases) should suffice.

#### What's Changed

Now that all of that has been said. Let's get back to our regularly schedule programming.

- build(deps): bump open from 5.3.2 to 5.3.3 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2235](Automattic/harper#2235)
- refactor: improvements to `ProgressiveNeedsBe` by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2232](Automattic/harper#2232)
- feat: filter out unknown `only` and `ignore` rules only once by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2231](Automattic/harper#2231)
- build(deps): bump hashbrown from 0.16.0 to 0.16.1 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2237](Automattic/harper#2237)
- feat: create component library + use in relevant places by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2229](Automattic/harper#2229)
- build(deps): bump clap from 4.5.51 to 4.5.53 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2236](Automattic/harper#2236)
- fix(chrome-ext): ignore inline markup in `contenteditable` fields by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2242](Automattic/harper#2242)
- feat: add technical words to dictionary by [@&#8203;rauletaveras](https://github.com/rauletaveras) in [#&#8203;2219](Automattic/harper#2219)
- fix: 15 `ExprLinter`s in `lint_group.rs` wrongly use `insert_struct_rule!` by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2249](Automattic/harper#2249)
- test: [#&#8203;2233](Automattic/harper#2233) and [#&#8203;1097](Automattic/harper#1097) by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2239](Automattic/harper#2239)
- test(core): check that [#&#8203;1772](Automattic/harper#1772) is resolved by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2247](Automattic/harper#2247)
- feat(core): `FindFine` by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2248](Automattic/harper#2248)
- feat: await for → await / wait for by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2250](Automattic/harper#2250)
- feat(cli): use Rayon when linting many items by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2244](Automattic/harper#2244)
- fix(ls): use `code` key in diagnostics by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2254](Automattic/harper#2254)
- fix(core): edge case in dictionary by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2255](Automattic/harper#2255)
- fix: don't flag 'every day free' by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2260](Automattic/harper#2260)
- feat: allow `ExprLinter` to work on sentences as well as chunks by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2165](Automattic/harper#2165)
- feat: per say / per-se → per se by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2258](Automattic/harper#2258)
- refactor: most `pub use` lines in `mod.rs` not needed by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2259](Automattic/harper#2259)
- docs: define a versioning policy by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2257](Automattic/harper#2257)
- feat(core): create rule to catch `Me and <PRON>` by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2245](Automattic/harper#2245)
- refactor(core): remove implementation details from public API by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2256](Automattic/harper#2256)
- feat(core): create more specialized rule for [#&#8203;2144](Automattic/harper#2144) by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2253](Automattic/harper#2253)

#### New Contributors

- [@&#8203;rauletaveras](https://github.com/rauletaveras) made their first contribution in [#&#8203;2219](Automattic/harper#2219)

**Full Changelog**: <Automattic/harper@v0.73.0...v1.0.0>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi4yNi4zIiwidXBkYXRlZEluVmVyIjoiNDIuNDQuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90Il19-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants