Python JavaScript HTML CSS Shell Emacs Lisp
Latest commit f53c77b Feb 25, 2017 @jwilk jwilk committed with suchow Fix typo (#680)
Permalink
Failed to load latest commit information.
corpora Fix typos Jun 23, 2016
plugins The Vim plugin has been included in syntastic 3.8.0. (#622) Oct 11, 2016
proselint Add verbose flag to broken links regexp (#671) Feb 25, 2017
research/comparison Fix typo (#680) Feb 25, 2017
scripts Tweak demo insertion script Oct 7, 2015
site correct misspellings (#670) Feb 20, 2017
tests Fix cache-clearing issue #624 (#655) Feb 23, 2017
tmp Add temporary folder for linted text Sep 28, 2015
.codeclimate.yml Add CodeClimate config files Apr 5, 2016
.coveralls.yml Update Coveralls.io repo token Sep 28, 2015
.csslintrc Add CodeClimate config files Apr 5, 2016
.eslintignore Add CodeClimate config files Apr 5, 2016
.eslintrc Add CodeClimate config files Apr 5, 2016
.gitignore Ignore link-checker files Oct 7, 2015
.travis.yml Move Danger to Travis 'script' section (#590) Aug 17, 2016
CHANGELOG.md Release version 0.8.0 (#678) Feb 23, 2017
CONTRIBUTING.md Fix contrib.md typo (#616) Sep 16, 2016
Dangerfile Ensure a clean commit history (#592) Aug 17, 2016
Gemfile Add Danger to Travis Jul 25, 2016
LICENSE.md Tweak license formatting Sep 28, 2015
MANIFEST.in Add CHANGELOG.md to MANIFEST.in for sdist (#627) Nov 8, 2016
Procfile Create an email autoresponder Sep 28, 2015
README.md Add usage example on calling linter from another program (#675) Feb 21, 2017
app.py Move linting to tools module Apr 4, 2016
appveyor.yml Use AppVeyor for Windows-based CI Apr 3, 2016
clock.py Improve autoresponder signature Oct 7, 2015
favicon.png Update favicon Sep 28, 2015
logo.png Add logo to README Sep 28, 2015
requirements.txt Fix cache-clearing issue #624 (#655) Feb 23, 2017
run_ci_checks.sh Add a script to run checks that are run in CI. Jul 17, 2016
setup.cfg Release version 0.8.0 (#678) Feb 23, 2017
setup.py fixup for pypi so demo will work Sep 30, 2015
worker.py Do some extra 2/3 futurizing Sep 28, 2015

README.md

proselint logo

Build Status Build status Code Climate Coverage Status Dependency Status License

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 American Usage, a 975-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, like a spell checker, scans through a document and analyzes it.)

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, E.B. 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.

proselint is a command-line utility that can be integrated into existing tools.

Installation

To get this up and running, install it using pip:

pip install proselint

Plugins for other software

proselint is available on:

Usage

Suppose you had a document text.md with the following text:

John is very unique.

You can run proselint over the document using the command line:

❯ proselint text.md

This prints a list of suggestions to stdout, one per line. Each suggestion has the form:

text.md:<line>:<column>: <check_name> <message>

For example,

text.md:0:10: wallace.uncomparables Comparison of an uncomparable: 'unique' cannot be compared.

The command-line utility can also print suggestions in JSON using the --json flag. In this case, the output is considerably richer:

{
    // Type of check that output this suggestion.
    check: "wallace.uncomparables",

    // Message to describe the suggestion.
    message: "Comparison of an uncomparable: 'unique' cannot be compared.",

    // The person or organization giving the suggestion.
    source: "David Foster Wallace"

    // URL pointing to the source material.
    source_url: "http://www.telegraph.co.uk/a/9715551"

    // Line where the error starts.
    line: 0,

    // Column where the error starts.
    column: 10,

    // Index in the text where the error starts.
    start: 10,

    // Index in the text where the error ends.
    end: 21,

    // start - end
    extent: 11,

    // How important is this? Can be "suggestion", "warning", or "error".
    severity: "warning",

    // Possible replacements.
    replacements: [
        {
            value: "unique"
        }
    ]
}

To run the linter as part of another program, you can use the lint function in proselint.tools:

import proselint

suggestions = proselint.tools.lint("This sentence is very unique")

This will return a list of suggestions:

[('weasel_words.very', "Substitute 'damn' every time you're inclined to write 'very;' your editor will delete it and the writing will be just as it should be.", 0, 17, 17, 22, 5, 'warning', None), ('uncomparables.misc', "Comparison of an uncomparable: 'very unique.' is not comparable.", 0, 17, 17, 29, 12, 'warning', None)]

Checks

You can disable any of the checks by modifying ~/.proselintrc:

{
  "checks": {
    "typography.diacritical_marks": false
  }
}
ID Description
airlinese.misc Avoiding jargon of the airline industry
annotations.misc Catching annotations left in the text
archaism.misc Avoiding archaic forms
cliches.hell Avoiding a common cliché
cliches.misc Avoiding clichés
consistency.spacing Consistent sentence spacing
consistency.spelling Consistent spelling
corporate_speak.misc Avoiding corporate buzzwords
cursing.filth Words to avoid
cursing.nfl Avoiding words banned by the NFL
dates_times.am_pm Using the right form for the time of day
dates_times.dates Stylish formatting of dates
hedging.misc Not hedging
hyperbole.misc Not being hyperbolic
jargon.misc Avoiding miscellaneous jargon
lgbtq.offensive_terms Avoding offensive LGBTQ terms
lgbtq.terms Misused LGBTQ terms
lexical_illusions.misc Avoiding lexical illusions
links.broken Linking only to existing sites
malapropisms.misc Avoiding common malapropisms
misc.apologizing Being confident
misc.back_formations Avoiding needless backformations
misc.bureaucratese Avoiding bureaucratese
misc.but Avoid starting a paragraph with "But..."
misc.capitalization Capitalizing only what ought to be capitalized
misc.chatspeak Avoiding lolling and other chatspeak
misc.commercialese Avoiding jargon of the commercial world
misc.currency Avoiding redundant currency symbols
misc.debased Avoiding debased language
misc.false_plurals Avoiding false plurals
misc.illogic Avoiding illogical forms
misc.inferior_superior Superior to, not than
misc.latin Avoiding overuse of Latin phrases
misc.many_a Many a singular
misc.metaconcepts Avoiding overuse of metaconcepts
misc.narcissism Talking about the subject, not its study
misc.phrasal_adjectives Hyphenating phrasal adjectives
misc.preferred_forms Miscellaneous preferred forms
misc.pretension Avoiding being pretentious
misc.professions Calling jobs by the right name
misc.punctuation Using punctuation assiduously
misc.scare_quotes Using scare quotes only when needed
misc.suddenly Avoiding the word suddenly
misc.tense_present Advice from Tense Present
misc.waxed Waxing poetic
misc.whence Using "whence"
mixed_metaphors.misc Not mixing metaphors
mondegreens.misc Avoiding mondegreen
needless_variants.misc Using the preferred form
nonwords.misc Avoid using nonwords
oxymorons.misc Avoiding oxymorons
psychology.misc Avoiding misused psychological terms
redundancy.misc Avoiding redundancy and saying things twice
redundancy.ras_syndrome Avoiding RAS syndrome
skunked_terms.misc Avoid using skunked terms
spelling.able_atable -able vs. -atable
spelling.able_ible -able vs. -ible
spelling.athletes Spelling of athlete names
spelling.em_im_en_in -em vs. -im and -en vs. -in
spelling.er_or -er vs. -or
spelling.in_un in- vs. un-
spelling.misc Spelling words corectly
security.credit_card Keeping credit card numbers secret
security.password Keeping passwords secret
sexism.misc Avoiding sexist language
terms.animal_adjectives Animal adjectives
terms.denizen_labels Calling denizens by the right name
terms.eponymous_adjectives Calling people by the right name
terms.venery Call groups of animals by the right name
typography.diacritical_marks Using dïacríticâl marks
typography.exclamation Avoiding overuse of exclamation
typography.symbols Using the right symbols
uncomparables.misc Not comparing uncomparables
weasel_words.misc Avoiding weasel words
weasel_words.very Avoiding the word "very"

Contributing

Interested in contributing to proselint? Great — there are plenty of ways you can help. Read more on our website, 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 in or send an email to hello@amperser.com.

Running Automated Tests

Automated tests are included in the proselint/tests directory. To run these tests locally, use the test runner nose and run the following commands:

cd tests/
nosetests

and watch the output. Nose is compatible with Python versions 2.7, 3.3, 3.4 and 3.5.

All automated tests in tests/ are run as part of each submitted pull request, including newly added tests.

License

The project is licensed under the BSD license.