Top Related Projects
:pencil: A markup-aware linter for prose built with speed and extensibility in mind.
Naive linter for English prose
Catch insensitive, inconsiderate writing
textlint is the pluggable linter for natural language text.
Quick Overview
Proselint is a linter for prose, designed to help writers improve their writing style and catch common errors. It's a command-line tool and Python library that analyzes text and provides suggestions for improvement based on various rules and best practices in writing.
Pros
- Comprehensive set of rules covering various aspects of writing, including style, grammar, and consistency
- Customizable and extensible, allowing users to add their own rules or disable existing ones
- Can be integrated into various text editors and writing workflows
- Supports multiple languages and writing styles
Cons
- May produce false positives or unnecessary suggestions in certain contexts
- Some users might find the default ruleset too strict or opinionated
- Limited support for non-English languages compared to English
- Requires Python installation, which might be a barrier for non-technical users
Code Examples
- Basic usage as a Python library:
import proselint
text = "The quick brown fox jumps over the lazy dog."
suggestions = proselint.tools.lint(text)
for suggestion in suggestions:
print(f"Line {suggestion['line']}: {suggestion['message']}")
- Checking a specific rule:
from proselint.tools import lint_text
text = "I'm very unique."
errors = lint_text(text, checks=['redundancy.very_unique'])
for error in errors:
print(f"{error['check']}: {error['message']}")
- Customizing the linter:
from proselint.config import default_config
custom_config = default_config.copy()
custom_config['checks']['typography.diacritical_marks'] = False
text = "The cafe is closed."
errors = proselint.tools.lint(text, config=custom_config)
Getting Started
To use Proselint, first install it using pip:
pip install proselint
Then, you can use it as a command-line tool:
proselint your_text_file.txt
Or import it in your Python script:
import proselint
text = "Your text here."
suggestions = proselint.tools.lint(text)
for suggestion in suggestions:
print(f"{suggestion['check']}: {suggestion['message']}")
Competitor Comparisons
:pencil: A markup-aware linter for prose built with speed and extensibility in mind.
Pros of Vale
- More customizable with user-defined rules and styles
- Supports multiple markup formats (Markdown, AsciiDoc, reStructuredText)
- Actively maintained with frequent updates
Cons of Vale
- Steeper learning curve due to more complex configuration
- Requires more setup and configuration compared to Proselint
- May be overkill for simple writing tasks
Code Comparison
Vale configuration example:
StylesPath = styles
MinAlertLevel = suggestion
[*.md]
BasedOnStyles = Vale, proselint
Proselint usage example:
from proselint import tools
suggestions = tools.lint("Your text goes here")
Key Differences
- Vale is more flexible and extensible, while Proselint is simpler to use out-of-the-box
- Vale supports multiple markup formats, whereas Proselint focuses primarily on plain text
- Vale allows for custom rule creation, while Proselint has a fixed set of rules
- Vale requires more configuration, but offers greater customization options
- Proselint is Python-based, while Vale is written in Go
Both tools aim to improve writing quality, but Vale offers more advanced features at the cost of increased complexity, while Proselint provides a simpler, more straightforward approach to prose linting.
Naive linter for English prose
Pros of write-good
- Lightweight and easy to integrate into various workflows
- Supports multiple languages (English, German, Spanish, etc.)
- Customizable rules and easy to extend with plugins
Cons of write-good
- Less comprehensive in its analysis compared to proselint
- May produce more false positives due to its simplistic approach
- Limited documentation and community support
Code Comparison
write-good:
var writeGood = require('write-good');
var suggestions = writeGood('So the cat was stolen.');
console.log(suggestions);
proselint:
import proselint
text = "So the cat was stolen."
suggestions = proselint.tools.lint(text)
print(suggestions)
Summary
write-good is a lightweight, multi-language linter that's easy to integrate and customize. However, it may lack the depth of analysis provided by proselint. proselint offers more comprehensive checks but is primarily focused on English and may be more complex to set up. The choice between the two depends on the specific needs of the project, with write-good being more suitable for quick, basic checks across multiple languages, while proselint is better for in-depth analysis of English text.
Catch insensitive, inconsiderate writing
Pros of alex
- More actively maintained with frequent updates
- Broader focus on inclusive language beyond just writing style
- Integrates well with various text editors and CI/CD pipelines
Cons of alex
- Less comprehensive in terms of general writing advice
- May produce more false positives due to its focus on inclusive language
- Requires more configuration to customize rules
Code comparison
alex:
const alex = require('alex');
console.log(alex('He is a businessman.').messages);
proselint:
from proselint import tools
text = "He is a businessman."
errors = tools.lint(text)
print(errors)
Key differences
- alex is written in JavaScript, while proselint is in Python
- alex focuses more on inclusive language, while proselint covers a wider range of writing issues
- alex has a larger community and more frequent updates
- proselint offers more detailed explanations for its suggestions
- alex is easier to integrate into modern web development workflows
Both tools aim to improve writing quality, but they approach the task from different angles. alex is better suited for projects prioritizing inclusive language, while proselint may be preferable for general writing improvement.
textlint is the pluggable linter for natural language text.
Pros of textlint
- Highly customizable with a plugin system for creating and using custom rules
- Supports multiple languages and file formats (Markdown, plain text, HTML, etc.)
- Active development and large community with numerous plugins available
Cons of textlint
- Steeper learning curve due to its flexibility and configuration options
- Requires more setup and configuration compared to proselint's out-of-the-box experience
- May have higher resource usage for complex rulesets
Code Comparison
textlint configuration example:
{
"rules": {
"no-todo": true,
"max-comma": { "max": 3 },
"spellcheck-tech-word": true
}
}
proselint usage example:
from proselint import tools
errors = tools.lint("Your text goes here")
for error in errors:
print(error)
Both tools aim to improve writing quality, but textlint offers more flexibility and customization at the cost of complexity, while proselint provides a simpler, more focused approach to prose linting. textlint's plugin system allows for extensive customization, making it suitable for various writing styles and languages. proselint, on the other hand, focuses primarily on English prose and offers a more opinionated set of rules out of the box.
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Writing is notoriously hard, even for the best writers, and it's not for lack of good advice â a tremendous amount of knowledge about the craft is strewn across usage guides, dictionaries, technical manuals, essays, pamphlets, websites, and the hearts and minds of great authors and editors. But poring over Strunk & White hardly makes one a better writer â it turns you into neither Strunk nor White. And nobody has the capacity to apply all the advice from Garnerâs Modern English Usage, an 1100-page usage guide, to everything they write. In fact, the whole notion that one becomes a better writer by reading advice on writing rests on untenable assumptions about learning and memory. The traditional formats of knowledge about writing are thus essentially inert, waiting to be transformed.
We devised a simple solution: proselint, a linter for English prose. A linter
is a computer program that, akin to a spell checker, scans through a file and
detects issues â like how a real lint roller helps you get unwanted lint off of
your shirt.
proselint places the world's greatest writers and editors by your side, where
they whisper suggestions on how to improve your prose. Youâll be guided by
advice inspired by Bryan Garner, David Foster Wallace, Chuck Palahniuk, Steve
Pinker, Mary Norris, Mark Twain, Elmore Leonard, George Orwell, Matthew
Butterick, William Strunk, Elwyn White, Philip Corbett, Ernest Gowers, and the
editorial staff of the worldâs finest literary magazines and newspapers, among
others. Our goal is to aggregate knowledge about best practices in writing and
to make that knowledge immediately accessible to all authors in the form of a
linter for prose; all in a neat command-line utility that you can integrate into
other tools, scripts, and workflows.
Installation
To get this up and running, install it using pip.
pip install proselint
Fedora
sudo dnf install proselint
Debian
sudo apt install python3-proselint
Ubuntu
sudo add-apt-repository universe
sudo apt install python3-proselint
Nix
proselint is packaged by nixpkgs.
pre-commit
To use proselint with pre-commit (by Andy Airey), point its config at this repository:
repos:
- repo: https://github.com/amperser/proselint
rev: v0.16.0
hooks:
- id: proselint
Be sure to change rev to use the desired proselint git tag or revision.
Declarative
environment.systemPackages = [pkgs.proselint];
Imperative
nix profile install nixpkgs#proselint
Plugins for other software
proselint is available on:
- A demo editor
- Emacs via Flycheck or via Flymake
- Vim via ALE or Syntastic (thanks to @lcd047, @Carreau, and Daniel M. Capella)
- Neovim via none-ls.nvim (none-ls has diagnostics and code actions for proselint)
- MegaLinter
The following plugins are also available, but they are archived or unmaintained:
- Atom Editor (thanks to Clay Miller).
- coala (thanks to the coala Development Group)
- Danger (thanks to David Grandinetti and Orta Therox)
- IntelliJ (by Victor Kropp)
- Neovim via null-ls (null-ls has diagnostics and code actions for proselint)
- Phabricator's
arcCLI (thanks to Jeff Verkoeyen) - Sublime Text
- Visual Studio Code (thanks to Patryk Peszko)
Usage
Suppose you have a document text.md with the following text:
John is very unique.
You can run proselint over the document using the command line:
proselint check text.md
This prints a list of suggestions to stdout, one per line. Each suggestion is of the form:
file:<line>:<column>: <check_name>: <message>
For example,
text.md:1:9: uncomparables: Comparison of an uncomparable: 'very unique' is not comparable.
The command-line utility can also print suggestions in JSON using the
--output-format json option. In this case, the output is considerably richer,
following our stable wire schema.
{
"result": {
"file:///path/to/text.md": {
"diagnostics": [
{
// Name of the check that output this suggestion.
"check_path": "uncomparables",
// Message to describe the suggestion
"message": "Comparison of an uncomparable: 'very unique' is not comparable.",
// Line and column where the error begins in the source
"pos": [1, 9],
// Absolute start and end of the error in the source
"span": [9, 20],
// Suggested replacements for the content, if applicable
"replacements": null,
}
]
}
}
}
To run the linter as part of another Python program, you can use the LintFile
class in proselint.tools. This requires CheckRegistry to be populated.
from proselint.checks import __register__
from proselint.registry import CheckRegistry
from proselint.tools import LintFile
CheckRegistry().register_many(__register__)
suggestions = LintFile("source-name", "This sentence is very unique").lint()
This will return a list of suggestions:
[LintResult(
check_result=CheckResult(
check_path='uncomparables',
message="Comparison of an uncomparable: 'very unique' is not comparable.",
span=(18, 29),
replacements=None,
),
pos=(1, 18),
)]
Checks
You can disable any of the checks by modifying
$XDG_CONFIG_HOME/proselint/config.json. If $XDG_CONFIG_HOME is not set or
empty, ~/.config/proselint/config.json will be used. Additionally, for
compatibility reasons, the legacy configurations ~/.proselintrc and
$XDG_CONFIG_HOME/proselint/config will be checked if
$XDG_CONFIG_HOME/proselint/config.json does not exist. Check selection is
granular at any level, illustrated in the following example:
{
"checks": {
"typography": true,
"typography.symbols": false,
"typography.symbols.curly_quotes": true,
"typography.punctuation.hyperbole": false,
}
}
This configuration would enable all checks in the typography module, excluding
typography.punctuation.hyperbole and those in typography.symbols, but
preserving typography.symbols.curly_quotes. Using this system allows you to
concisely and precisely select checks at an individual level.
| ID | Description |
|---|---|
annotations | Catch annotations left in the text |
archaism | Avoid archaic forms |
cliches.hell | Avoid a common cliché regarding hell |
cliches.misc | Avoid clichés |
dates_times.am_pm | Format the time of day correctly |
dates_times.dates | Format dates appropriately |
hedging | Avoid undermining yourself with uncertainty |
industrial_language.airlinese | Avoid jargon of the airline industry |
industrial_language.bureaucratese | Avoid bureaucratese |
industrial_language.chatspeak | Avoid lolling and other chatspeak |
industrial_language.commercialese | Avoid jargon of the commercial world |
industrial_language.corporate_speak | Avoid corporate buzzwords |
industrial_language.jargon | Avoid miscellaneous jargon |
lexical_illusions | Avoid repeating words or phrases |
malapropisms | Avoid common malapropisms |
misc.apologizing | Be confident and avoid excessive apologizing |
misc.back_formations | Avoid redundant backformations |
misc.but | Do not start a paragraph with "But..." |
misc.capitalization | Capitalize only what ought to be capitalized |
misc.composition | Adhere to principles of composition |
misc.currency | Avoid redundant currency symbols |
misc.debased | Avoid debased language |
misc.false_plurals | Avoid false plurals |
misc.greylist | Avoid greylisted terms |
misc.illogic | Avoid illogical forms |
misc.inferior_superior | Superior to, not than |
misc.institution_name | Use the correct names of institutions |
misc.latin | Avoid overuse of Latin phrases |
misc.many_a | Use singular forms with "many a" |
misc.metadiscourse | Avoid discussing the discussion |
misc.narcissism | Talk about the subject, not its study |
misc.not_guilty | Avoid "not guilty beyond a reasonable doubt" |
misc.phrasal_adjectives | Hyphenate phrasal adjectives correctly |
misc.preferred_forms | Use the preferred forms of terms |
misc.pretension | Do not be pretentious |
misc.professions | Use the right names for jobs |
misc.scare_quotes | Do not misuse scare quotes |
misc.suddenly | Retain suddenness by not using "suddenly" |
misc.tense_present | Follow advice from Tense Present |
misc.waxed | Use adjectives for waxed, as in "wax poetic" |
misc.whence | Avoid redundancy with "whence" |
mixed_metaphors | Do not mix metaphors |
mondegreens | Avoid mondegreens |
needless_variants | Use preferred forms over uncommon variants |
nonwords | Do not use nonwords |
oxymorons | Avoid oxymorons |
psychology | Avoid misusing psychological terms |
redundancy.misc | Avoid redundancy in phrases |
redundancy.ras_syndrome | Avoid redundancy in acronyms |
restricted.elementary | Restrict writing to terms from elementary school |
restricted.top1000 | Restrict writing to the top 1000 words by usage |
skunked_terms | Avoid using skunked terms |
social_awareness.lgbtq | Be aware of LGBTQ+ terminology |
social_awareness.nword | Take responsibility for use of "the n-word" |
social_awareness.sexism | Be aware of sexist language |
spelling.able_atable | Use the correct form of -able and -atable |
spelling.able_ible | Use the correct form of -able and -ible |
spelling.ally_ly | Use the correct form of -ally and -ly |
spelling.ance_ence | Use the correect form of -ance and -ence |
spelling.athletes | Spell the names of athletes correctly |
spelling.consistency | Be consistent in spelling |
spelling.ely_ly | Use the correct form of -ely and -ly |
spelling.em_im_en_in | Use the correct form of -em, -im, -en, and -in |
spelling.er_or | Use the correct form of -er and -or |
spelling.in_un | Use the correct form of -in and -un |
spelling.misc | Spell miscellaneous terms correctly |
spelling.ve_of | Use the correct form of -ve and -of |
terms.animal_adjectives | Use the right adjectives for likening animals |
terms.denizen_labels | Use the right names for denizens |
terms.eponymous_adjectives | Use the right names for likening people |
terms.venery | Use the right names for groups of animals |
typography.diacritical_marks | Use diacritical marks |
typography.punctuation | Use punctuation correctly |
typography.symbols | Use symbols correctly |
uncomparables | Do not compare uncomparables |
weasel_words | Avoid weasel words |
Contributing
Interested in contributing to proselint? Great â there are plenty of ways you
can help. Check out our contributing guidelines, where we describe how you
can help us build proselint into the greatest writing tool in the world.
Support
If you run into a problem, please open an issue.
Running Tests
Automated tests are included in the tests directory. To run these
tests locally, you can use pytest via poe test.
License
The project is licensed under the BSD license.
Top Related Projects
:pencil: A markup-aware linter for prose built with speed and extensibility in mind.
Naive linter for English prose
Catch insensitive, inconsiderate writing
textlint is the pluggable linter for natural language text.
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot