Skip to content

feat(core): create the Weir language#2357

Merged
elijah-potter merged 53 commits intoAutomattic:masterfrom
elijah-potter:nesl
Jan 12, 2026
Merged

feat(core): create the Weir language#2357
elijah-potter merged 53 commits intoAutomattic:masterfrom
elijah-potter:nesl

Conversation

@elijah-potter
Copy link
Copy Markdown
Collaborator

@elijah-potter elijah-potter commented Dec 17, 2025

Description

The Weir programming language is a DSL for defining linters for Harper. This is a draft PR because it will take time for me to finalize everything and write up all the associated documentation. I also want to embody my own policy.

See my recent blog posts for more deteils:

Specifically, I'd like to ping @hippietrail and @ccoVeille. I suspect they'll have thoughts on syntax and direction.

How Has this Been Tested?

Extensive unit and integration testing.

Checklist

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

@hippietrail
Copy link
Copy Markdown
Collaborator

You may or may not already be aware but I better point out just in case that the $ operator will result in both false positives and false negatives.

Languages have two kinds of affixes: Inflectional and derivational. Harper currently does not distinguish. So using $, like the DerivedFrom pattern will include all regular inflections of all parts of speech that apply to the word, but also none of the irregular ones.

So using it for click would cause it not just to match clicked, clicks, and clicking, but also click's and, hypothetically at least, words like clicker andreclick. Some words have prefixes and suffixes which build upon each other too. Some of these won't be correct when part of a compound or other type of expression.

And since irregular forms are not generated by affixation, if you used $ for something like give it wouldn't include gave or given.

We could of course just have more experienced contributors fix up any made by new contributors by turning them into full linters. But we should probably document it.

Now we could make this part of the affix system. By adding new annotation flags to distinguish inflectional suffixes (-s, -'s, -ing, -ed, -er when applied to an adjective, -est) from derivational suffixes (-ation, -er when applied to a verb). But this wouldn't address irregular verbs or irregular plurals.

That may be achievable via the irregular noun and verb modules, possibly with some extra functionality added, or by additions to the dictionary and annotation format, in which case we'd have to go beyond single character annotation flags as far as I can see.

Thoughts?

@elijah-potter
Copy link
Copy Markdown
Collaborator Author

There are two important things here.

First: The DerivedFrom expression does not properly match all inflections of the word. Specifically, it does not include the irregular forms. I believe your recent work makes this a solvable problem, right?

As for the right-click example. I believe that all of those derived from are still valid. Don't they all need to be hyphenated?

@hippietrail
Copy link
Copy Markdown
Collaborator

There are two important things here.

First: The DerivedFrom expression does not properly match all inflections of the word. Specifically, it does not include the irregular forms. I believe your recent work makes this a solvable problem, right?

You could try adding lookups into the irregular tables every time DerivedFrom is used. It sounds expensive to me but might not actually be. We could add an annotation flag for words with irregular inflection and only do the lookups when it's true. Or we could add one for verbs and one for plurals.

By the way there are other times inflected forms of words are split across multiple entries in the dictionary. They could be regular but have an ending-change pattern that's not handled by the affix code. The pattern where the last consonant is doubled is the most obvious but not the only one.

Another reason for splitting an entry is when an annotation flag didn't take into account the POS because the orthographic change is the same: "I bike->he bikes" / "one bike / two bikes". But this doesn't always hold: "one knife->two knives" / "this killer knifes his victims". So to prevent false entries in the FST dictionary we split the entry. This means not all will be connected by the 'derived' flag.

You can probably write a script to compare the full expanded FST dictionary to a curated wordlist that includes inflected forms.

As for the right-click example. I believe that all of those derived from are still valid. Don't they all need to be hyphenated?

That was a made up example but I don't think there's an accepted term "right-clicker". "right-clickable" seems sound but what about "right-unclickable"? That might not happen for "click" but is bound to happen for other words.

Copy link
Copy Markdown
Collaborator

@hippietrail hippietrail left a comment

Choose a reason for hiding this comment

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

English copyedit.

Comment thread packages/web/src/routes/docs/weir/+page.md
Comment thread packages/web/src/routes/docs/weir/+page.md Outdated
Comment thread packages/web/src/routes/docs/weir/+page.md Outdated
@elijah-potter elijah-potter marked this pull request as ready for review January 5, 2026 20:02
@elijah-potter
Copy link
Copy Markdown
Collaborator Author

That was a made up example but I don't think there's an accepted term "right-clicker". "right-clickable" seems sound but what about "right-unclickable"? That might not happen for "click" but is bound to happen for other words.

You're right that those phrases are incorrect. However, the rule only requires that they are hyphenated. Since I don't think it's necessarily wrong to hyphenate those phrases (even if we should mark them as wrong), I think we can overlook it.

@elijah-potter elijah-potter added this pull request to the merge queue Jan 12, 2026
Merged via the queue into Automattic:master with commit 46f4547 Jan 12, 2026
11 checks passed
@elijah-potter elijah-potter deleted the nesl branch January 12, 2026 18:14
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Jan 23, 2026
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [Automattic/harper/harper-ls](https://github.com/Automattic/harper) | minor | `v1.4.1` → `v1.5.1` |

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.5.1`](https://github.com/Automattic/harper/releases/tag/v1.5.1)

[Compare Source](Automattic/harper@v1.5.0...v1.5.1)

#### What's Changed

- fix(chrome-ext): problems with incorrect dialect selection and reversion by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2569](Automattic/harper#2569)

**Full Changelog**: <Automattic/harper@v1.5.0...v1.5.1>

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

[Compare Source](Automattic/harper@v1.4.1...v1.5.0)

#### What's Changed

- feat(cli): Support all potential md extensions by [@&#8203;Inhishonor](https://github.com/Inhishonor) in [#&#8203;2449](Automattic/harper#2449)
- fix: Allow exception `need to match` for `NeedToNoun` by [@&#8203;Greenheart](https://github.com/Greenheart) in [#&#8203;2448](Automattic/harper#2448)
- feat: initiatively→proactively / initially by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2432](Automattic/harper#2432)
- fix: propagate proper noun property to possessive forms by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2399](Automattic/harper#2399)
- chore: +vibe coding terms; add `/` annotation for phrasal verbs by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2452](Automattic/harper#2452)
- Add some political science terms to the dictionary by [@&#8203;Inhishonor](https://github.com/Inhishonor) in [#&#8203;2441](Automattic/harper#2441)
- feat: number agreement in this/these type(s) of thing(s) by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2400](Automattic/harper#2400)
- build(deps): bump serde\_json from 1.0.148 to 1.0.149 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2467](Automattic/harper#2467)
- fix(core): don't replace non-alphabetic characters when title-casing by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2454](Automattic/harper#2454)
- `harper-cli lint` keep overlapping lints switch & show lint priorities by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2435](Automattic/harper#2435)
- feat: imho→in my humble/honest opinion by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2468](Automattic/harper#2468)
- feat(core): create the Weir language by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2357](Automattic/harper#2357)
- chore: add "discoverable", "handoff" by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2457](Automattic/harper#2457)
- refactor(core): merge semantically identical funcs by [@&#8203;86xsk](https://github.com/86xsk) in [#&#8203;2458](Automattic/harper#2458)
- doc: clarify instructions and project status by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2453](Automattic/harper#2453)
- feat: Add get\_rel() to get a token relative to the end of a slice by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2461](Automattic/harper#2461)
- chore: add "different tact" to "change tacts" linter by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2469](Automattic/harper#2469)
- feat: create `harper-thesaurus` by [@&#8203;86xsk](https://github.com/86xsk) in [#&#8203;2085](Automattic/harper#2085)
- fix(core): MR getting flagged as 'misspelled' by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2476](Automattic/harper#2476)
- feat: Make the dialect indicator in the VS Code status bar clickable to change dialect by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2443](Automattic/harper#2443)
- fix(core): ignore apostrophes in the `OrthographicConsistency` rule by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2475](Automattic/harper#2475)
- fix(chrome-ext): highlights are mis-positioned in fixed elements by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2477](Automattic/harper#2477)
- feat: take a look to → take a look at by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2478](Automattic/harper#2478)
- feat: better of with → better off with by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2483](Automattic/harper#2483)
- doc(core): describe how Weir's replacement strategies work by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2480](Automattic/harper#2480)
- fix: don't flag "no two" etc. by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2489](Automattic/harper#2489)
- feat: very less → much less/far less/a lot less by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2484](Automattic/harper#2484)
- feat: more fast → faster etc. by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2263](Automattic/harper#2263)
- Hotkey by [@&#8203;LoganBrinsmead](https://github.com/LoganBrinsmead) in [#&#8203;2149](Automattic/harper#2149)
- feat: fix "I walks" / "he walk" etc. by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2333](Automattic/harper#2333)
- perf(test): improve test performance by [@&#8203;86xsk](https://github.com/86xsk) in [#&#8203;2473](Automattic/harper#2473)
- fix(core): panics in Weir by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2493](Automattic/harper#2493)
- fix(thesaurus): MacOS builds by using `ruzstd` by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2490](Automattic/harper#2490)
- build(deps): bump chrono from 0.4.42 to 0.4.43 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2535](Automattic/harper#2535)
- build(deps): bump thiserror from 2.0.17 to 2.0.18 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2533](Automattic/harper#2533)
- build(deps): bump indexmap from 2.12.1 to 2.13.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;2534](Automattic/harper#2534)
- Indian English tweaks by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2507](Automattic/harper#2507)
- fix(core): fix `AnA` false-positives by [@&#8203;86xsk](https://github.com/86xsk) in [#&#8203;2538](Automattic/harper#2538)
- feat: whom → who when subject of verb by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2528](Automattic/harper#2528)
- feat: obsess on → obsess over; obsessed on → obsessed with by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2537](Automattic/harper#2537)
- feat: vicious circle vs cycle by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2384](Automattic/harper#2384)
- fix(core): capitalization issue in `SpellCheck` by [@&#8203;86xsk](https://github.com/86xsk) in [#&#8203;2541](Automattic/harper#2541)
- feat: despite it is→ despite (it/its) being by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2542](Automattic/harper#2542)
- feat: detect browser dialect by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2485](Automattic/harper#2485)
- feat: to loose/too lose→too loose/to lose by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2543](Automattic/harper#2543)
- feat: allow any preposition, special plurals for both nouns by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2514](Automattic/harper#2514)
- fix(chrome-ext): Applying suggestions breaks cursor/keyboard in Draft.js and Slate editors by [@&#8203;draphy](https://github.com/draphy) in [#&#8203;2495](Automattic/harper#2495)
- feat(cli): chunk annotations by [@&#8203;86xsk](https://github.com/86xsk) in [#&#8203;2450](Automattic/harper#2450)
- fix(core): allow both a/an for "LED" in `AnA` by [@&#8203;86xsk](https://github.com/86xsk) in [#&#8203;2556](Automattic/harper#2556)
- refactor(core): simplify code by [@&#8203;86xsk](https://github.com/86xsk) in [#&#8203;2555](Automattic/harper#2555)
- feat(core): create a good number of new Weir rules by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2506](Automattic/harper#2506)
- feat(harper.js): expose the Typst parser in `harper.js` by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2554](Automattic/harper#2554)
- docs: fix errors in documentation by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2557](Automattic/harper#2557)
- fix(chrome-ext): Applying suggestions duplicates text in WhatsApp Web Lexical editor by [@&#8203;draphy](https://github.com/draphy) in [#&#8203;2563](Automattic/harper#2563)
- fix(harper-typst): condense contractions by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2558](Automattic/harper#2558)
- chore: dictionary curation by [@&#8203;hippietrail](https://github.com/hippietrail) in [#&#8203;2496](Automattic/harper#2496)
- chore: Update dictionary with new entries by [@&#8203;Inhishonor](https://github.com/Inhishonor) in [#&#8203;2540](Automattic/harper#2540)
- refactor(core): remove dependency on `lazy_static` by [@&#8203;86xsk](https://github.com/86xsk) in [#&#8203;2560](Automattic/harper#2560)
- feat(harper-typst): update to Typst `0.14.2` by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2566](Automattic/harper#2566)
- fix(chrome-ext): remove mention of Chrome Extension to avoid confusion for Firefox users by [@&#8203;elijah-potter](https://github.com/elijah-potter) in [#&#8203;2567](Automattic/harper#2567)

#### New Contributors

- [@&#8203;Inhishonor](https://github.com/Inhishonor) made their first contribution in [#&#8203;2449](Automattic/harper#2449)
- [@&#8203;Greenheart](https://github.com/Greenheart) made their first contribution in [#&#8203;2448](Automattic/harper#2448)
- [@&#8203;draphy](https://github.com/draphy) made their first contribution in [#&#8203;2495](Automattic/harper#2495)

**Full Changelog**: <Automattic/harper@v1.4.1...v1.5.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:eyJjcmVhdGVkSW5WZXIiOiI0Mi44OC4yIiwidXBkYXRlZEluVmVyIjoiNDIuODguMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90IiwiYXV0b21hdGlvbjpib3QtYXV0aG9yZWQiLCJkZXBlbmRlbmN5LXR5cGU6Om1pbm9yIl19-->
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