proselint-0.10.2/0000775000372000037200000000000013331225202014444 5ustar travistravis00000000000000proselint-0.10.2/README.md0000664000372000037200000002731213331225053015734 0ustar travistravis00000000000000proselint logo [![Build Status](https://travis-ci.org/amperser/proselint.svg)](https://travis-ci.org/amperser/proselint) [![Build status](https://ci.appveyor.com/api/projects/status/hfgv05nkjxkg2gcc/branch/master?svg=true)](https://ci.appveyor.com/project/suchow/proselint-knwyf/branch/master) [![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com) [![Code Climate](https://codeclimate.com/repos/5538989ee30ba0793100090f/badges/e10a2fe18a9256d69e2a/gpa.svg)](https://codeclimate.com/repos/5538989ee30ba0793100090f/feed) [![Coverage Status](https://coveralls.io/repos/github/amperser/proselint/badge.svg?branch=master)](https://coveralls.io/github/amperser/proselint?branch=master) [![Dependency Status](https://gemnasium.com/amperser/proselint.svg)](https://gemnasium.com/amperser/proselint) [![License](https://img.shields.io/badge/License-BSD-blue.svg)](https://en.wikipedia.org/wiki/BSD_licenses) 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](https://packaging.python.org/installing/#use-pip-for-installing): ``` 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 ``` ### Plugins for other software `proselint` is available on: - [x] A [demo editor](http://proselint.com/write) - [x] [Sublime Text](https://github.com/amperser/proselint/tree/master/plugins/sublime/SublimeLinter-contrib-proselint) - [x] [Atom Editor](https://github.com/smockle/linter-proselint) (thanks to [Clay Miller](https://github.com/smockle)). - [x] [Emacs via Flycheck](http://www.flycheck.org/). - [x] Vim via [ALE](https://github.com/w0rp/ale) or [Syntastic](https://github.com/vim-syntastic/syntastic) (thanks to @lcd047, @Carreau, and [Daniel M. Capella](https://github.com/polyzen)) - [x] [Phabricator's `arc` CLI](https://github.com/google/arc-proselint) (thanks to [Jeff Verkoeyen](https://github.com/jverkoey)) - [x] [Danger](https://github.com/dbgrandi/danger-prose) (thanks to [David Grandinetti](https://github.com/dbgrandi) and [Orta Therox](https://github.com/orta)) - [x] [Visual Studio Code](https://github.com/ppeszko/vscode-proselint) (thanks to [Patryk Peszko](https://github.com/ppeszko)) - [x] [coala](https://github.com/coala-analyzer/bear-docs/blob/master/docs/ProseLintBear.rst) (thanks to the [coala Development Group](https://github.com/coala-analyzer)) - [x] [IntelliJ](https://github.com/kropp/intellij-proselint) (by [Victor Kropp](https://github.com/kropp)) - [x] [pre-commit](https://pre-commit.com/) (by [Andy Airey](https://github.com/aairey)) ### 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: ```bash ❯ proselint text.md ``` This prints a list of suggestions to stdout, one per line. Each suggestion has the form: ```bash text.md::: ``` For example, ```bash 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: ```javascript { // 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`: ```python import proselint suggestions = proselint.tools.lint("This sentence is very unique") ``` This will return a list of suggestions: ```python [('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 `$XDG_CONFIG_HOME/proselint/config`. If `$XDG_CONFIG_HOME` is not set or empty, `~/.config/proselint/config` will be used. Additionally for compatible reason, the legacy configuration `~/.proselintrc` will be used if `$XDG_CONFIG_HOME/proselint/config` does not exist. ```json { "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](http://proselint.com/contributing/), where we describe how you can help us build `proselint` into the greatest writing tool in the world. - [Issue Tracker](http://github.com/amperser/proselint/issues) - [Source Code](http://github.com/amperser/proselint) ### Support If you run into a problem, please [open an issue](http://github.com/amperser/proselint/issues) 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 [pytest](https://docs.pytest.org/en/latest/) and run the following commands: ```bash pytest ``` and watch the output. Nose is compatible with Python versions 2.7, 3.4, 3.5 and 3.6. 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. proselint-0.10.2/setup.py0000664000372000037200000000276113331225053016170 0ustar travistravis00000000000000"""Installation script for proselint.""" import io import os from setuptools import setup, find_packages from proselint.version import __version__ DESCRIPTION = "A linter for prose." base_url = 'http://github.com/amperser/proselint' here = os.path.abspath(os.path.dirname(__file__)) try: with io.open(os.path.join(here, 'README.md'), encoding='utf-8') as f: long_description = '\n' + f.read() except FileNotFoundError: long_description = DESCRIPTION setup( name='proselint', version=__version__, description=DESCRIPTION, long_description=long_description, long_description_content_type='text/markdown', url=base_url, download_url="{}/tarball/{}".format(base_url, __version__), author='Amperser Labs', author_email='hello@amperser.com', license='BSD', classifiers=[ 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: Implementation :: CPython', ], packages=find_packages( exclude=["*.tests", "*.tests.*", "tests.*", "tests"]), package_data={'': ['demo.md', '.proselintrc']}, zip_safe=False, entry_points={ 'console_scripts': [ 'proselint = proselint.command_line:proselint', ], }, install_requires=[ 'click', 'future', 'six' ]) proselint-0.10.2/CHANGELOG.md0000664000372000037200000012163113331225053016265 0ustar travistravis00000000000000# Change Log ## [0.10.2](https://github.com/amperser/proselint/tree/0.10.2) (2018-08-03) [Full Changelog](https://github.com/amperser/proselint/compare/0.10.1...0.10.2) - Include tests in source package ([mavit](https://github.com/mavit)) ## [0.10.1](https://github.com/amperser/proselint/tree/0.10.1) (2018-08-01) [Full Changelog](https://github.com/amperser/proselint/compare/0.10.0...0.10.1) - Support use as [pre-commit](https://pre-commit.com/) hook ([Andy Airey](https://github.com/aairey)) ## [0.10.0](https://github.com/amperser/proselint/tree/0.10.0) (2018-07-23) [Full Changelog](https://github.com/amperser/proselint/compare/0.9.0...0.10.0) - Update dependencies to latest - Add support for reading from stdin with the CLI ([io12](https://github.com/io12)) - Use pytest, not Nose, on Travis ## [0.9.0](https://github.com/amperser/proselint/tree/0.9.0) (2018-07-20) [Full Changelog](https://github.com/amperser/proselint/compare/0.8.0...0.9.0) - Add new plugins to README - Update dependencies - Comply with XDG spec ([xu-cheng](https://github.com/xu-cheng)) ## [0.8.0](https://github.com/amperser/proselint/tree/0.8.0) (2017-02-22) [Full Changelog](https://github.com/amperser/proselint/compare/0.7.0...0.8.0) - Fix a cache-clearing issue ([m-charlton](https://github.com/m-charlton)) - Tons of improvements to tests ([joshmgrant](https://github.com/joshmgrant)) - New LGBTQ-terms module - Misc. bug fixes and improvements - Update various dependencies ## [0.7.0](https://github.com/amperser/proselint/tree/0.7.0) (2016-08-25) [Full Changelog](https://github.com/amperser/proselint/compare/0.6.1...0.7.0) **Implemented enhancements:** - how about `typography.symbols` instead of `me.symbols` [\#373](https://github.com/amperser/proselint/issues/373) - Improve test coverage [\#145](https://github.com/amperser/proselint/issues/145) - Add a changelog [\#596](https://github.com/amperser/proselint/pull/596) ([suchow](https://github.com/suchow)) **Fixed bugs:** - Exclamation point warning on all caps text [\#540](https://github.com/amperser/proselint/issues/540) - proselint choked on bad character [\#504](https://github.com/amperser/proselint/issues/504) - Could not open cache file [\#399](https://github.com/amperser/proselint/issues/399) **Closed issues:** - Add Instructions for Running Automated Tests on README [\#575](https://github.com/amperser/proselint/issues/575) - Add the "real estate tycoon" to phrasal adjectives [\#543](https://github.com/amperser/proselint/issues/543) - proselint CLI should append path to files [\#539](https://github.com/amperser/proselint/issues/539) - Add "English-language learners" to phrasal adjectives [\#537](https://github.com/amperser/proselint/issues/537) - Check out this Danger plugin [\#489](https://github.com/amperser/proselint/issues/489) - No args leads to repeated messages: Exception TypeError: "'NoneType' object is not callable" in ignore [\#323](https://github.com/amperser/proselint/issues/323) - Add rule on redundancies extracted from After the Deadline [\#279](https://github.com/amperser/proselint/issues/279) - Add rule on "not guilty beyond a reasonable doubt" [\#242](https://github.com/amperser/proselint/issues/242) - Eventually, submit to https://github.com/mcandre/linters [\#143](https://github.com/amperser/proselint/issues/143) - Add check for Mondegreens [\#134](https://github.com/amperser/proselint/issues/134) **Merged pull requests:** - Ensure a clean commit history [\#592](https://github.com/amperser/proselint/pull/592) ([suchow](https://github.com/suchow)) - Remove Danger CI token [\#591](https://github.com/amperser/proselint/pull/591) ([suchow](https://github.com/suchow)) - Move Danger to Travis 'script' section [\#590](https://github.com/amperser/proselint/pull/590) ([suchow](https://github.com/suchow)) - more tests, all modules from C to L except links [\#589](https://github.com/amperser/proselint/pull/589) ([joshmgrant](https://github.com/joshmgrant)) - Add phrasal adj for issues \#543 and \#537 [\#588](https://github.com/amperser/proselint/pull/588) ([kylesezhi](https://github.com/kylesezhi)) - Added More Tests For Coverage [\#584](https://github.com/amperser/proselint/pull/584) ([joshmgrant](https://github.com/joshmgrant)) - added some instructions for running automated tests [\#581](https://github.com/amperser/proselint/pull/581) ([suchow](https://github.com/suchow)) - unintentionally unintentionally misspelled. [\#580](https://github.com/amperser/proselint/pull/580) ([suchow](https://github.com/suchow)) - unintentionally unintentionally misspelled. [\#579](https://github.com/amperser/proselint/pull/579) ([suchow](https://github.com/suchow)) - Update GitHub access token [\#578](https://github.com/amperser/proselint/pull/578) ([suchow](https://github.com/suchow)) - Add cats to list of venerys [\#568](https://github.com/amperser/proselint/pull/568) ([Decagon](https://github.com/Decagon)) - Add "kind of" and "mildly" to uncomparables [\#562](https://github.com/amperser/proselint/pull/562) ([Decagon](https://github.com/Decagon)) - Fix \#540 [\#557](https://github.com/amperser/proselint/pull/557) ([Decagon](https://github.com/Decagon)) - Survey improvements [\#554](https://github.com/amperser/proselint/pull/554) ([suchow](https://github.com/suchow)) - Use a more up-to-date link checker [\#553](https://github.com/amperser/proselint/pull/553) ([suchow](https://github.com/suchow)) - Fix a typo [\#552](https://github.com/amperser/proselint/pull/552) ([suchow](https://github.com/suchow)) - Add "color" to inconsistent spelling [\#547](https://github.com/amperser/proselint/pull/547) ([Decagon](https://github.com/Decagon)) - Danger [\#546](https://github.com/amperser/proselint/pull/546) ([suchow](https://github.com/suchow)) - Add Danger plugin to readme [\#545](https://github.com/amperser/proselint/pull/545) ([suchow](https://github.com/suchow)) - Removing relative directory line on extract\_files function in the command line interface [\#541](https://github.com/amperser/proselint/pull/541) ([CatherineH](https://github.com/CatherineH)) - Improve survey [\#538](https://github.com/amperser/proselint/pull/538) ([suchow](https://github.com/suchow)) - Bump version to 0.6.1 [\#531](https://github.com/amperser/proselint/pull/531) ([suchow](https://github.com/suchow)) - Guidelines based on GLAAD Media Reference [\#486](https://github.com/amperser/proselint/pull/486) ([joshmgrant](https://github.com/joshmgrant)) ## [0.6.1](https://github.com/amperser/proselint/tree/0.6.1) (2016-07-18) [Full Changelog](https://github.com/amperser/proselint/compare/0.6.0...0.6.1) **Closed issues:** - sort output by line number? [\#505](https://github.com/amperser/proselint/issues/505) **Merged pull requests:** - Pr/518 [\#529](https://github.com/amperser/proselint/pull/529) ([suchow](https://github.com/suchow)) - Test Case for `tools.consistency\_check` [\#522](https://github.com/amperser/proselint/pull/522) ([joshmgrant](https://github.com/joshmgrant)) - Testing for illegal utf-8 seq handling [\#520](https://github.com/amperser/proselint/pull/520) ([CraigKelly](https://github.com/CraigKelly)) - Remove skipping tests for preferred\_forms\_check [\#515](https://github.com/amperser/proselint/pull/515) ([joshmgrant](https://github.com/joshmgrant)) - Change file opening to replace characters on UTF-8 decode errors [\#514](https://github.com/amperser/proselint/pull/514) ([suchow](https://github.com/suchow)) - Sort output by line and column number [\#512](https://github.com/amperser/proselint/pull/512) ([vikasgorur](https://github.com/vikasgorur)) - typo? [\#507](https://github.com/amperser/proselint/pull/507) ([ivarvong](https://github.com/ivarvong)) ## [0.6.0](https://github.com/amperser/proselint/tree/0.6.0) (2016-07-01) [Full Changelog](https://github.com/amperser/proselint/compare/0.5.4...0.6.0) **Closed issues:** - Proselint doesn't work on readonly files [\#502](https://github.com/amperser/proselint/issues/502) - Segmentation fault: 11 [\#487](https://github.com/amperser/proselint/issues/487) **Merged pull requests:** - Bump version to 0.6.0 [\#503](https://github.com/amperser/proselint/pull/503) ([suchow](https://github.com/suchow)) ## [0.5.4](https://github.com/amperser/proselint/tree/0.5.4) (2016-06-28) [Full Changelog](https://github.com/amperser/proselint/compare/0.5.3...0.5.4) **Fixed bugs:** - Remove `shell=True` as they are a security hazard [\#395](https://github.com/amperser/proselint/issues/395) **Closed issues:** - Speed up AppVeyor builds by caching [\#470](https://github.com/amperser/proselint/issues/470) - Instructions for installing on OS X [\#457](https://github.com/amperser/proselint/issues/457) - Wow [\#435](https://github.com/amperser/proselint/issues/435) - OS X Installation issue [\#423](https://github.com/amperser/proselint/issues/423) - Create a list of known automated grammar / usage checkers [\#281](https://github.com/amperser/proselint/issues/281) - Checklist for open sourcing [\#198](https://github.com/amperser/proselint/issues/198) **Merged pull requests:** - Pr/376 [\#500](https://github.com/amperser/proselint/pull/500) ([suchow](https://github.com/suchow)) - Pr/481 [\#499](https://github.com/amperser/proselint/pull/499) ([suchow](https://github.com/suchow)) - Improve formatting of Josh Grant's cliches test [\#498](https://github.com/amperser/proselint/pull/498) ([suchow](https://github.com/suchow)) - Call load\_options\(\) once and save the results instead of calling it t… [\#493](https://github.com/amperser/proselint/pull/493) ([suchow](https://github.com/suchow)) - Fix typos [\#492](https://github.com/amperser/proselint/pull/492) ([jwilk](https://github.com/jwilk)) - Fixed spelling [\#482](https://github.com/amperser/proselint/pull/482) ([TalkingAvocado](https://github.com/TalkingAvocado)) - Tweak website [\#479](https://github.com/amperser/proselint/pull/479) ([suchow](https://github.com/suchow)) - Update Werkzeug version [\#478](https://github.com/amperser/proselint/pull/478) ([suchow](https://github.com/suchow)) - Tracebacks [\#475](https://github.com/amperser/proselint/pull/475) ([suchow](https://github.com/suchow)) - Add replacements to return value of checks [\#473](https://github.com/amperser/proselint/pull/473) ([suchow](https://github.com/suchow)) - Tests for existence\_check in tools.py [\#469](https://github.com/amperser/proselint/pull/469) ([joshmgrant](https://github.com/joshmgrant)) - Remove `shell=True` [\#467](https://github.com/amperser/proselint/pull/467) ([suchow](https://github.com/suchow)) - Fix typo in docstring [\#466](https://github.com/amperser/proselint/pull/466) ([suchow](https://github.com/suchow)) - Improve code coverage [\#465](https://github.com/amperser/proselint/pull/465) ([suchow](https://github.com/suchow)) - Update dependencies to latest versions [\#464](https://github.com/amperser/proselint/pull/464) ([suchow](https://github.com/suchow)) - Create a list of other usage & grammar tools [\#462](https://github.com/amperser/proselint/pull/462) ([suchow](https://github.com/suchow)) - Improve documentation [\#461](https://github.com/amperser/proselint/pull/461) ([suchow](https://github.com/suchow)) - Copyedit the readme [\#459](https://github.com/amperser/proselint/pull/459) ([suchow](https://github.com/suchow)) - Update Coveralls badge in readme [\#456](https://github.com/amperser/proselint/pull/456) ([suchow](https://github.com/suchow)) - Add link to Phabricator integration to readme [\#453](https://github.com/amperser/proselint/pull/453) ([suchow](https://github.com/suchow)) - Remove lintscore badge from README [\#452](https://github.com/amperser/proselint/pull/452) ([suchow](https://github.com/suchow)) - Allow proselintrc to be overriden by user [\#451](https://github.com/amperser/proselint/pull/451) ([suchow](https://github.com/suchow)) - Create test pattern for checks [\#450](https://github.com/amperser/proselint/pull/450) ([suchow](https://github.com/suchow)) - Add CodeClimate config file [\#449](https://github.com/amperser/proselint/pull/449) ([suchow](https://github.com/suchow)) - Do not open file for reading and writing [\#447](https://github.com/amperser/proselint/pull/447) ([Tatsh](https://github.com/Tatsh)) - Refactor tools [\#445](https://github.com/amperser/proselint/pull/445) ([suchow](https://github.com/suchow)) ## [0.5.3](https://github.com/amperser/proselint/tree/0.5.3) (2016-04-05) [Full Changelog](https://github.com/amperser/proselint/compare/0.5.2...0.5.3) **Merged pull requests:** - Bump version to 0.5.3 [\#448](https://github.com/amperser/proselint/pull/448) ([suchow](https://github.com/suchow)) ## [0.5.2](https://github.com/amperser/proselint/tree/0.5.2) (2016-04-04) [Full Changelog](https://github.com/amperser/proselint/compare/0.5.1...0.5.2) **Implemented enhancements:** - Make `proselint .` run over entire directory, possibly with a recursive option [\#292](https://github.com/amperser/proselint/issues/292) **Merged pull requests:** - Fix error message for phrasal-adj. hyphenation [\#444](https://github.com/amperser/proselint/pull/444) ([suchow](https://github.com/suchow)) - Show status of master in AppVeyor badge [\#442](https://github.com/amperser/proselint/pull/442) ([suchow](https://github.com/suchow)) - Fix AppVeyor badge in readme [\#441](https://github.com/amperser/proselint/pull/441) ([suchow](https://github.com/suchow)) - Use AppVeyor for Windows CI [\#440](https://github.com/amperser/proselint/pull/440) ([suchow](https://github.com/suchow)) - Handle missing dbm module on some python 2.7 systems [\#439](https://github.com/amperser/proselint/pull/439) ([CraigKelly](https://github.com/CraigKelly)) ## [0.5.1](https://github.com/amperser/proselint/tree/0.5.1) (2016-04-02) [Full Changelog](https://github.com/amperser/proselint/compare/0.5.0...0.5.1) **Fixed bugs:** - JSON flag gives incorrect line/column numbers [\#418](https://github.com/amperser/proselint/issues/418) - Exception TypeError: "'NoneType' object is not callable" in ignored [\#238](https://github.com/amperser/proselint/issues/238) **Merged pull requests:** - Bump version to 0.5.1 [\#436](https://github.com/amperser/proselint/pull/436) ([suchow](https://github.com/suchow)) - Attempt to fix cache-related bugs [\#432](https://github.com/amperser/proselint/pull/432) ([CraigKelly](https://github.com/CraigKelly)) - Add entry to phrasal-adj. hyphenation check [\#431](https://github.com/amperser/proselint/pull/431) ([suchow](https://github.com/suchow)) - Fix off-by-one error in JSON output [\#429](https://github.com/amperser/proselint/pull/429) ([suchow](https://github.com/suchow)) - Don't warn when there's only 1 "!" [\#426](https://github.com/amperser/proselint/pull/426) ([laraross](https://github.com/laraross)) ## [0.5.0](https://github.com/amperser/proselint/tree/0.5.0) (2016-03-31) [Full Changelog](https://github.com/amperser/proselint/compare/0.4.4...0.5.0) **Implemented enhancements:** - Return a non-zero exit status when there are warnings [\#427](https://github.com/amperser/proselint/issues/427) **Merged pull requests:** - Use exit codes [\#428](https://github.com/amperser/proselint/pull/428) ([suchow](https://github.com/suchow)) ## [0.4.4](https://github.com/amperser/proselint/tree/0.4.4) (2016-03-30) [Full Changelog](https://github.com/amperser/proselint/compare/0.4.3...0.4.4) **Implemented enhancements:** - Assorted issues from Debian mailing list [\#389](https://github.com/amperser/proselint/issues/389) **Fixed bugs:** - Typo on API page [\#417](https://github.com/amperser/proselint/issues/417) - Assorted issues from Debian mailing list [\#389](https://github.com/amperser/proselint/issues/389) **Merged pull requests:** - Reorganization [\#424](https://github.com/amperser/proselint/pull/424) ([suchow](https://github.com/suchow)) - Update api.md - fixes \#417 [\#420](https://github.com/amperser/proselint/pull/420) ([shubheksha](https://github.com/shubheksha)) - added tests for butterick.symbols [\#413](https://github.com/amperser/proselint/pull/413) ([suchow](https://github.com/suchow)) - Deploy to PyPi only once [\#410](https://github.com/amperser/proselint/pull/410) ([suchow](https://github.com/suchow)) - Deploy to pypi automatically [\#409](https://github.com/amperser/proselint/pull/409) ([suchow](https://github.com/suchow)) ## [0.4.3](https://github.com/amperser/proselint/tree/0.4.3) (2016-03-19) [Full Changelog](https://github.com/amperser/proselint/compare/0.4.2...0.4.3) ## [0.4.2](https://github.com/amperser/proselint/tree/0.4.2) (2016-03-18) [Full Changelog](https://github.com/amperser/proselint/compare/0.4.1...0.4.2) **Merged pull requests:** - Fixed exception in the TypeError handler when cache sync fails [\#408](https://github.com/amperser/proselint/pull/408) ([saul](https://github.com/saul)) - Set option name to json output [\#406](https://github.com/amperser/proselint/pull/406) ([marsam](https://github.com/marsam)) ## [0.4.1](https://github.com/amperser/proselint/tree/0.4.1) (2016-03-18) [Full Changelog](https://github.com/amperser/proselint/compare/0.4.0...0.4.1) **Implemented enhancements:** - explain corpora directory [\#357](https://github.com/amperser/proselint/issues/357) - Add clean option to ensure that proselint clears cache before running [\#330](https://github.com/amperser/proselint/issues/330) - Hide filename in log when linting individual files [\#317](https://github.com/amperser/proselint/issues/317) **Fixed bugs:** - Remove filthy language from demo and test site [\#347](https://github.com/amperser/proselint/issues/347) **Closed issues:** - 'bug' when run with op to terminal? [\#405](https://github.com/amperser/proselint/issues/405) - Validity of Strunk & White as source [\#394](https://github.com/amperser/proselint/issues/394) - Create plugin for Atom [\#371](https://github.com/amperser/proselint/issues/371) - Add tex support for vim plugin [\#340](https://github.com/amperser/proselint/issues/340) - Create plugin for emacs [\#37](https://github.com/amperser/proselint/issues/37) **Merged pull requests:** - Add check for 'But' at start of paragraph [\#404](https://github.com/amperser/proselint/pull/404) ([dhan12](https://github.com/dhan12)) - Fix the Vim plugin to work with older versions of syntastic [\#398](https://github.com/amperser/proselint/pull/398) ([lcd047](https://github.com/lcd047)) - Added check for inferior/superior to/than. [\#392](https://github.com/amperser/proselint/pull/392) ([tkmharris](https://github.com/tkmharris)) - Added a directory for checks from Fowler's. Added a check for 'waxed … [\#391](https://github.com/amperser/proselint/pull/391) ([tkmharris](https://github.com/tkmharris)) - Add check for nonwords [\#390](https://github.com/amperser/proselint/pull/390) ([suchow](https://github.com/suchow)) - Make it possible to run `proselint .` over a directory [\#388](https://github.com/amperser/proselint/pull/388) ([suchow](https://github.com/suchow)) - Add rule on 'geometer' [\#387](https://github.com/amperser/proselint/pull/387) ([suchow](https://github.com/suchow)) - Fix the Vim plugin [\#377](https://github.com/amperser/proselint/pull/377) ([lcd047](https://github.com/lcd047)) - Fix bug in version formatting [\#372](https://github.com/amperser/proselint/pull/372) ([suchow](https://github.com/suchow)) - Add a --compact flag [\#370](https://github.com/amperser/proselint/pull/370) ([suchow](https://github.com/suchow)) - Fix bug in garner.dates \#278 [\#369](https://github.com/amperser/proselint/pull/369) ([ksslng](https://github.com/ksslng)) - Fix bug in Travis yml [\#368](https://github.com/amperser/proselint/pull/368) ([suchow](https://github.com/suchow)) - Remove filth from demo [\#366](https://github.com/amperser/proselint/pull/366) ([suchow](https://github.com/suchow)) - Remove rogue print statement [\#365](https://github.com/amperser/proselint/pull/365) ([suchow](https://github.com/suchow)) - Create file in memory in worker function [\#363](https://github.com/amperser/proselint/pull/363) ([suchow](https://github.com/suchow)) - Fix bug in webapp [\#362](https://github.com/amperser/proselint/pull/362) ([suchow](https://github.com/suchow)) - Describe corpus in README [\#360](https://github.com/amperser/proselint/pull/360) ([laraross](https://github.com/laraross)) - Add check for 'not guilty beyond a reasonable doubt' [\#359](https://github.com/amperser/proselint/pull/359) ([suchow](https://github.com/suchow)) - Update commercialese.py [\#354](https://github.com/amperser/proselint/pull/354) ([ciarand](https://github.com/ciarand)) - Fix backwards reference [\#353](https://github.com/amperser/proselint/pull/353) ([drinks](https://github.com/drinks)) - Fix spelling of kaleidoscope [\#352](https://github.com/amperser/proselint/pull/352) ([drinks](https://github.com/drinks)) - Correct duplicate docstrings [\#351](https://github.com/amperser/proselint/pull/351) ([hugovk](https://github.com/hugovk)) - Fix misattributed Twain quote [\#350](https://github.com/amperser/proselint/pull/350) ([hugovk](https://github.com/hugovk)) - Fix typo of garner in three checks' error messages [\#349](https://github.com/amperser/proselint/pull/349) ([stig](https://github.com/stig)) - Github -\> GitHub typos [\#348](https://github.com/amperser/proselint/pull/348) ([hugovk](https://github.com/hugovk)) ## [0.4.0](https://github.com/amperser/proselint/tree/0.4.0) (2016-03-08) [Full Changelog](https://github.com/amperser/proselint/compare/0.3.5...0.4.0) **Implemented enhancements:** - Proselint's SublimeText plugin is not on Package Control [\#234](https://github.com/amperser/proselint/issues/234) **Fixed bugs:** - Short flags are broken [\#326](https://github.com/amperser/proselint/issues/326) - trigger happy on exclamation mark warnings [\#322](https://github.com/amperser/proselint/issues/322) - proselint --initialize throws errors [\#304](https://github.com/amperser/proselint/issues/304) - Add -h argument option and double dash single character options [\#303](https://github.com/amperser/proselint/issues/303) - Enforce compatibility with Python 2 and 3 [\#297](https://github.com/amperser/proselint/issues/297) - Remove newline characters from error messages [\#288](https://github.com/amperser/proselint/issues/288) **Closed issues:** - Add LICENSE.md and README.md to source distribution [\#343](https://github.com/amperser/proselint/issues/343) - Website Lintscore Error [\#319](https://github.com/amperser/proselint/issues/319) - Vim Plugin [\#309](https://github.com/amperser/proselint/issues/309) - broken link http://amzn.to/15wF76r [\#298](https://github.com/amperser/proselint/issues/298) - Extract rules from the Federal Plain Language Guidelines [\#255](https://github.com/amperser/proselint/issues/255) - Create plugin for Atom editor [\#36](https://github.com/amperser/proselint/issues/36) **Merged pull requests:** - v0.4.0 [\#346](https://github.com/amperser/proselint/pull/346) ([suchow](https://github.com/suchow)) - Add README.md and LICENSE.md to source distribution [\#344](https://github.com/amperser/proselint/pull/344) ([viccuad](https://github.com/viccuad)) - Only complain about punctuational exclamation marks. Fixes \#322 [\#339](https://github.com/amperser/proselint/pull/339) ([jsenn](https://github.com/jsenn)) - Update site table [\#338](https://github.com/amperser/proselint/pull/338) ([michaelpacer](https://github.com/michaelpacer)) - Add list of available plugins to README [\#337](https://github.com/amperser/proselint/pull/337) ([suchow](https://github.com/suchow)) - added clean mode to build with no cache [\#332](https://github.com/amperser/proselint/pull/332) ([michaelpacer](https://github.com/michaelpacer)) - add short option to show help [\#329](https://github.com/amperser/proselint/pull/329) ([jstewmon](https://github.com/jstewmon)) - use absolute import to find proselint.tools [\#328](https://github.com/amperser/proselint/pull/328) ([jstewmon](https://github.com/jstewmon)) - fix click option declarations [\#327](https://github.com/amperser/proselint/pull/327) ([jstewmon](https://github.com/jstewmon)) - Fix miscalculation in lintscore example [\#324](https://github.com/amperser/proselint/pull/324) ([suchow](https://github.com/suchow)) - Update site only on master [\#321](https://github.com/amperser/proselint/pull/321) ([suchow](https://github.com/suchow)) - support variadic file args and stdin [\#320](https://github.com/amperser/proselint/pull/320) ([jstewmon](https://github.com/jstewmon)) - Correct spelling of "multiplication" [\#318](https://github.com/amperser/proselint/pull/318) ([fdb](https://github.com/fdb)) - Spelling corrections on page 'checks' [\#311](https://github.com/amperser/proselint/pull/311) ([TKAB](https://github.com/TKAB)) - v0.3.6 [\#307](https://github.com/amperser/proselint/pull/307) ([suchow](https://github.com/suchow)) - Update Flask-Limiter to latest version [\#302](https://github.com/amperser/proselint/pull/302) ([suchow](https://github.com/suchow)) - Update dependencies to latest [\#301](https://github.com/amperser/proselint/pull/301) ([suchow](https://github.com/suchow)) - Clean up source URLs and attributions [\#299](https://github.com/amperser/proselint/pull/299) ([suchow](https://github.com/suchow)) - Curly-quote max [\#296](https://github.com/amperser/proselint/pull/296) ([suchow](https://github.com/suchow)) - Don't flag 'matrices' [\#294](https://github.com/amperser/proselint/pull/294) ([suchow](https://github.com/suchow)) - Add rule on the redundant 'collocated together' [\#291](https://github.com/amperser/proselint/pull/291) ([suchow](https://github.com/suchow)) - Don't print errors object in json output [\#290](https://github.com/amperser/proselint/pull/290) ([marsam](https://github.com/marsam)) - Kill newline characters and whitespace in errors [\#289](https://github.com/amperser/proselint/pull/289) ([suchow](https://github.com/suchow)) - Add Flycheck plugin [\#287](https://github.com/amperser/proselint/pull/287) ([suchow](https://github.com/suchow)) - Add clichés from GNU diction [\#284](https://github.com/amperser/proselint/pull/284) ([suchow](https://github.com/suchow)) - Add check for diacritical marks [\#280](https://github.com/amperser/proselint/pull/280) ([suchow](https://github.com/suchow)) - Use subdirectories for posts [\#274](https://github.com/amperser/proselint/pull/274) ([suchow](https://github.com/suchow)) - Require a number on either side [\#273](https://github.com/amperser/proselint/pull/273) ([suchow](https://github.com/suchow)) - Skunked terms [\#270](https://github.com/amperser/proselint/pull/270) ([suchow](https://github.com/suchow)) - Allow no space around x in multiplication [\#269](https://github.com/amperser/proselint/pull/269) ([suchow](https://github.com/suchow)) - Add rule on false plurals [\#268](https://github.com/amperser/proselint/pull/268) ([suchow](https://github.com/suchow)) - Add stub for phrasal adjectives [\#267](https://github.com/amperser/proselint/pull/267) ([suchow](https://github.com/suchow)) - Improve typography checks [\#266](https://github.com/amperser/proselint/pull/266) ([suchow](https://github.com/suchow)) - Add stub of rule for professions [\#265](https://github.com/amperser/proselint/pull/265) ([suchow](https://github.com/suchow)) - Remove bare except clauses [\#264](https://github.com/amperser/proselint/pull/264) ([Uran198](https://github.com/Uran198)) - Upgrade to latest version of requirements [\#262](https://github.com/amperser/proselint/pull/262) ([suchow](https://github.com/suchow)) - Add instructions for Vim plug-in [\#258](https://github.com/amperser/proselint/pull/258) ([Carreau](https://github.com/Carreau)) - enable testing on Python 3.5 [\#257](https://github.com/amperser/proselint/pull/257) ([Carreau](https://github.com/Carreau)) - add a vim syntastic checker [\#256](https://github.com/amperser/proselint/pull/256) ([Carreau](https://github.com/Carreau)) - Add rule on "nouveau riche" [\#251](https://github.com/amperser/proselint/pull/251) ([suchow](https://github.com/suchow)) - Use Jekyll v2.5.3 [\#250](https://github.com/amperser/proselint/pull/250) ([suchow](https://github.com/suchow)) - Use bumpversion to manage versions [\#241](https://github.com/amperser/proselint/pull/241) ([suchow](https://github.com/suchow)) - Bump version number to 0.3.5 [\#240](https://github.com/amperser/proselint/pull/240) ([suchow](https://github.com/suchow)) ## [0.3.5](https://github.com/amperser/proselint/tree/0.3.5) (2015-10-20) [Full Changelog](https://github.com/amperser/proselint/compare/0.3.4...0.3.5) **Fixed bugs:** - Permission issues with current location of cache directory [\#225](https://github.com/amperser/proselint/issues/225) **Merged pull requests:** - Further copyedit Sublime Text plugin README [\#239](https://github.com/amperser/proselint/pull/239) ([suchow](https://github.com/suchow)) - Fix up the SublimeText README [\#237](https://github.com/amperser/proselint/pull/237) ([suchow](https://github.com/suchow)) - Fix bug in mondegreen rule [\#236](https://github.com/amperser/proselint/pull/236) ([suchow](https://github.com/suchow)) - Copy edit README for SublimeText plugin [\#235](https://github.com/amperser/proselint/pull/235) ([suchow](https://github.com/suchow)) - Update comment in butterick.symbols [\#233](https://github.com/amperser/proselint/pull/233) ([FakeYou](https://github.com/FakeYou)) - Add rule on mondegreens [\#232](https://github.com/amperser/proselint/pull/232) ([suchow](https://github.com/suchow)) - Fix for cache saving [\#231](https://github.com/amperser/proselint/pull/231) ([PatchRanger](https://github.com/PatchRanger)) - Fix bug in README formatting [\#230](https://github.com/amperser/proselint/pull/230) ([suchow](https://github.com/suchow)) - Add rule on 'neck-and-neck' [\#229](https://github.com/amperser/proselint/pull/229) ([suchow](https://github.com/suchow)) - Copy edit readme [\#228](https://github.com/amperser/proselint/pull/228) ([suchow](https://github.com/suchow)) - Update exclamation.py [\#226](https://github.com/amperser/proselint/pull/226) ([MichalPokorny](https://github.com/MichalPokorny)) - Fix version label [\#222](https://github.com/amperser/proselint/pull/222) ([suchow](https://github.com/suchow)) - Add rule on Wallace's examples of redundancy [\#221](https://github.com/amperser/proselint/pull/221) ([suchow](https://github.com/suchow)) - Revert "Enable all the checks by default" [\#220](https://github.com/amperser/proselint/pull/220) ([suchow](https://github.com/suchow)) - Fix autoresponder [\#219](https://github.com/amperser/proselint/pull/219) ([suchow](https://github.com/suchow)) - Tweak website [\#218](https://github.com/amperser/proselint/pull/218) ([suchow](https://github.com/suchow)) - Reinstate web app [\#216](https://github.com/amperser/proselint/pull/216) ([suchow](https://github.com/suchow)) - Misc. website improvements [\#215](https://github.com/amperser/proselint/pull/215) ([suchow](https://github.com/suchow)) - Update dependencies [\#214](https://github.com/amperser/proselint/pull/214) ([suchow](https://github.com/suchow)) - Remove live demo link, for now [\#213](https://github.com/amperser/proselint/pull/213) ([suchow](https://github.com/suchow)) - Further improve the README [\#212](https://github.com/amperser/proselint/pull/212) ([suchow](https://github.com/suchow)) - Update README [\#211](https://github.com/amperser/proselint/pull/211) ([suchow](https://github.com/suchow)) - Remove Heroku build from Travis [\#210](https://github.com/amperser/proselint/pull/210) ([suchow](https://github.com/suchow)) - Add stub for a rule on venery terms [\#209](https://github.com/amperser/proselint/pull/209) ([suchow](https://github.com/suchow)) ## [0.3.4](https://github.com/amperser/proselint/tree/0.3.4) (2015-10-01) [Full Changelog](https://github.com/amperser/proselint/compare/0.3.3...0.3.4) **Merged pull requests:** - Deploy to PyPi manually for now [\#207](https://github.com/amperser/proselint/pull/207) ([suchow](https://github.com/suchow)) - Fix some versioning issues [\#206](https://github.com/amperser/proselint/pull/206) ([suchow](https://github.com/suchow)) ## [0.3.3](https://github.com/amperser/proselint/tree/0.3.3) (2015-09-30) [Full Changelog](https://github.com/amperser/proselint/compare/0.3.2...0.3.3) **Merged pull requests:** - fixes version number [\#205](https://github.com/amperser/proselint/pull/205) ([michaelpacer](https://github.com/michaelpacer)) ## [0.3.2](https://github.com/amperser/proselint/tree/0.3.2) (2015-09-30) [Full Changelog](https://github.com/amperser/proselint/compare/0.3.1...0.3.2) **Merged pull requests:** - Disable version test [\#204](https://github.com/amperser/proselint/pull/204) ([laraross](https://github.com/laraross)) - fixup for pypi so demo will work [\#203](https://github.com/amperser/proselint/pull/203) ([laraross](https://github.com/laraross)) - Continuous integration [\#200](https://github.com/amperser/proselint/pull/200) ([suchow](https://github.com/suchow)) ## [0.3.1](https://github.com/amperser/proselint/tree/0.3.1) (2015-09-30) [Full Changelog](https://github.com/amperser/proselint/compare/0.3.0...0.3.1) ## [0.3.0](https://github.com/amperser/proselint/tree/0.3.0) (2015-09-30) [Full Changelog](https://github.com/amperser/proselint/compare/0.2.1...0.3.0) **Merged pull requests:** - Get ready for PyPi [\#199](https://github.com/amperser/proselint/pull/199) ([suchow](https://github.com/suchow)) ## [0.2.1](https://github.com/amperser/proselint/tree/0.2.1) (2015-09-30) [Full Changelog](https://github.com/amperser/proselint/compare/0.2.0...0.2.1) **Implemented enhancements:** - Create a timing test on the command line [\#191](https://github.com/amperser/proselint/issues/191) **Merged pull requests:** - Add timing test to CLI [\#197](https://github.com/amperser/proselint/pull/197) ([suchow](https://github.com/suchow)) - Test proselint version number [\#196](https://github.com/amperser/proselint/pull/196) ([suchow](https://github.com/suchow)) - Print full email headers [\#195](https://github.com/amperser/proselint/pull/195) ([suchow](https://github.com/suchow)) - Fix bug in email bot [\#194](https://github.com/amperser/proselint/pull/194) ([suchow](https://github.com/suchow)) - Improve links [\#193](https://github.com/amperser/proselint/pull/193) ([suchow](https://github.com/suchow)) - Improve website copy [\#192](https://github.com/amperser/proselint/pull/192) ([suchow](https://github.com/suchow)) - Contributing recommendations [\#189](https://github.com/amperser/proselint/pull/189) ([laraross](https://github.com/laraross)) - Tweak license formatting [\#188](https://github.com/amperser/proselint/pull/188) ([laraross](https://github.com/laraross)) - Remove corpus [\#186](https://github.com/amperser/proselint/pull/186) ([laraross](https://github.com/laraross)) - Add CI token to Travis [\#185](https://github.com/amperser/proselint/pull/185) ([suchow](https://github.com/suchow)) - Don't run timing test [\#184](https://github.com/amperser/proselint/pull/184) ([suchow](https://github.com/suchow)) - add bsd license [\#181](https://github.com/amperser/proselint/pull/181) ([michaelpacer](https://github.com/michaelpacer)) - Move to proselint.com [\#180](https://github.com/amperser/proselint/pull/180) ([suchow](https://github.com/suchow)) - Move scoring into its own file [\#179](https://github.com/amperser/proselint/pull/179) ([suchow](https://github.com/suchow)) - Fix one more malapropism typo [\#178](https://github.com/amperser/proselint/pull/178) ([suchow](https://github.com/suchow)) - Fix typos [\#177](https://github.com/amperser/proselint/pull/177) ([suchow](https://github.com/suchow)) - Specify version of future in reqs. [\#174](https://github.com/amperser/proselint/pull/174) ([suchow](https://github.com/suchow)) - Remove 'll' from NFL's naughty words [\#173](https://github.com/amperser/proselint/pull/173) ([suchow](https://github.com/suchow)) - Beef up the README [\#172](https://github.com/amperser/proselint/pull/172) ([suchow](https://github.com/suchow)) - Consolidate hardcoding of version number [\#169](https://github.com/amperser/proselint/pull/169) ([suchow](https://github.com/suchow)) ## [0.2.0](https://github.com/amperser/proselint/tree/0.2.0) (2015-09-18) [Full Changelog](https://github.com/amperser/proselint/compare/v0.1.0...0.2.0) **Closed issues:** - should we delete the python3 branch now that it's complete? [\#157](https://github.com/amperser/proselint/issues/157) - Add Louis C.K.'s rule on "the N-word" [\#154](https://github.com/amperser/proselint/issues/154) - Upgrade to most recent version of dependencies [\#144](https://github.com/amperser/proselint/issues/144) - Figure out the right name for a "check" [\#21](https://github.com/amperser/proselint/issues/21) - Extract rules from DFW's dictionary in The Telegraph [\#4](https://github.com/amperser/proselint/issues/4) **Merged pull requests:** - Daily GMAUs [\#160](https://github.com/amperser/proselint/pull/160) ([suchow](https://github.com/suchow)) - Add Louis C.K.'s rule on the n-word [\#159](https://github.com/amperser/proselint/pull/159) ([suchow](https://github.com/suchow)) - Python3 [\#156](https://github.com/amperser/proselint/pull/156) ([michaelpacer](https://github.com/michaelpacer)) - Update requirements [\#147](https://github.com/amperser/proselint/pull/147) ([suchow](https://github.com/suchow)) - Improve test coverage [\#146](https://github.com/amperser/proselint/pull/146) ([suchow](https://github.com/suchow)) ## [v0.1.0](https://github.com/amperser/proselint/tree/v0.1.0) (2015-07-13) **Implemented enhancements:** - Move cache to a place where Heroku can see it [\#90](https://github.com/amperser/proselint/issues/90) - Fork NLTK / TextBlob and speed up importing them [\#88](https://github.com/amperser/proselint/issues/88) **Fixed bugs:** - "every possible" flagged as comparing an uncomparable [\#129](https://github.com/amperser/proselint/issues/129) - Make proselint work in normal install mode [\#91](https://github.com/amperser/proselint/issues/91) - Decade detector false alarms on 50 cent posessive [\#82](https://github.com/amperser/proselint/issues/82) - Fix web plugin's handling of Unicode [\#62](https://github.com/amperser/proselint/issues/62) **Closed issues:** - Extract business euphemisms from Inc article [\#136](https://github.com/amperser/proselint/issues/136) - Refactor proselint/checks/norris/denizen\_labels.py from a D on Code Climate [\#127](https://github.com/amperser/proselint/issues/127) - Refactor proselint/checks/garner/sexism.py from a D on Code Climate [\#126](https://github.com/amperser/proselint/issues/126) - Refactor proselint/checks/butterick/symbols.py from a D on Code Climate [\#125](https://github.com/amperser/proselint/issues/125) - Test ticket from Code Climate [\#124](https://github.com/amperser/proselint/issues/124) - Create a linter email service [\#123](https://github.com/amperser/proselint/issues/123) - Make a splash page to collect email addresses [\#102](https://github.com/amperser/proselint/issues/102) - Get a logo [\#101](https://github.com/amperser/proselint/issues/101) - Add rate limiting to API [\#100](https://github.com/amperser/proselint/issues/100) - Use worker and web processes [\#96](https://github.com/amperser/proselint/issues/96) - Issue with broken link parsing [\#84](https://github.com/amperser/proselint/issues/84) - Extract rules from "Anguished English" [\#67](https://github.com/amperser/proselint/issues/67) - Make pep8 and pep257 run cleanly [\#61](https://github.com/amperser/proselint/issues/61) - Add rule about spelling names correctly [\#58](https://github.com/amperser/proselint/issues/58) - Build online writing editor using http://codemirror.net/? [\#50](https://github.com/amperser/proselint/issues/50) - Check out the cement framework for command line utilities [\#47](https://github.com/amperser/proselint/issues/47) - False alarms, corpora, QA, and contributing back [\#45](https://github.com/amperser/proselint/issues/45) - Create a .proselintrc file [\#39](https://github.com/amperser/proselint/issues/39) - Create plugin for Sublime Text [\#35](https://github.com/amperser/proselint/issues/35) - Create an API [\#33](https://github.com/amperser/proselint/issues/33) - Using "a" vs. "an" [\#31](https://github.com/amperser/proselint/issues/31) - Figure out test inheritance [\#30](https://github.com/amperser/proselint/issues/30) - Great writing should come back nearly clean [\#25](https://github.com/amperser/proselint/issues/25) - Don't lint quoted text [\#24](https://github.com/amperser/proselint/issues/24) - Architecture for sharing processed data across rules [\#20](https://github.com/amperser/proselint/issues/20) - It's et al., not et. al [\#18](https://github.com/amperser/proselint/issues/18) - Sort errors by the position in which they occur [\#12](https://github.com/amperser/proselint/issues/12) - Integrate into Sublime Text as a linter [\#11](https://github.com/amperser/proselint/issues/11) - Extract rules from write-good [\#5](https://github.com/amperser/proselint/issues/5) - working out how i can best contribute using github/git [\#3](https://github.com/amperser/proselint/issues/3) - Create a plugin system [\#2](https://github.com/amperser/proselint/issues/2) - Choose a sensible naming/numbering scheme for errors [\#1](https://github.com/amperser/proselint/issues/1) **Merged pull requests:** - Make compatible with Python 3 [\#95](https://github.com/amperser/proselint/pull/95) ([suchow](https://github.com/suchow)) - Change the sublime plugin file [\#53](https://github.com/amperser/proselint/pull/53) ([suchow](https://github.com/suchow)) - Create a plugin system [\#13](https://github.com/amperser/proselint/pull/13) ([suchow](https://github.com/suchow)) proselint-0.10.2/proselint/0000775000372000037200000000000013331225202016463 5ustar travistravis00000000000000proselint-0.10.2/proselint/tools.py0000664000372000037200000003205513331225053020206 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """General-purpose tools shared across linting checks.""" from __future__ import print_function from __future__ import unicode_literals import sys import traceback import os import shelve import inspect import functools import re import hashlib import json import importlib try: import dbm except ImportError: import anydbm as dbm PY3 = sys.version_info[0] == 3 if PY3: string_types = str else: string_types = basestring, _cache_shelves = dict() proselint_path = os.path.dirname(os.path.realpath(__file__)) def close_cache_shelves(): """Close previously opened cache shelves.""" for pth, cache in _cache_shelves.items(): cache.close() _cache_shelves.clear() def close_cache_shelves_after(f): """Decorator that ensures cache shelves are closed after the call.""" @functools.wraps(f) def wrapped(*args, **kwargs): f(*args, **kwargs) close_cache_shelves() return wrapped def _get_xdg_path(variable_name, default_path): path = os.environ.get(variable_name) if path is None or path == '': return default_path else: return path def _get_xdg_config_home(): return _get_xdg_path('XDG_CONFIG_HOME', os.path.join(os.path.expanduser('~'), '.config')) def _get_xdg_cache_home(): return _get_xdg_path('XDG_CACHE_HOME', os.path.join(os.path.expanduser('~'), '.cache')) def _get_cache(cachepath): if cachepath in _cache_shelves: return _cache_shelves[cachepath] try: cache = shelve.open(cachepath, protocol=2) except dbm.error: # dbm error on open - delete and retry print('Error (%s) opening %s - will attempt to delete and re-open.' % (sys.exc_info()[1], cachepath)) try: os.remove(cachepath) cache = shelve.open(cachepath, protocol=2) except Exception: print('Error on re-open: %s' % sys.exc_info()[1]) cache = None except Exception: # unknown error print('Could not open cache file %s, maybe name collision. ' 'Error: %s' % (cachepath, traceback.format_exc())) cache = None # Don't fail on bad caches if cache is None: print('Using in-memory shelf for cache file %s' % cachepath) cache = shelve.Shelf(dict()) _cache_shelves[cachepath] = cache return cache def memoize(f): """Cache results of computations on disk.""" # Determine the location of the cache. cache_dirname = os.path.join(_get_xdg_cache_home(), 'proselint') legacy_cache_dirname = os.path.join(os.path.expanduser("~"), ".proselint") if not os.path.isdir(cache_dirname): # Migrate the cache from the legacy path to XDG complaint location. if os.path.isdir(legacy_cache_dirname): os.rename(legacy_cache_dirname, cache_dirname) # Create the cache if it does not already exist. else: os.makedirs(cache_dirname) cache_filename = f.__module__ + "." + f.__name__ cachepath = os.path.join(cache_dirname, cache_filename) @functools.wraps(f) def wrapped(*args, **kwargs): # handle instance methods if hasattr(f, '__self__'): args = args[1:] signature = (f.__module__ + '.' + f.__name__).encode("utf-8") tempargdict = inspect.getcallargs(f, *args, **kwargs) for item in list(tempargdict.items()): signature += item[1].encode("utf-8") key = hashlib.sha256(signature).hexdigest() try: cache = _get_cache(cachepath) return cache[key] except KeyError: value = f(*args, **kwargs) cache[key] = value cache.sync() return value except TypeError: call_to = f.__module__ + '.' + f.__name__ print('Warning: could not disk cache call to %s;' 'it probably has unhashable args. Error: %s' % (call_to, traceback.format_exc())) return f(*args, **kwargs) return wrapped def get_checks(options): """Extract the checks.""" sys.path.append(proselint_path) checks = [] check_names = [key for (key, val) in list(options["checks"].items()) if val] for check_name in check_names: module = importlib.import_module("checks." + check_name) for d in dir(module): if re.match("check", d): checks.append(getattr(module, d)) return checks def load_options(): """Read various proselintrc files, allowing user overrides.""" possible_defaults = ( '/etc/proselintrc', os.path.join(proselint_path, '.proselintrc'), ) options = {} has_overrides = False for filename in possible_defaults: try: options = json.load(open(filename)) break except IOError: pass try: user_options = json.load( open(os.path.join(_get_xdg_config_home(), 'proselint', 'config'))) has_overrides = True except IOError: pass # Read user configuration from the legacy path. if not has_overrides: try: user_options = json.load( open(os.path.join(os.path.expanduser('~'), '.proselintrc'))) has_overrides = True except IOError: pass if has_overrides: if 'max_errors' in user_options: options['max_errors'] = user_options['max_errors'] if 'checks' in user_options: for (key, value) in user_options['checks'].items(): try: options['checks'][key] = value except KeyError: pass return options def errors_to_json(errors): """Convert the errors to JSON.""" out = [] for e in errors: out.append({ "check": e[0], "message": e[1], "line": 1 + e[2], "column": 1 + e[3], "start": 1 + e[4], "end": 1 + e[5], "extent": e[6], "severity": e[7], "replacements": e[8], }) return json.dumps( dict(status="success", data={"errors": out}), sort_keys=True) def line_and_column(text, position): """Return the line number and column of a position in a string.""" position_counter = 0 for idx_line, line in enumerate(text.splitlines(True)): if (position_counter + len(line.rstrip())) >= position: return (idx_line, position - position_counter) else: position_counter += len(line) def lint(input_file, debug=False): """Run the linter on the input file.""" options = load_options() if isinstance(input_file, string_types): text = input_file else: text = input_file.read() # Get the checks. checks = get_checks(options) # Apply all the checks. errors = [] for check in checks: result = check(text) for error in result: (start, end, check, message, replacements) = error (line, column) = line_and_column(text, start) if not is_quoted(start, text): errors += [(check, message, line, column, start, end, end - start, "warning", replacements)] if len(errors) > options["max_errors"]: break # Sort the errors by line and column number. errors = sorted(errors[:options["max_errors"]], key=lambda e: (e[2], e[3])) return errors def assert_error(text, check, n=1): """Assert that text has n errors of type check.""" assert_error.description = "No {} error for '{}'".format(check, text) assert(check in [error[0] for error in lint(text)]) def consistency_check(text, word_pairs, err, msg, offset=0): """Build a consistency checker for the given word_pairs.""" errors = [] msg = " ".join(msg.split()) for w in word_pairs: matches = [ [m for m in re.finditer(w[0], text)], [m for m in re.finditer(w[1], text)] ] if len(matches[0]) > 0 and len(matches[1]) > 0: idx_minority = len(matches[0]) > len(matches[1]) for m in matches[idx_minority]: errors.append(( m.start() + offset, m.end() + offset, err, msg.format(w[~idx_minority], m.group(0)), w[~idx_minority])) return errors def preferred_forms_check(text, list, err, msg, ignore_case=True, offset=0, max_errors=float("inf")): """Build a checker that suggests the preferred form.""" if ignore_case: flags = re.IGNORECASE else: flags = 0 msg = " ".join(msg.split()) errors = [] regex = u"[\W^]{}[\W$]" for p in list: for r in p[1]: for m in re.finditer(regex.format(r), text, flags=flags): txt = m.group(0).strip() errors.append(( m.start() + 1 + offset, m.end() + offset, err, msg.format(p[0], txt), p[0])) errors = truncate_to_max(errors, max_errors) return errors def existence_check(text, list, err, msg, ignore_case=True, str=False, max_errors=float("inf"), offset=0, require_padding=True, dotall=False, excluded_topics=None, join=False): """Build a checker that blacklists certain words.""" flags = 0 msg = " ".join(msg.split()) if ignore_case: flags = flags | re.IGNORECASE if str: flags = flags | re.UNICODE if dotall: flags = flags | re.DOTALL if require_padding: regex = u"(?:^|\W){}[\W$]" else: regex = u"{}" errors = [] # If the topic of the text is in the excluded list, return immediately. if excluded_topics: tps = topics(text) if any([t in excluded_topics for t in tps]): return errors rx = "|".join(regex.format(w) for w in list) for m in re.finditer(rx, text, flags=flags): txt = m.group(0).strip() errors.append(( m.start() + 1 + offset, m.end() + offset, err, msg.format(txt), None)) errors = truncate_to_max(errors, max_errors) return errors def truncate_to_max(errors, max_errors): """If max_errors was specified, truncate the list of errors. Give the total number of times that the error was found elsewhere. """ if len(errors) > max_errors: start1, end1, err1, msg1, replacements = errors[0] if len(errors) == (max_errors + 1): msg1 += " Found once elsewhere." else: msg1 += " Found {} times elsewhere.".format(len(errors)) errors = errors[1:max_errors] errors = [(start1, end1, err1, msg1, replacements)] + errors return errors def is_quoted(position, text): """Determine if the position in the text falls within a quote.""" def matching(quotemark1, quotemark2): straight = '\"\'' curly = '“”' if quotemark1 in straight and quotemark2 in straight: return True if quotemark1 in curly and quotemark2 in curly: return True else: return False def find_ranges(text): s = 0 q = pc = '' start = None ranges = [] seps = " .,:;-\r\n" quotes = ['\"', '“', '”', "'"] for i, c in enumerate(text + "\n"): if s == 0 and c in quotes and pc in seps: start = i s = 1 q = c elif s == 1 and matching(c, q): s = 2 elif s == 2: if c in seps: ranges.append((start+1, i-1)) start = None s = 0 else: s = 1 pc = c return ranges def position_in_ranges(ranges, position): for start, end in ranges: if start <= position < end: return True return False return position_in_ranges(find_ranges(text), position) def detector_50_Cent(text): """Determine whether 50 Cent is a topic.""" keywords = [ "50 Cent", "rap", "hip hop", "Curtis James Jackson III", "Curtis Jackson", "Eminem", "Dre", "Get Rich or Die Tryin'", "G-Unit", "Street King Immortal", "In da Club", "Interscope", ] num_keywords = sum(word in text for word in keywords) return ("50 Cent", float(num_keywords > 2)) def topics(text): """Return a list of topics.""" detectors = [ detector_50_Cent ] ts = [] for detector in detectors: ts.append(detector(text)) return [t[0] for t in ts if t[1] > 0.95] def context(text, position, level="paragraph"): """Get sentence or paragraph that surrounds the given position.""" if level == "sentence": pass elif level == "paragraph": pass return "" proselint-0.10.2/proselint/checks/0000775000372000037200000000000013331225202017723 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/weasel_words/0000775000372000037200000000000013331225202022421 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/weasel_words/very.py0000664000372000037200000000133513331225053023766 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Very. --- layout: post source: William Allen White source_url: http://bit.ly/1XaMllw title: very date: 2014-06-10 12:31:19 categories: writing --- 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. """ from proselint.tools import memoize, existence_check @memoize def check(text): """Avoid 'very'.""" err = "weasel_words.very" msg = ("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.") regex = "very" return existence_check(text, [regex], err, msg, max_errors=1) proselint-0.10.2/proselint/checks/weasel_words/__init__.py0000664000372000037200000000002413331225053024532 0ustar travistravis00000000000000"""Weasel words.""" proselint-0.10.2/proselint/checks/weasel_words/misc.py0000664000372000037200000000063313331225053023734 0ustar travistravis00000000000000"""Weasel words. --- layout: post source: write-good source_url: https://github.com/btford/write-good title: Weasel words. date: 2014-06-10 12:31:19 categories: writing --- Weasel words clearly weaken various aspects of a number of your sentences. """ # def check(text): # error_code = "weasel_words.misc" # msg = "Weasel words present." # return [(1, 1, error_code, msg)] proselint-0.10.2/proselint/checks/sexism/0000775000372000037200000000000013331225202021233 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/sexism/__init__.py0000664000372000037200000000001613331225053023345 0ustar travistravis00000000000000"""Sexism.""" proselint-0.10.2/proselint/checks/sexism/misc.py0000664000372000037200000000500713331225053022546 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Sexism. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: sexism date: 2014-06-10 12:31:19 categories: writing --- Points out sexist language. """ from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "sexism.misc" msg = "Gender bias. Use '{}' instead of '{}'." sexism = [ ["anchor", ["anchorman", "anchorwoman"]], ["chair", ["chairman", "chairwoman"]], ["drafter", ["draftman", "draftwoman"]], ["ombuds", ["ombudsman", "ombudswoman"]], ["tribe member", ["tribesman", "tribeswoman"]], ["police officer", ["policeman", "policewoman"]], ["firefighter", ["fireman", "firewoman"]], ["mail carrier", ["mailman", "mailwoman"]], ["history", ["herstory"]], ["women", ["womyn"]], ["poet", ["poetess"]], ["author", ["authoress"]], ["waiter", ["waitress"]], ["lawyer", ["lady lawyer"]], ["doctor", ["woman doctor"]], ["bookseller", ["female booksalesman"]], ["air pilot", ["female airman"]], ["executor", ["executrix"]], ["prosecutor", ["prosecutrix"]], ["testator", ["testatrix"]], ["husband and wife", ["man and wife"]], ["chairs", ["chairmen and chairs"]], ["men and women", ["men and girls"]], ["comedian", ["comedienne"]], ["confidant", ["confidante"]], ["scientist", ["woman scientist"]], ["scientists", ["women scientists"]] # ["hero", ["heroine"]] ] errors = preferred_forms_check(text, sexism, err, msg, ignore_case=False) msg = "Not a preferred form. Use '{}' instead of '{}'." pref = [ ["anchor", ["anchorperson"]], ["chair", ["chairperson"]], ["drafter", ["draftperson"]], ["ombuds", ["ombudsperson"]], ["tribe member", ["tribesperson"]], ["police officer", ["policeperson"]], ["firefighter", ["fireperson"]], ["mail carrier", ["mailperson"]], ] for x in preferred_forms_check(text, pref, err, msg, ignore_case=False): errors.append(x) return errors proselint-0.10.2/proselint/checks/links/0000775000372000037200000000000013331225202021043 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/links/broken.py0000664000372000037200000000320013331225053022674 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Checks that links are viable. --- layout: post source: SublimeLinter-annotations source_url: http://bit.ly/16Q7H41 title: broken links date: 2014-06-10 12:31:19 categories: writing --- Check that links are not broken. """ from proselint.tools import memoize from future import standard_library import re try: import urllib.request as urllib_request # for Python 3 except ImportError: import urllib2 as urllib_request # for Python 2 from socket import error as SocketError standard_library.install_aliases() @memoize def check(text): """Check the text.""" err = "links.valid" msg = u"Broken link: {}" regex = re.compile( r"""(?i)\b((?:https?://|www\d{0,3}[.] |[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+ |(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\) |[^\s`!()\[\]{};:\'".,<>?\xab\xbb\u201c\u201d\u2018\u2019\u21a9]))""", re.U | re.X) errors = [] for m in re.finditer(regex, text): url = m.group(0).strip() if "http://" not in url and "https://" not in url: url = "http://" + url if is_broken_link(url): errors.append((m.start(), m.end(), err, msg.format(url), None)) return errors @memoize def is_broken_link(url): """Determine whether the link returns a 404 error.""" try: request = urllib_request.Request( url, headers={'User-Agent': 'Mozilla/5.0'}) urllib_request.urlopen(request).read() return False except urllib_request.URLError: return True except SocketError: return True proselint-0.10.2/proselint/checks/links/__init__.py0000664000372000037200000000002413331225053023154 0ustar travistravis00000000000000"""Broken links.""" proselint-0.10.2/proselint/checks/jargon/0000775000372000037200000000000013331225202021203 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/jargon/__init__.py0000664000372000037200000000001613331225053023315 0ustar travistravis00000000000000"""Jargon.""" proselint-0.10.2/proselint/checks/jargon/misc.py0000664000372000037200000000126313331225053022516 0ustar travistravis00000000000000# -*- coding: utf-8 -*- u"""Cliches. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: a vs. an date: 2014-06-10 12:31:19 categories: writing --- Cliches are cliché. """ from proselint.tools import memoize, existence_check @memoize def check(text): """Check the text.""" err = "jargon.misc" msg = u"'{}' is jargon. Can you replace it with something more standard?" jargon = [ "in the affirmative", "in the negative", "agendize", "per your order", "per your request", "disincentivize", ] return existence_check(text, jargon, err, msg, join=True) proselint-0.10.2/proselint/checks/mixed_metaphors/0000775000372000037200000000000013331225202023113 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/mixed_metaphors/__init__.py0000664000372000037200000000002713331225053025227 0ustar travistravis00000000000000"""Mixed metaphors.""" proselint-0.10.2/proselint/checks/mixed_metaphors/misc.py0000664000372000037200000000255113331225053024427 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Mixed metaphors.""" from proselint.tools import memoize, existence_check, preferred_forms_check @memoize def check_bottleneck(text): """Avoid mixing metaphors about bottles and their necks. source: Sir Ernest Gowers source_url: http://bit.ly/1CQPH61 """ err = "mixed_metaphors.misc.bottleneck" msg = u"Mixed metaphor — bottles with big necks are easy to pass through." list = [ "biggest bottleneck", "big bottleneck", "large bottleneck", "largest bottleneck", "world-wide bottleneck", "huge bottleneck", "massive bottleneck", ] return existence_check(text, list, err, msg, max_errors=1) @memoize def check_misc(text): """Avoid mixing metaphors. source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY """ err = "mixed_metaphors.misc.misc" msg = u"Mixed metaphor. Try '{}'." preferences = [ ["cream rises to the top", ["cream rises to the crop"]], ["fasten your seatbelts", ["button your seatbelts"]], ["a minute to decompress", ["a minute to decompose"]], ["sharpest tool in the shed", ["sharpest marble in the (shed|box)"]], ["not rocket science", ["not rocket surgery"]], ] return preferred_forms_check(text, preferences, err, msg) proselint-0.10.2/proselint/checks/mondegreens/0000775000372000037200000000000013331225202022231 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/mondegreens/__init__.py0000664000372000037200000000002313331225053024341 0ustar travistravis00000000000000"""Mondegreens.""" proselint-0.10.2/proselint/checks/mondegreens/misc.py0000664000372000037200000000210113331225053023534 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Mondegreens. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: mondegreens date: 2014-06-10 12:31:19 categories: writing --- Points out preferred form. """ from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "misc.mondegreens" msg = "'{}' is the preferred form." list = [ ["a girl with kaleidoscope eyes", ["a girl with colitis goes by"]], ["a partridge in a pear tree", ["a part-red gingerbread tree"]], ["attorney and not a republic", ["attorney and notary public"]], ["beck and call", ["beckon call"]], ["for all intents and purposes", ["for all intensive purposes"]], ["laid him on the green", ["Lady Mondegreen"]], ["all of the other reindeer", ["Olive, the other reindeer"]], ["to the manner born", ["to the manor born"]], ] return preferred_forms_check(text, list, err, msg) proselint-0.10.2/proselint/checks/airlinese/0000775000372000037200000000000013331225202021676 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/airlinese/__init__.py0000664000372000037200000000002113331225053024004 0ustar travistravis00000000000000"""Airlinese.""" proselint-0.10.2/proselint/checks/airlinese/misc.py0000664000372000037200000000111013331225053023200 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Airlinese. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: Airlinese date: 2014-06-10 12:31:19 categories: writing --- Airlinese. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "airlinese.misc" msg = u"'{}' is airlinese." airlinese = [ "enplan(?:e|ed|ing|ement)", "deplan(?:e|ed|ing|ement)", "taking off momentarily", ] return existence_check(text, airlinese, err, msg) proselint-0.10.2/proselint/checks/dates_times/0000775000372000037200000000000013331225202022224 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/dates_times/dates.py0000664000372000037200000000324013331225053023701 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Dates. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: dates date: 2014-06-10 12:31:19 categories: writing --- Dates. """ from proselint.tools import existence_check, memoize import calendar @memoize def check_decade_apostrophes_short(text): """Check the text for dates of the form X0's.""" err = "dates_times.dates" msg = u"Apostrophes aren't needed for decades." regex = "\d0\'s" return existence_check( text, [regex], err, msg, excluded_topics=["50 Cent"]) @memoize def check_decade_apostrophes_long(text): """Check the text for dates of the form XXX0's.""" err = "dates_times.dates" msg = u"Apostrophes aren't needed for decades." regex = "\d\d\d0\'s" return existence_check(text, [regex], err, msg) @memoize def check_dash_and_from(text): """Check the text.""" err = "dates_times.dates" msg = u"When specifying a date range, write 'from X to Y'." regex = "[fF]rom \d+[^ \t\n\r\f\va-zA-Z0-9_\.]\d+" return existence_check(text, [regex], err, msg) def check_month_year_comma(text): """Check the text.""" err = "dates_times.dates" msg = u"When specifying a month and year, no comma is needed." regex = "(?:" + "|".join(calendar.month_name[1:]) + "), \d{3,}" return existence_check(text, [regex], err, msg) @memoize def check_month_of_year(text): """Check the text.""" err = "dates_times.dates" msg = u"When specifying a month and year, 'of' is unnecessary." regex = "(?:" + "|".join(calendar.month_name[1:]) + ") of \d{3,}" return existence_check(text, [regex], err, msg) proselint-0.10.2/proselint/checks/dates_times/__init__.py0000664000372000037200000000002713331225053024340 0ustar travistravis00000000000000"""Dates and times.""" proselint-0.10.2/proselint/checks/dates_times/am_pm.py0000664000372000037200000000266713331225053023706 0ustar travistravis00000000000000# -*- coding: utf-8 -*- u"""a.m. / p.m. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: a.m. & p.m. date: 2014-06-10 12:31:19 categories: writing --- """ from proselint.tools import memoize, existence_check @memoize def check_lowercase_periods(text): """Check the text.""" err = "dates_times.am_pm.lowercase_periods" msg = u"With lowercase letters, the periods are standard." return existence_check(text, ["\d{1,2} ?[ap]m"], err, msg) @memoize def check_spacing(text): """Check the text.""" err = "dates_times.am_pm.spacing" msg = u"It's standard to put a space before 'a.m.' or 'p.m.'." return existence_check(text, ["\d{1,2}[ap]\.?m\.?"], err, msg) @memoize def check_midnight_noon(text): """Check the text.""" err = "dates_times.am_pm.midnight_noon" msg = (u"12 a.m. and 12 p.m. are wrong and confusing." " Use 'midnight' or 'noon'.") return existence_check(text, ["12 ?[ap]\.?m\.?"], err, msg) @memoize def check_redundancy(text): """Check the text.""" err = "dates_times.am_pm.midnight_noon" msg = (u"'a.m.' is always morning; 'p.m.' is always night.") list = [ "\d{1,2} ?a\.?m\.? in the morning", "\d{1,2} ?p\.?m\.? in the evening", "\d{1,2} ?p\.?m\.? at night", "\d{1,2} ?p\.?m\.? in the afternoon", ] return existence_check(text, list, err, msg, join=True) proselint-0.10.2/proselint/checks/typography/0000775000372000037200000000000013331225202022131 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/typography/exclamation.py0000664000372000037200000000215213331225053025013 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Too much yelling. --- layout: post source: ??? source_url: ??? title: yelling date: 2014-06-10 12:31:19 categories: writing --- Too much yelling. """ import re from proselint.tools import existence_check, memoize @memoize def check_repeated_exclamations(text): """Check the text.""" err = "leonard.exclamation.multiple" msg = u"Stop yelling. Keep your exclamation points under control." regex = r"[\!]\s*?[\!]{1,}" return existence_check( text, [regex], err, msg, require_padding=False, ignore_case=False, max_errors=1, dotall=True) @memoize def check_exclamations_ppm(text): """Make sure that the exclamation ppm is under 30.""" err = "leonard.exclamation.30ppm" msg = u"More than 30 ppm of exclamations. Keep them under control." regex = r"\w!" count = len(re.findall(regex, text)) num_words = len(text.split(" ")) ppm = (count*1.0 / num_words) * 1e6 if ppm > 30 and count > 1: loc = re.search(regex, text).start() + 1 return [(loc, loc+1, err, msg, ".")] else: return [] proselint-0.10.2/proselint/checks/typography/diacritical_marks.py0000664000372000037200000001116213331225053026155 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Diacritical marks. Use of diacritical marks where common. """ from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "typography.diacritical_marks" msg = u"Use diacritical marks in '{}'." list = [ # French loanwords [u"beau idéal", ["beau ideal"]], [u"boutonnière", ["boutonniere"]], [u"bric-à-brac", ["bric-a-brac"]], [u"café", ["cafe"]], [u"cause célèbre", ["cause celebre"]], [u"chèvre", ["chevre"]], [u"cliché", ["cliche"]], [u"comme ci comme ça", ["comme ci comme ca", "comsi comsa"]], [u"consommé", ["consomme"]], [u"coup d'état", ["coup d'etat"]], [u"coup de grâce", ["coup de grace"]], [u"crudités", ["crudites"]], [u"crème brûlée", ["creme brulee"]], [u"crème de menthe", ["creme de menthe"]], [u"crème fraîche", ["creme fraice"]], [u"crème fraîche", ["creme fresh"]], [u"crêpe", ["crepe"]], [u"débutante", ["debutante"]], [u"décor", ["decor"]], [u"déjà vu", ["deja vu"]], [u"dénouement", ["denouement"]], [u"façade", ["facade"]], [u"fiancé", ["fiance"]], [u"fiancée", ["fiancee"]], [u"flambé", ["flambe"]], [u"garçon", ["garcon"]], [u"lycée", ["lycee"]], [u"maître d", ["maitre d"]], [u"ménage à trois", ["menage a trois"]], [u"négligée", ["negligee"]], [u"papier-mâché", ["papier-mache", "paper mache", "paper-mache"]], [u"protégé", ["protege"]], [u"protégée", ["protegee"]], [u"purée", ["puree"]], [u"raison d'être", ["raison d'etre"]], [u"my résumé", ["my resume"]], [u"your résumé", ["your resume"]], [u"his résumé", ["his resume"]], [u"her résumé", ["her resume"]], [u"a résumé", ["a resume"]], [u"the résumé", ["the resume"]], [u"risqué", ["risque"]], [u"roué", ["roue"]], [u"soirée", ["soiree"]], [u"soufflé", ["souffle"]], [u"soupçon", ["soupcon"]], [u"touché", ["touche"]], [u"tête-à-tête", ["tete-a-tete"]], [u"voilà", ["voila"]], [u"à la carte", ["a la carte"]], [u"à la mode", ["a la mode"]], [u"émigré", ["emigre"]], # Spanish loanwords [u"El Niño", ["El Nino"]], [u"jalapeño", ["jalapeno"]], [u"La Niña", ["La Nina"]], [u"piña colada", ["pina colada"]], [u"señor", ["senor"]], [u"señora", ["senora"]], [u"señorita", ["senorita"]], # Portuguese loanwords [u"açaí", ["acai"]], # German loanwords [u"doppelgänger", ["doppelganger"]], [u"Führer", ["Fuhrer"]], [u"Gewürztraminer", ["Gewurztraminer"]], [u"vis-à-vis", ["vis-a-vis"]], [u"Übermensch", ["Ubermensch"]], # Swedish loanwords [u"filmjölk", ["filmjolk"]], [u"smörgåsbord", ["smorgasbord"]], # Names, places, and companies [u"Beyoncé", ["Beyonce"]], [u"Brontë", ["Bronte"]], [u"Brontë", ["Bronte"]], [u"Champs-Élysées", ["Champs-Elysees"]], [u"Citroën", ["Citroen"]], [u"Curaçao", ["Curacao"]], [u"Häagen-Dazs", ["Haagen-Dazs", "Haagen Dazs"]], [u"Löwenbräu", ["Lowenbrau"]], [u"Monégasque", ["Monegasque"]], [u"Mötley Crüe", ["Motley Crue"]], [u"Nescafé", ["Nescafe"]], [u"Queensrÿche", ["Queensryche"]], [u"Québec", ["Quebec"]], [u"Québécois", ["Quebecois"]], [u"Ångström", ["Angstrom"]], [u"ångström", ["angstrom"]], [u"Škoda", ["Skoda"]], ] return preferred_forms_check(text, list, err, msg) proselint-0.10.2/proselint/checks/typography/symbols.py0000664000372000037200000000544013331225053024202 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Use the right symbols. source: Butterick's Practical Typography source_url: http://practicaltypography.com/ """ from proselint.tools import memoize, existence_check, preferred_forms_check @memoize def check_ellipsis(text): """Use an ellipsis instead of three dots.""" err = "typography.symbols.ellipsis" msg = u"'...' is an approximation, use the ellipsis symbol '…'." regex = "\.\.\." return existence_check(text, [regex], err, msg, max_errors=3, require_padding=False, offset=0) @memoize def check_copyright_symbol(text): """Use the copyright symbol instead of (c).""" err = "typography.symbols.copyright" msg = u"(c) is a goofy alphabetic approximation, use the symbol ©." regex = "\([cC]\)" return existence_check( text, [regex], err, msg, max_errors=1, require_padding=False) @memoize def check_trademark_symbol(text): """Use the trademark symbol instead of (TM).""" err = "typography.symbols.trademark" msg = u"(TM) is a goofy alphabetic approximation, use the symbol ™." regex = "\(TM\)" return existence_check( text, [regex], err, msg, max_errors=3, require_padding=False) @memoize def check_registered_trademark_symbol(text): """Use the registered trademark symbol instead of (R).""" err = "typography.symbols.trademark" msg = u"(R) is a goofy alphabetic approximation, use the symbol ®." regex = "\([rR]\)" return existence_check( text, [regex], err, msg, max_errors=3, require_padding=False) @memoize def check_sentence_spacing(text): """Use no more than two spaces after a period.""" err = "typography.symbols.sentence_spacing" msg = u"More than two spaces after the period; use 1 or 2." regex = "\. {3}" return existence_check( text, [regex], err, msg, max_errors=3, require_padding=False) @memoize def check_multiplication_symbol(text): u"""Use the multiplication symbol ×, not the lowercase letter x.""" err = "typography.symbols.multiplication_symbol" msg = u"Use the multiplication symbol ×, not the letter x." regex = "[0-9]+ ?x ?[0-9]+" return existence_check( text, [regex], err, msg, max_errors=3, require_padding=False) @memoize def check_curly_quotes(text): u"""Use curly quotes, not straight quotes.""" err = "typography.symbols.curly_quotes" msg = u'Use curly quotes “”, not straight quotes "".' list = [ [u"“ or ”", ['"']], ] return preferred_forms_check( text, list, err, msg, ignore_case=False, max_errors=2) # @memoize # def check_en_dash_separated_names(text): # """Use an en-dash to separate names.""" # # [u"[A-Z][a-z]{1,10}[-\u2014][A-Z][a-z]{1,10}", # # u"Use an en dash (–) to separate names."], proselint-0.10.2/proselint/checks/typography/__init__.py0000664000372000037200000000003413331225053024243 0ustar travistravis00000000000000"""Advice on typography.""" proselint-0.10.2/proselint/checks/misc/0000775000372000037200000000000013331225202020656 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/misc/metadiscourse.py0000664000372000037200000000130113331225053024076 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Metadiscourse. --- layout: post source: Pinker's book on writing source_url: ??? title: metadiscourse date: 2014-06-10 12:31:19 categories: writing --- Points out metadiscourse. """ from proselint.tools import memoize, existence_check @memoize def check(text): """Suggest the preferred forms.""" err = "pinker.metadiscourse" msg = "Excessive metadiscourse." metadiscourse = [ "The preceeding discussion", "The rest of this article", "This chapter discusses", "The preceding paragraph demonstrated", "The previous section analyzed", ] return existence_check(text, metadiscourse, err, msg) proselint-0.10.2/proselint/checks/misc/inferior_superior.py0000664000372000037200000000132413331225053025001 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Inferior / Superior. --- layout: post source: Fowler's Modern English Usage source_url: bit.ly/1YBG8QJ title: Inferior / Superior date: 2016-03-10 17:27:37 categories: writing --- Corrects 'inferior/superior than' to 'inferior/superior to'. """ from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "misc.inferior_superior" msg = "'Inferior' and 'superior' are not true comparatives. Use '{}'." preferences = [ ["inferior to", ["inferior than"]], ["superior to", ["superior than"]], ] return preferred_forms_check(text, preferences, err, msg) proselint-0.10.2/proselint/checks/misc/tense_present.py0000664000372000037200000000210113331225053024104 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Tense present. --- layout: post source: DFW's Tense Present source_url: http://bit.ly/1c85lgR title: Tense present date: 2014-06-10 12:31:19 categories: writing --- Archaism. """ from proselint.tools import memoize import re @memoize def check(text): """Check the text.""" err = "misc.tense_present" msg = u"'{}'." illogics = [ u"up to \d{1,3}% ?[-\u2014\u2013]{0,3} ?(?:or|and) more\W?", "between you and I", "on accident", "somewhat of a", "all it's own", "reason is because", "audible to the ear", "in regards to", "would of", # "and so", "i ?(?:feel|am feeling|am|'m|'m feeling) nauseous", ] errors = [] for i in illogics: for m in re.finditer(u"\s{}\s".format(i), text, flags=re.U | re.I): txt = m.group(0).strip() errors.append(( m.start() + 1, m.end(), err, msg.format(txt), None)) return errors proselint-0.10.2/proselint/checks/misc/apologizing.py0000664000372000037200000000105613331225053023560 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Excessive apologizing. --- layout: post source: Pinker's book on writing source_url: ??? title: excessive apologizing date: 2014-06-10 12:31:19 categories: writing --- Points out excessive apologizing. """ from proselint.tools import memoize, existence_check @memoize def check(text): """Suggest the preferred forms.""" err = "pinker.apologizing" msg = "Excessive apologizing." narcissism = [ "More research is needed", ] return existence_check(text, narcissism, err, msg) proselint-0.10.2/proselint/checks/misc/back_formations.py0000664000372000037200000000111413331225053024372 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Back-formations. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: back-formations date: 2014-06-10 12:31:19 categories: writing --- Back-formations. """ from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "misc.back_formations" msg = "Back-formation. '{}' is the preferred form." list = [ ["improper", ["improprietous"]], ] return preferred_forms_check(text, list, err, msg) proselint-0.10.2/proselint/checks/misc/greylist.py0000664000372000037200000000167413331225053023106 0ustar travistravis00000000000000"""Use of greylisted words. --- layout: post source: Strunk & White source_url: ??? title: Use of greylisted words date: 2014-06-10 12:31:19 categories: writing --- Strunk & White say: """ from proselint.tools import memoize import re @memoize def check(text): """Check the text.""" err = "strunk_white.greylist" msg = "Use of '{}'. {}" bad_words = [ "obviously", "utilize" ] explanations = { "obviously": "This is obviously an inadvisable word to use.", "utilize": r"Do you know anyone who *needs* to utilize the word utilize?" } errors = [] for word in bad_words: occ = [m for m in re.finditer(word, text.lower())] for o in occ: errors.append(( o.start(), o.end(), err, msg.format(word, explanations[word]), None)) return errors proselint-0.10.2/proselint/checks/misc/many_a.py0000664000372000037200000000131613331225053022501 0ustar travistravis00000000000000# -*- coding: utf-8 -*- u"""Many a singular. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: Many a singular. date: 2014-06-10 12:31:19 categories: writing --- The idiom 'many a' requires a singular verb. """ from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "misc.many_a" msg = "'many a' requires a singular verb." preferences = [ ["is many a", ["are many a"]], ["has been many a", ["have been many a"]], ["was many a", ["were many a"]], ] return preferred_forms_check(text, preferences, err, msg) proselint-0.10.2/proselint/checks/misc/false_plurals.py0000664000372000037200000000150713331225053024073 0ustar travistravis00000000000000# -*- coding: utf-8 -*- u"""False plurals. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: False plurals. date: 2014-06-10 12:31:19 categories: writing --- Using the incorrect form of the plural. """ from proselint.tools import memoize, preferred_forms_check, existence_check @memoize def check(text): """Suggest the preferred forms.""" err = "misc.false_plurals.examples" msg = "The plural is {}" preferences = [ ["talismans", ["talismen"]], ["phenomena", ["phenomenons"]], ] return preferred_forms_check(text, preferences, err, msg) @memoize def check_kudos(text): """Check the text.""" err = "misc.false_plurals.kudos" msg = u"Kudos is singular." return existence_check(text, ["many kudos"], err, msg) proselint-0.10.2/proselint/checks/misc/illogic.py0000664000372000037200000000254213331225053022661 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Illogic. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: Illogic date: 2014-06-10 12:31:19 categories: writing --- Archaism. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "misc.illogic" msg = u"'{}' is illogical." illogics = [ "preplan", "more than .{1,10} all", "appraisal valuations?", "(?:i|you|he|she|it|y'all|all y'all|you all|they) could care less", "least worst", "much-needed gaps?", "much-needed voids?", "no longer requires oxygen", "without scarcely", ] return existence_check(text, illogics, err, msg, offset=1) @memoize def check_coin_a_phrase_from(text): """Check the text.""" err = "misc.illogic.coin" msg = "You can't coin an existing phrase. Did you mean 'borrow'?" regex = "to coin a phrase from" return existence_check(text, [regex], err, msg, offset=1) @memoize def check_without_your_collusion(text): """Check the textself.""" err = "misc.illogic.collusion" msg = "It's impossible to defraud yourself. Try 'aquiescence'." regex = "without your collusion" return existence_check( text, [regex], err, msg, require_padding=False, offset=-1) proselint-0.10.2/proselint/checks/misc/usage.py0000664000372000037200000000374313331225053022347 0ustar travistravis00000000000000"""Elementary Rules of Usage. --- layout: post source: Strunk & White source_url: ??? title: Elementary Rules of Usage date: 2014-06-10 12:31:19 categories: writing --- Strunk & White say: 1. Form the possessive singular of nouns by adding 's. 2. In a series of three or more terms with a conjunction, use a comma after each term except the last. 3. Enclose parenthetic expressions between commas. ("This rule is difficult to apply.") 4. Place a comma before a conjunction introducing an independent clause. 5. Do not join independent clauses with a comma; use a semi-colon. Or a period. 6. Do not break sentences in two. Do not use periods for the role of commas. 7. Use a colon after an independent clause if you introduce: a list of particulars, an appositive, an application, or an illustrative quotation. 8. Use a dash to set off an abrupt break or interruption and to announce a long appositive or summary. 9. The number of the subject determines the number of the verb. (MDPNB: This will require nltk & syntactic parsing) 10. Use the proper case(grammatical gender) of pronouns. * MDPNB: hard case: "Give this work to whoever looks idle." `whoever looks idle` is the object of `to`. 11. A participial phrase at the beginning of a sentence must refer to the grammatical subject. """ # from proselint.tools import memoize # import re # @memoize # def check(text): # err = "strunk_white.usage" # msg = "Use of '{}'. {}" # bad_words = [ # "obviously", # "utilize" # ] # explanations = { # "obviously": # "This is obviously an inadvisable word to use.", # "utilize": # r"Do you know anyone who *needs* to utilize the word utilize?" # } # errors = [] # for word in bad_words: # occ = [m for m in re.finditer(word, text.lower())] # for o in occ: # errors.append((o.start(), o.end(), err, # msg.format(word, explanations[word]))) # return errors proselint-0.10.2/proselint/checks/misc/metaconcepts.py0000664000372000037200000000111313331225053023715 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Metaconcepts. --- layout: post source: Pinker's book on writing source_url: ??? title: misuse of scare quotes date: 2014-06-10 12:31:19 categories: writing --- Point out misuse of scare quotes. """ # from proselint.tools import memoize, existence_check # @memoize # def check(text): # """Suggest the preferred forms.""" # err = "pinker.metaconcepts" # msg = "Misuse of 'scare quotes'. Delete them." # narcissism = [ # "the 'take-home message'", # ] # return existence_check(text, narcissism, err, msg) proselint-0.10.2/proselint/checks/misc/institution_name.py0000664000372000037200000000142313331225053024625 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Common errors with institution names. --- layout: post source: Institution's webpage source_url: http://bit.ly/2en1zbv, title: Institution Name date: 2016-11-16 11:46:19 categories: writing --- Institution names. """ from proselint.tools import memoize, preferred_forms_check @memoize def check_vtech(text): """Suggest the correct name. source: Virginia Tech Division of Student Affairs source_url: http://bit.ly/2en1zbv """ err = "institution.vtech" msg = "Incorrect name. Use '{}' instead of '{}'." institution = [ ["Virginia Polytechnic Institute and State University", ["Virginia Polytechnic and State University"]], ] return preferred_forms_check(text, institution, err, msg) proselint-0.10.2/proselint/checks/misc/__init__.py0000664000372000037200000000006613331225053022775 0ustar travistravis00000000000000"""Miscellaneous advice not otherwise categorized.""" proselint-0.10.2/proselint/checks/misc/but.py0000664000372000037200000000101413331225053022022 0ustar travistravis00000000000000# -*- coding: utf-8 -*- u"""Don't start a paragraph with 'But'. --- layout: source: Justin Jungé source_url: title: date: 2016-03-10 12:31:19 categories: writing --- Paragraphs should not start with certain bad words. """ from proselint.tools import memoize, existence_check @memoize def check(text): """Do not start a paragraph with a 'But'.""" err = "misc.but" msg = u"No paragraph should start with a 'But'." regex = "(^|([\n\r]+))(\s*)But" return existence_check(text, [regex], err, msg) proselint-0.10.2/proselint/checks/misc/currency.py0000664000372000037200000000101213331225053023060 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Currency. --- layout: post source: SublimeLinter-annotations source_url: http://bit.ly/16Q7H41 title: symbols date: 2014-06-10 12:31:19 categories: writing --- Symbols. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "misc.currency" msg = u"Incorrect use of symbols in {}." symbols = [ "\$[\d]* ?(?:dollars|usd|us dollars)" ] return existence_check(text, symbols, err, msg) proselint-0.10.2/proselint/checks/misc/not_guilty.py0000664000372000037200000000207613331225053023436 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Not guilty beyond a reasonable doubt. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: Not guilty beyond a reasonable doubt. date: 2016-03-09 15:50:31 categories: writing --- This phrasing is ambiguous. The standard by which a jury decides criminal charges is this: a defendant is guilty only if the evidence shows, beyond a reasonable doubt, that he or she committed the crime. Otherwise, the defendant is not guilty. Thus, we say that a defendant was not found "guilty beyond a reasonable doubt." If somebody is found not guilty, say "not guilty." Omit the standard ("beyond a reasonable doubt") to prevent a miscue. Not guilty beyond a reasonable doubt """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "misc.not_guilty" msg = u"'not guilty beyond a reasonable doubt' is an ambiguous phrasing." regex = r"not guilty beyond (a |any )?reasonable doubt" return existence_check(text, [regex], err, msg) proselint-0.10.2/proselint/checks/misc/capitalization.py0000664000372000037200000000475513331225053024262 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Incorrect capitalization. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: incorrect captalization date: 2014-06-10 12:31:19 categories: writing --- Incorrect capitalization. """ from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "misc.captalization" msg = "Incorrect capitalization. '{}' is the preferred form." list = [ ["Stone Age", ["stone age"]], ["space age", ["Space Age"]], ["the American West", ["the American west"]], ["Mother Nature", ["mother nature"]], ] return preferred_forms_check(text, list, err, msg, ignore_case=False) # @memoize # def check_seasons(text): # """Suggest the preferred forms.""" # err = "MAU102" # msg = "Seasons shouldn't be capitalized. '{}' is the preferred form." # list = [ # # ["winter", ["Winter"]], # # ["fall", ["Fall"]], # # ["summer", ["Summer"]], # # ["spring", ["Spring"]], # ] # return preferred_forms_check(text, list, err, msg, ignore_case=False) @memoize def check_months(text): """Suggest the preferred forms.""" err = "MAU102" msg = "Months should be capitalized. '{}' is the preferred form." list = [ ["January", ["january"]], ["February", ["february"]], # ["March", ["march"]], ["April", ["april"]], # ["May", ["may"]], ["June", ["june"]], ["July", ["july"]], ["August", ["august"]], ["September", ["september"]], ["October", ["october"]], ["November", ["november"]], ["December", ["december"]], ] return preferred_forms_check(text, list, err, msg, ignore_case=False) @memoize def check_days(text): """Suggest the preferred forms.""" err = "MAU102" msg = "Days of the week should be capitalized. '{}' is the preferred form." list = [ ["Monday", ["monday"]], ["Tuesday", ["tuesday"]], ["Wednesday", ["wednesday"]], ["Thursday", ["thursday"]], ["Friday", ["friday"]], ["Saturday", ["saturday"]], ["Sunday", ["sunday"]], ] return preferred_forms_check(text, list, err, msg, ignore_case=False) proselint-0.10.2/proselint/checks/misc/pretension.py0000664000372000037200000000116013331225053023420 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Pretension. --- layout: post source: ??? source_url: ??? title: yelling date: 2014-06-10 12:31:19 categories: writing --- Never use the phrase 'all hell broke loose'. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "ogilvy.pretension" msg = u"Jargon words like this one are the hallmarks of a pretentious ass." list = [ "reconceptualize", "demassification", "attitudinally", "judgmentally", ] return existence_check(text, list, err, msg, max_errors=1) proselint-0.10.2/proselint/checks/misc/chatspeak.py0000664000372000037200000000142713331225053023203 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Chatspeak. --- layout: post source: ??? source_url: ??? title: textese date: 2014-06-10 12:31:19 categories: writing --- Chatspeak. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "misc.chatspeak" msg = u"'{}' is chatspeak. Write it out." words = [ "2day", "4U", "AFAIK", "AFK", "AFK", "ASAP", "B4", "brb", "btw", "cya", "GR8", "lol", "LOL", "LUV", "OMG", "rofl", "roftl", "sum1", "SWAK", "THNX", "THX", "TTYL", "XOXO" ] return existence_check(text, words, err, msg) proselint-0.10.2/proselint/checks/misc/latin.py0000664000372000037200000000141713331225053022346 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Back-formations. --- layout: post source: The sense of style source_url: http://amzn.to/1EOUZ5g title: back-formations date: 2014-06-10 12:31:19 categories: writing --- Back-formations. """ from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "pinker.latin" msg = "Use English. '{}' is the preferred form." list = [ ["other things being equal", ["ceteris paribus"]], ["among other things", ["inter alia"]], ["in and of itself", ["simpliciter"]], ["having made the necessary changes", ["mutatis mutandis"]], ] return preferred_forms_check(text, list, err, msg) proselint-0.10.2/proselint/checks/misc/preferred_forms.py0000664000372000037200000001664313331225053024432 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Preferred forms. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: preferred forms date: 2014-06-10 12:31:19 categories: writing --- Points out preferred forms. """ from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "garner.preferred_forms" msg = "'{}' is the preferred form." preferences = [ # Obsolete words ["imprimatur", ["imprimature"]], # Proper nouns ["Halloween", ["haloween", "hallowe'en"]], ["Khrushchev", ["Khruschev", "Kruschev"]], ["Ku Klux Klan", ["Klu Klux Klan"]], ["Pontius Pilate", ["Pontius Pilot"]], # Plurals ["hippopotamuses", ["hippopotami"]], ["manifestos", ["manifesti"]], # ["matrixes", ["matrices"]], ["mongooses", ["mongeese"]], ["narcissi", ["narcissuses"]], ["retinas", ["retinae"]], ["sopranos", ["soprani"]], ["titmice", ["titmouses"]], # Hyphenated words ["long-standing", ["longstanding"]], ["sans serif", ["sans-serif", "sanserif"]], ["tortfeasor", ["tort feasor", "tort-feasor"]], ["transship", ["tranship", "trans-ship"]], ["transshipped", ["transhipped", "trans-shipped"]], ["transshipping", ["transhipping", "trans-shipping"]], ["non sequitur", ["non-sequitur"]], # Misc ["attitude", ["mental attitude"]], ["Chief Justice of the United States", ["Chief Justice of the United States Supreme Court", "Chief Justice of the Supreme Court of the United States."]], ["chitterlings", ["chitlings", "chitlins"]], ["combustion engine", ["combustible engine"]], ["during / throughout", ["for the duration of"]], ["foreclose on", ["foreclose againt"]], ["friend in common", ["mutual friend"]], ["in regard to", ["in regards to"]], ["infectious", ["infectuous"]], ["inferable", ["inferrable", "inferrible"]], ["knowing that", ["in light of the fact that"]], ["lanyard", ["laniard"]], ["largess", ["largesse"]], ["lasagna", ["lasagne"]], ["leery", ["leary"]], ["lend me her", ["loan me her"]], ["lend me his", ["loan me his"]], ["lend me their", ["loan me their"]], ["lend me your", ["loan me your"]], ["lent me her", ["loaned me her"]], ["lent me his", ["loaned me his"]], ["lent me their", ["loaned me their"]], ["lent me your", ["loaned me your"]], ["linguist", ["linguistician"]], ["matzo-ball", ["matzoh-ball", "matza-ball", "matzah-ball", "matsah-ball"]], ["mayoralty", ["mayorality"]], ["mealy-mouthed", ["mealymouthed"]], ["mean-spirited", ["meanspirited"]], ["midwifed", ["midwived"]], ["moniker", ["monicker"]], ["musical revue", ["musical review"]], ["mustache", ["moustache"]], ["nonplussed", ["nonplused"]], ["nonplussing", ["nonplusing"]], ["non sequitur", ["nonsequitur"]], ["not nearly as", ["nowhere near as"]], ["off", ["off of"]], ["podiatrist", ["chiropodist"]], ["podiatry", ["chiropody"]], ["shoo-in", ["shoe-in"]], ["suicide", ["suicide victim"]], ["the highway median", ["the highway medium"]], ["vaipidity", ["vapidness"]], ["weather vane", ["weather vein", "weather vain"]], ["with regard to", ["with regards to"]], # Idioms ["a couple of people", ["a couple people"]], ["all the time", ["all of the time"]], ["as follows", ["as follow"]], ["bulk large", ["bulk largely"]], ["burying the lede", ["burying the lead"]], ["came to naught", ["came to nought"]], ["come off it", ["come off of it"]], ["corroborating evidence", ["corroborative evidence"]], ["dear departed", ["dearly departed"]], ["default on a loan", ["default to a loan"]], ["draw an inference", ["make an inference"]], ["in the meantime", ["in the meanwhile"]], ["long distances", ["lengthy distances"]], ["madding crowd", ["maddening crowd"]], ["Magna Carta", ["Magna Charta"]], ["marriage of convenience", ["mariage de convenance"]], ["Meanwhile,", ["Meantime,"]], ["Midwest", ["Middle West"]], ["Midwestern", ["Middle Western"]], ["modi operandi", ["modes of operandi"]], ["modus operandi", ["mode of operandi"]], ["motion seconded", ["notion seconded"]], ["mucous membranes", ["mucus membranes"]], ["must pass muster", ["must past muster"]], ["neck-and-neck", ["neck-in-neck"]], ["no-holds-barred", ["no-holes-barred"]], ["oil magnate", ["oil magnet"]], ["punch up the lede", ["punch up the lead"]], ["railroad magnate", ["railroad magnet"]], ["seconded the motion", ["seconded the notion"]], ["statute of limitationas", ["statute of limits"]], ["take precedence over", ["take prescience over"]], ["the last two", ["both of the last two"]], ["the last two", ["both of the last"]], ["unorganic food", ["inorganic food"]], ["vale of tears", ["veil of tears"]], ["Venus flytrap", ["Venus's flytrap", "Venus' flytrap"]], ["was accused of", ["was accused with"]], # Verbosity ["try to", ["make an attempt to"]], ["try to", ["make attempts to"]], ["try to", ["make efforts to"]], ["tried to", ["made an attempt to"]], ["tried to", ["made attempts to"]], ["tried to", ["made efforts to"]], ["modern", ["modern-day"]], # Grammar ["be misled", ["be mislead"]], ["was misled", ["was mislead"]], ["were misled", ["were mislead"]], # Euphemisms ["a search-and-destroy mission", ["armed reconnaissance"]], ["abortion", ["pregnancy termination"]], ["bisexual", ["sexually ambidextrous"]], ["exterminator", ["extermination engineer"]], ["firing", ["permanent layoff"]], ["rat-catcher", ["rodent operative"]], # Tenses ["mistook", ["mistaked"]], # Accents ["né", ["ne"]], ["née", ["nee"]], ] return preferred_forms_check(text, preferences, err, msg) proselint-0.10.2/proselint/checks/misc/whence.py0000664000372000037200000000071413331225053022507 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """From whence it came. --- layout: post source: unknown source_url: unknown title: whence date: 2014-06-10 12:31:19 categories: writing --- From whence it came. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "misc.whence" msg = u"The 'from' in 'from whence' is not needed." return existence_check(text, ["from whence"], err, msg) proselint-0.10.2/proselint/checks/misc/suddenly.py0000664000372000037200000000272713331225053023073 0ustar travistravis00000000000000# -*- coding: utf-8 -*- u"""Suddenly. --- layout: post source: Reference for Writers source_url: http://bit.ly/1E94vyD title: suddenly date: 2014-06-10 12:31:19 categories: writing --- “Sudden” means quickly and without warning, but using the word “suddenly” both slows down the action and warns your reader. Do you know what’s more effective for creating the sense of the sudden? Just saying what happens. When using “suddenly,” you communicate through the narrator that the action seemed sudden. By jumping directly into the action, you allow the reader to experience that suddenness first hand. “Suddenly” also suffers from being nondescript, failing to communicate the nature of the action itself; providing no sensory experience or concrete fact to hold on to. Just … suddenly. Feel free to employ “suddenly” in situations where the suddenness is not apparent in the action itself. For example, in “Suddenly, I don’t hate you anymore,” the “suddenly” substantially changes the way we think about the shift in emotional calibration. """ from proselint.tools import memoize, existence_check @memoize def check(text): """Advice on sudden vs suddenly.""" err = "misc.suddenly" msg = u"Suddenly is nondescript, slows the action, and warns your reader." regex = "Suddenly," return existence_check(text, [regex], err, msg, max_errors=3, require_padding=False, offset=-1, ignore_case=False) proselint-0.10.2/proselint/checks/misc/commercialese.py0000664000372000037200000000240213331225053024042 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Commercialese. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: commercialese date: 2014-06-10 12:31:19 categories: writing --- Commercialese. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "misc.commercialese" msg = u"'{}' is commercialese." commercialese = [ "acknowledging yours of", "beg to advise", "enclosed herewith", "enclosed please find", "further to yours of", "further to your letter", "in regard to", "inst\.", "in the amount of", "of even date", "pending receipt of", "please be advised that", "please return same", "pleasure of a reply", "prox\.", "pursuant to your request", "regarding the matter", "regret to inform", "thanking you in advance", "the undersigned", "this acknowledges your letter", "ult\." "we are pleased to note", "with regard to", "your favor has come to hand", "yours of even date" ] return existence_check(text, commercialese, err, msg, join=True) proselint-0.10.2/proselint/checks/misc/professions.py0000664000372000037200000000105113331225053023603 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Profession. --- layout: post source: source_url: title: Professions date: 2014-06-10 12:31:19 categories: writing --- Professions. """ from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "misc.professions" msg = "'{}' is the name of that job." preferences = [ ["cobbler", ["shoe repair guy"]], ["geometer", ["geometrist"]], ] return preferred_forms_check(text, preferences, err, msg) proselint-0.10.2/proselint/checks/misc/waxed.py0000664000372000037200000000346313331225053022352 0ustar travistravis00000000000000"""Waxed lyrical. --- layout: post source: Fowler's Modern English Usage source_url: bit.ly/1YBG8QJ title: Waxed lyrical date: 2016-03-10 14:48:42 categories: writing --- Fowler's says: Its primary meaning 'grow larger, increase' (as opposed to 'wane') leads naturally to the sense 'pass into a specified state or mood, begin to use a specified tone. In this meaning a following modifier must be an adj. not an adverb ('He waxed enthusiastic [not enthusiastically] about Australia'). """ from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "misc.waxed" msg = u"The modifier following 'waxed' must be an adj.: '{}' is correct" waxes = ["wax", "waxes", "waxed", "waxing"] modifiers = [("ebullient", "ebulliently"), ("ecstatic", "ecstatically"), ("eloquent", "eloquently"), ("enthusiastic", "enthusiastically"), ("euphoric", "euphorically"), ("indignant", "indignantly"), ("lyrical", "lyrically"), ("melancholic", "melancholically"), ("metaphorical", "metaphorically"), ("nostalgic", "nostalgically"), ("patriotic", "patriotically"), ("philosophical", "philosophically"), ("poetic", "poetically"), ("rhapsodic", "rhapsodically"), ("romantic", "romantically"), ("sentimental", "sentimentally") ] def pairs(word): return [[word + ' ' + pair[0], [word + ' ' + pair[1]]] for pair in modifiers] preferred = [] for word in waxes: preferred += pairs(word) return preferred_forms_check(text, preferred, err, msg) proselint-0.10.2/proselint/checks/misc/narcissism.py0000664000372000037200000000117613331225053023414 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Professional narcissism. --- layout: post source: Pinker's book on writing source_url: ??? title: professional narcissism date: 2014-06-10 12:31:19 categories: writing --- Points out academic narcissism. """ from proselint.tools import memoize, existence_check @memoize def check(text): """Suggest the preferred forms.""" err = "pinker.narcissism" msg = "Professional narcissism. Talk about the subject, not its study." narcissism = [ "In recent years, an increasing number of [a-zA-Z]{3,}sts have", ] return existence_check(text, narcissism, err, msg) proselint-0.10.2/proselint/checks/misc/bureaucratese.py0000664000372000037200000000111413331225053024063 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Bureaucratese. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: bureaucratese date: 2014-06-10 12:31:19 categories: writing --- Bureaucratese. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "misc.bureaucratese" msg = u"'{}' is bureaucratese." bureaucratese = [ "meet with your approval", "meets with your approval", ] return existence_check(text, bureaucratese, err, msg, join=True) proselint-0.10.2/proselint/checks/misc/punctuation.py0000664000372000037200000000102213331225053023600 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Punctuation. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: dates date: 2014-06-10 12:31:19 categories: writing --- Dates. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "garner.punctuation" msg = u"Misplaced punctuation. It's 'et al.'" list = [ "et. al", "et. al." ] return existence_check(text, list, err, msg, join=True) proselint-0.10.2/proselint/checks/misc/scare_quotes.py0000664000372000037200000000110213331225053023723 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Misuse of scare quotes. --- layout: post source: Pinker's book on writing source_url: ??? title: misuse of scare quotes date: 2014-06-10 12:31:19 categories: writing --- Points out misuse of scare quotes. """ from proselint.tools import memoize, existence_check @memoize def check(text): """Suggest the preferred forms.""" err = "pinker.scare_quotes" msg = "Misuse of 'scare quotes'. Delete them." narcissism = [ "the 'take-home message'", ] return existence_check(text, narcissism, err, msg) proselint-0.10.2/proselint/checks/misc/composition.py0000664000372000037200000000663613331225053023612 0ustar travistravis00000000000000"""Elementary Rules of Usage. --- layout: post source: Strunk & White source_url: ??? title: Elementary Principles of Composition date: 2014-06-10 12:31:19 categories: writing --- Strunk & White say: 1. Choose a suitable design and hold to it. * MDPNB: Sounds like a principle of `consistency`. 2. Make the paragraph the unit of composition. * MDPNB: This can be generalized to say something about variability in the length of paragraphs and sentences. When any device is too often used it becomes a mannerism. * MDPNB: Sounds like a principle of `variation`. 3. Use the active voice. 4. Put statements in positive form. * MDPNB: In some cases this will apply as an invective against the use of a double negative. * Ex: He was not very often on time. -> He usually came late. * Ex: 4.1. Placing negative and positive in opposition makes for a stronger structure. * Ex. Not charity, but simple justice. * Not that I loved Caesar less, but that I loved Rome more. 4.2. Do not use unnecessary auxiliaries or conditionals. 5. Use definite, specific, concrete language. * A period of unfavorable weather set in. ->It rained every day for a week. 6. Omit needless words. * `The fact that` is particularly pernicious. * `who is, which was` and the like are often superfluous 7. Avoid a succession of loose sentences. * MDPNB Principle of brevity. Take 2. 8. Express coordinate ideas in similar form. * MDPNB: Principle of parallel structure. * MDPNB: This one will be hard... 9. Keep related words together. * MDPNB: Principle of localism in semantics. 10. In summaries, keep to one tense. * MDPNB: Principle of temporal consistency. 11. Place the emphatic word of a sentence at the end. * MDPNB: Principle of recency. """ from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "strunk_white.composition" msg = "Try '{}' instead of '{}'." bad_forms = [ # Put statements in positive form ["dishonest", ["not honest"]], ["trifling", ["not important"]], ["forgot", ["did not remember"]], ["ignored", ["did not pay (any )?attention to"]], ["distrusted", ["did not have much confidence in"]], # Omit needless words ["whether", ["the question as to whether"]], ["no doubt", ["there is no doubt but that"]], ["used for fuel", ["used for fuel purposes"]], ["he", ["he is a man who"]], ["hastily", ["in a hasty manner"]], ["this subject", ["this is a subject that"]], ["Her story is strange.", ["Her story is a strange one."]], ["because", ["the reason why is that"]], ["because / since", ["owing to the fact that"]], ["although / though", ["in spite of the fact that"]], ["remind you / notify you", ["call your attention to the fact that"]], ["I did not know that / I was unaware that", ["I was unaware of the fact that"]], ["his failure", ["the fact that he had not succeeded"]], ["my arrival", ["the fact that i had arrived"]] ] return preferred_forms_check(text, bad_forms, err, msg) proselint-0.10.2/proselint/checks/misc/debased.py0000664000372000037200000000121013331225053022615 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Debased language. --- layout: post source: ??? source_url: ??? title: yelling date: 2014-06-10 12:31:19 categories: writing --- Too much yelling. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "misc.debased" msg = u"Bad usage, debased language, a continuous temptation." list = [ "a not unjustifiable assumption", "leaves much to be desired", "would serve no purpose", "a consideration which we should do well to bear in mind", ] return existence_check(text, list, err, msg) proselint-0.10.2/proselint/checks/misc/phrasal_adjectives.py0000664000372000037200000001547713331225053025105 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Phrasal adjectives. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: Phrasal adjectives date: 2014-06-10 12:31:19 categories: writing --- Phrasal adjectives. """ from proselint.tools import existence_check, preferred_forms_check, memoize @memoize def check_ly(text): """Check the text.""" err = "garner.phrasal_adjectives.ly" msg = u"""No hyphen is necessary in phrasal adjectives with an adverb ending in -ly, unless the -ly adverb is part of a longer phrase""" regex = "\s[^\s-]+ly-" return existence_check(text, [regex], err, msg, require_padding=False, offset=-1) @memoize def check(text): """Check the text.""" err = "garner.phrasal_adjectives.examples" msg = u"""Hyphenate '{1}', a phrasal adjective, as '{0}'.""" list = [ ["across-the-board discounts", ["across the board discounts"]], ["acute-care treatment", ["acute care treatment"]], ["agreed-upon answer", ["agreed upon answer"]], ["big-ticket item", ["big ticket item"]], ["class-action lawyer", ["class action lawyer"]], ["criminal-law professor", ["criminal law professor"]], ["cut-and-dried issue", ["cut and dried issue"]], ["downward-sloping line", ["downward sloping line"]], ["English-language learners", ["English language learners"]], ["English-speaking people", ["English speaking people"]], ["even-numbered", ["even numbered"]], ["face-to-face meeting", ["fact to face meeting"]], ["fixed-rate mortgage", ["fixed rate mortgage"]], ["for-profit firm", ["for profit firm"]], ["foreign-sounding name", ["foreign sounding name"]], ["government-owned business", ["government owned business"]], ["hard-and-fast issue", ["hard and fast issue"]], ["head-on collision", ["head on collision"]], ["head-to-head battle", ["head to head battle"]], ["head-to-head competition", ["head to head competition"]], ["health-care coverage", ["heath care coverage"]], ["high-school student", ["high school student"]], ["hit-and-run statute", ["hit and run statute"]], ["HIV-negative person", ["HIV negative person"]], ["HIV-positive person", ["HIV positive person"]], ["information-technology personnel", ["information technology personnel"]], ["intellectual-property rights", ["intellectual property rights"]], ["interest-group pressures", ["interest group pressures"]], ["joint-stock company", ["joint stock company"]], ["kidney-dialysis machine", ["kidney dialysis machine"]], ["long-run costs", ["long run costs"]], ["long-term care", ["long term care"]], ["low-income housing", ["low income housing"]], ["mom-and-pop retail outlet", ["mom and pop retail outlet"]], ["mom-and-pop shop", ["mom and pop shop"]], ["national-security briefing", ["national security briefing"]], ["natural-gas pipeline", ["natural gas pipeline"]], ["no-fault accident", ["no fault accident"]], ["no-fault divorce", ["no fault divorce"]], ["no-fault insurance", ["no fault insurance"]], ["odd-numbered", ["odd numbered"]], ["office-supply store", ["office supply store"]], ["one-way flight", ["one way flight"]], ["one-way window", ["one way window"]], ["open-and-shut case", ["open and shut case"]], ["open-and-shut issue", ["open and shut issue"]], ["open-source community", ["open source community"]], ["optical-scan ballot", ["optical scan ballot"]], ["pension-fund investments", ["pension fund investments"]], ["private-sector employment", ["private sector employment"]], ["profit-seeking efforts", ["profit seeking efforts"]], ["punch-card ballot", ["punch card ballot"]], ["quality-adjusted price", ["quality adjusted price"]], ["razor-sharp intellect", ["razor sharp intellect"]], ["razor-sharp mind", ["razor sharp mind"]], ["razor-sharp mind", ["razor sharp mind"]], ["razor-sharp wit", ["razor sharp wit"]], ["larger-than-life personality", ["larger than life personality"]], ["real-estate prices", ["real estate prices"]], ["real-estate tycoon", ["real estate tycoon"]], ["right-wing militia", ["right wing militia"]], ["round-trip flight", ["round trip flight"]], ["search-and-rescue operation", ["search and rescue operation"]], ["second-largest army", ["second largest army"]], ["shell-shocked mothers", ["shell shocked mothers"]], ["shell-shocked soldiers", ["shell shocked soldiers"]], ["small-business loan", ["small business loan"]], ["small-business owner", ["small business owner"]], ["small-state senator", ["small state senator"]], ["small-animal veterinarian", ["small animal veterinarian"]], ["state-sponsored terrorism", ["state sponsored terrorism"]], ["state-sponsored violence", ["state sponsored violence"]], ["thumbs-up sign", ["thumbs up sign"]], ["time-honored tradition", ["time honored tradition"]], ["U.S.-led campaign", ["U.S. led campaign"]], ["upward-sloping line", ["upward sloping line"]], ["venture-backed company", ["venture backed company"]], ["well-publicized event", ["well publicized event"]], ["wire-transfer service", ["wire transfer service"]], ["yes-or-no question", ["yes or no question"]], ["zero-sum game", ["zero sum game"]], ["stained-glass ceiling", ["stained glass ceiling"]], ["stained-glass window", ["stained glass window"]], ["free-range chicken", ["free range chicken"]], ["free-range poultry", ["free range poultry"]], ["non-profit-making organization", ["non profit making organization", "non-profit making organization", "non profit-making organization"]], # Harmony ["three-part harmony", ["three part harmony"]], ["four-part harmony", ["four part harmony"]], ["six-part harmony", ["six part harmony"]], ["eight-part harmony", ["eight part harmony"]], # Losses and gains. ["first-quarter loss", ["first quarter loss"]], ["second-quarter loss", ["second quarter loss"]], ["third-quarter loss", ["third quarter loss"]], ["fourth-quarter loss", ["fourth quarter loss"]], ["first-quarter gain", ["first quarter gain"]], ["second-quarter gain", ["second quarter gain"]], ["third-quarter gain", ["third quarter gain"]], ["fourth-quarter gain", ["fourth quarter gain"]], ] return preferred_forms_check(text, list, err, msg) proselint-0.10.2/proselint/checks/__init__.py0000664000372000037200000000010113331225053022030 0ustar travistravis00000000000000"""All the checks are organized into modules and places here.""" proselint-0.10.2/proselint/checks/hedging/0000775000372000037200000000000013331225202021330 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/hedging/__init__.py0000664000372000037200000000001713331225053023443 0ustar travistravis00000000000000"""Hedging.""" proselint-0.10.2/proselint/checks/hedging/misc.py0000664000372000037200000000106013331225053022636 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Hedging. --- layout: post source: Pinker's book on writing source_url: ??? title: hedging date: 2014-06-10 12:31:19 categories: writing --- Points out hedging. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Suggest the preferred forms.""" err = "hedging.misc" msg = "Hedging. Just say it." narcissism = [ "I would argue that", ", so to speak", "to a certain degree", ] return existence_check(text, narcissism, err, msg) proselint-0.10.2/proselint/checks/oxymorons/0000775000372000037200000000000013331225202022000 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/oxymorons/__init__.py0000664000372000037200000000002113331225053024106 0ustar travistravis00000000000000"""Oxymorons.""" proselint-0.10.2/proselint/checks/oxymorons/misc.py0000664000372000037200000000210613331225053023310 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Oxymorons. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: Oxymorons date: 2014-06-10 12:31:19 categories: writing --- Archaism. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "oxymorons.misc" msg = u"'{}' is an oxymoron." oxymorons = [ "amateur expert", "increasingly less", "advancing backwards?", "alludes explicitly to", "explicitly alludes to", "totally obsolescent", "completely obsolescent", "generally always", "usually always", "increasingly less", "build down", "conspicuous absence", "exact estimate", "found missing", "intense apathy", "mandatory choice", "nonworking mother", "organized mess", # "pretty ugly", # "sure bet", # "executive secretary", ] return existence_check(text, oxymorons, err, msg, offset=1, join=True) proselint-0.10.2/proselint/checks/needless_variants/0000775000372000037200000000000013331225202023434 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/needless_variants/__init__.py0000664000372000037200000000003113331225053025543 0ustar travistravis00000000000000"""Needless variants.""" proselint-0.10.2/proselint/checks/needless_variants/misc.py0000664000372000037200000004225613331225053024756 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Needless variants. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: needless variants date: 2014-06-10 12:31:19 categories: writing --- Points out use of needless variants. """ from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "needless_variants.misc" msg = "Needless variant. '{}' is the preferred form." preferences = [ # Needless variants ["abolition", ["abolishment"]], ["accessory", ["accessary"]], ["accredit", ["accreditate"]], ["accrual", ["accruement"]], ["accumulate", ["cumulate"]], ["accused", ["accusee"]], ["acquaintance", ["acquaintanceship"]], ["acquittal", ["acquitment"]], ["administer", ["administrate"]], ["administered", ["administrated"]], ["administering", ["administrating"]], ["adulterous", ["adulterate"]], ["advisory", ["advisatory"]], ["advocate", ["advocator"]], ["alleger", ["allegator"]], ["allusive", ["allusory"]], ["ameliorate", ["meliorate"]], ["amorous", ["amative"]], ["amortization", ["amortizement"]], ["amphibology", ["amphiboly"]], ["anachronism", ["parachronism"]], ["anecdotist", ["anecdotalist"]], ["anilingus", ["anilinctus"]], ["anticipatory", ["anticipative"]], ["antithetical", ["antithetic"]], ["applicable", ["applicative"]], ["applicable", ["applicatory"]], ["applicator", ["applier"]], ["approbatory", ["approbative"]], ["arbitrageur", ["arbitrager"]], ["arsenious", ["arsenous"]], ["ascendancy", ["ascendance"]], ["ascendancy", ["ascendence"]], ["ascendancy", ["ascendency"]], ["authorial", ["auctorial"]], ["averment", ["averral"]], ["barbed wire", ["barbwire"]], ["beneficent", ["benefic"]], ["benign", ["benignant"]], ["bestowal", ["bestowment"]], ["betrothal", ["betrothment"]], ["blameworthiness", ["blamableness"]], ["buck naked", ["butt naked"]], ["captor", ["capturer"]], ["carte blanche", ["carta blanca"]], ["casualties", ["casualities"]], ["casualty", ["casuality"]], ["catch fire", ["catch on fire"]], ["catholically", ["catholicly"]], ["ceasefire", ["cease fire"]], ["cellphone", ["cell phone", "cell-phone"]], ["channel", ["channelize"]], ["chaplaincy", ["chaplainship"]], ["chrysalis", ["chrysalid"]], ["chrysalises", ["chrysalids"]], ["cigarette", ["cigaret"]], ["cliquish", ["cliquey", "cliquy"]], ["cognitive", ["cognitional"]], ["cohabit", ["cohabitate"]], ["cohabitant", ["cohabitor"]], ["collodion", ["collodium"]], ["collusive", ["collusory"]], ["commemorative", ["commemoratory"]], ["commonage", ["commonty"]], ["communicative", ["communicatory"]], ["compensatory", ["compensative"]], ["complacency", ["complacence"]], ["complicit", ["complicitous"]], ["compute", ["computate"]], ["comrade", ["camarade"]], ["conciliatory", ["conciliative"]], ["concomitance", ["concomitancy"]], ["condonation", ["condonance"]], ["confirmatory", ["confirmative"]], ["congruence", ["congruency"]], ["connote", ["connotate"]], ["consanguine", ["consanguineal"]], ["conspicuousness", ["conspicuity"]], ["conspirator", ["conspiratorialist"]], ["constitutionalist", ["constitutionist"]], ["contemporaneous", ["cotemporaneous"]], ["contemporary", ["cotemporary"]], ["contigency", ["contingence"]], ["contributory", ["contributary"]], ["contumacy", ["contumacity"]], ["convertible", ["conversible"]], ["conveyance", ["conveyal"]], ["corroborative", ["corroboratory"]], ["coworker", ["coemployee"]], ["curative", ["curatory"]], ["daredevilry", ["daredeviltry"]], ["deceptive", ["deceptious"]], ["defamatory", ["defamative"]], ["degenerative", ["degeneratory"]], ["delimit", ["delimitate"]], ["delusive", ["delusory"]], ["denunciation", ["denouncement"]], ["depositary", ["depositee"]], ["depreciatory", ["depreciative"]], ["deprivation", ["deprival"]], ["derogatory", ["derogative"]], ["destructible", ["destroyable"]], ["dethrone", ["disenthrone"]], ["detoxify", ["detoxicate"]], ["detractive", ["detractory"]], ["deuterogamy", ["digamy"]], ["deviance", ["deviancy"]], ["deviant", ["deviationist"]], ["digitize", ["digitalize"]], ["diminution", ["diminishment"]], ["diplomat", ["diplomatist"]], ["disciplinary", ["disciplinatory"]], ["discriminating", ["discriminant"]], ["disintegrative", ["disintegratory"]], ["dismissal", ["dismission"]], ["disorient", ["disorientate"]], ["disoriented", ["disorientated"]], ["disquiet", ["disquieten"]], ["dissociate", ["disassociate"]], ["distrait", ["distraite"]], ["divergence", ["divergency"]], ["divisible", ["dividable"]], ["doctrinaire", ["doctrinary"]], ["documentary", ["documental"]], ["domesticate", ["domesticize"]], ["doubt", ["misdoubt"]], ["duplicative", ["duplicatory"]], ["dutiful", ["duteous"]], ["educationist", ["educationalist"]], ["educative", ["educatory"]], ["empanel", ["impanel"]], ["encumbrance", ["cumbrance"]], ["endow", ["indow"]], ["endue", ["indue"]], ["enigmas", ["enigmatas"]], ["enlarge", ["enlargen"]], ["epic", ["epical"]], ["eroticism", ["erotism"]], ["ethicist", ["ethician"]], ["ex officio", ["ex officiis"]], ["exculpatory", ["exculpative"]], ["exigency", ["exigence"]], ["exigent", ["exigeant"]], ["exoticism", ["exotism"]], ["expediency", ["expedience"]], ["expedient", ["expediential"]], ["expedient", ["expediential"]], ["extendable", ["extensible"]], ["eyeing", ["eying"]], ["fief", ["fiefdom"]], ["flagrancy", ["flagrance"]], ["flatulence", ["flatulency"]], ["fraudulent", ["defraudulent"]], ["fraudulent", ["fraudful"]], ["funereal", ["funebrial"]], ["geographic", ["geographical"]], ["geometric", ["geometrical"]], ["goatherd", ["goatherder"]], ["grievance", ["aggrievance"]], ["gustatory", ["gustatorial"]], ["habit", ["habitude"]], ["henceforth", ["henceforward"]], ["hesitancy", ["hesitance"]], ["heterogeneous", ["heterogenous"]], ["hierarchical", ["hierarchic"]], ["hindmost", ["hindermost"]], ["honoree", ["honorand"]], ["hypostatize", ["hypostasize"]], ["hysterical", ["hysteric"]], ["idolize", ["idolatrize"]], ["impersonation", ["personation"]], ["impervious", ["imperviable"]], ["importunity", ["importunacy"]], ["impotence", ["impotency"]], ["imprimatur", ["imprimatura"]], ["improper", ["improprietous"]], ["incitement", ["incitation"]], ["inconsistency", ["inconsistence"]], ["incriminate", ["criminate"]], ["inculpatory", ["culpatory"]], ["incurrence", ["incurment"]], ["infrequent", ["unfrequent"]], ["inhibitory", ["inhibitive"]], ["innovative", ["innovational"]], ["inquisitorial", ["inquisitional"]], ["insistence", ["insistment"]], ["instillation", ["instillment"]], ["instinctive", ["instinctual"]], ["insubstantial", ["unsubstantial"]], ["insurer", ["insuror"]], ["insurrectionary", ["insurrectional"]], ["interpret", ["interpretate"]], ["intervention", ["intervenience"]], ["ironic", ["ironical"]], ["irrevocable", ["unrevokable"]], ["judgmental", ["judgmatic"]], ["jury-rigged", ["gerry-rigged"]], ["jury-rigged", ["jerry-rigged"]], ["kaffeeklatsch", ["Coffee klatsch", "coffee klatch"]], ["knickknack", ["nicknack"]], ["labyrinthine", ["labyrinthian"]], ["laudatory", ["laudative"]], ["legitimation", ["legitimatization"]], ["legitimation", ["legitimization"]], ["legitimize", ["legitimatize"]], ["lengthwise", ["lengthways"]], ["licorice", ["liquorice"]], ["life-size", ["life-sized"]], ["lithe", ["lithesome"]], ["loath", ["loth"]], ["lollypop", ["lollipop"]], ["lubricious", ["lubricous"]], ["mayhem", ["maihem"]], ["medical marijuana", ["medicinal marijuana"]], ["minimize", ["minimalize"]], ["monetize", ["monetarize"]], ["movable", ["moveable"]], ["murk", ["mirk"]], ["murky", ["mirky"]], ["narcissism", ["narcism"]], ["neglectful", ["neglective"]], ["negligence", ["negligency"]], ["neologist", ["neologizer"]], ["neurological", ["neurologic"]], ["nictitate", ["nictate"]], ["normality", ["normalcy"]], ["numbness", ["numbedness"]], ["omissible", ["omittable"]], ["onomatopoeic", ["onomatopoetic"]], ["opined", ["opinioned"]], ["optimal advantage", ["optimum advantage"]], ["orient", ["orientate"]], ["outsize", ["outsized"]], ["oversize", ["oversized"]], ["overthrow", ["overthrowal"]], ["pacifist", ["pacificist"]], ["parti-colored", ["parti-color"]], ["parti-colored", ["party-colored"]], ["participatory", ["participative"]], ["partner", ["copartner"]], ["partnership", ["copartnership"]], # ["password", ["passcode"]], # FIXME ["patina", ["patine"]], ["pederast", ["paederast"]], ["pediatrician", ["pediatrist"]], ["pejorative", ["perjorative"]], ["penumbral", ["penumbrous"]], ["permissive", ["permissory"]], ["permute", ["permutate"]], ["pharmaceutical", ["pharmaceutic"]], ["pleurisy", ["pleuritis"]], ["policyholder", ["policy holder"]], ["policyholder", ["policyowner"]], ["politicize", ["politicalize"]], ["pre-Columbian", ["precolumbian"]], ["precedence", ["precedency"]], ["preceptorial", ["preceptoral"]], ["precipitancy", ["precipitance"]], ["precipitate", ["precipitant"]], ["preclusive", ["preclusory"]], ["prefectorial", ["prefectoral"]], ["preponderantly", ["preponderately"]], ["preservation", ["preserval"]], ["preventive", ["preventative"]], ["proconsulate", ["proconsulship"]], ["procreative", ["procreational"]], ["procurement", ["procurance"]], ["propulsion", ["propelment"]], ["propulsive", ["propulsory"]], ["prosecutory", ["prosecutive"]], ["protective", ["protectory"]], ["provocative", ["provocatory"]], ["prurience", ["pruriency"]], ["psychical", ["psychal"]], ["punitive", ["punitory"]], ["pygmy", ["pygmean", "pygmaen"]], ["quantify", ["quantitate"]], ["questionnaire", ["questionary"]], ["quiescence", ["quiescency"]], ["rabbi", ["rabbin"]], ["reasonableness", ["reasonability"]], ["recidivous", ["recidivistic"]], ["recriminatory", ["recriminative"]], ["recruitment", ["recruital"]], ["recurrence", ["recurrency"]], ["recusal", ["recusation"]], ["recusal", ["recusement"]], ["recusancy", ["recusance"]], ["redemptive", ["redemptory"]], ["referable", ["referrable"]], ["referable", ["referrible"]], ["refutative", ["refutatory"]], ["remission", ["remittal"]], ["remittance", ["remitment"]], ["renounceable", ["renunciable"]], ["renunciation", ["renouncement"]], ["reparative", ["reparatory"]], ["repudiatory", ["repudiative"]], ["requital", ["requitement"]], ["rescission", ["rescindment"]], ["restoration", ["restoral"]], ["reticence", ["reticency"]], ["retributive", ["retributional", "retributionary"]], ["review", ["reviewal"]], ["revision", ["revisal"]], ["revisionary", ["revisional"]], ["revocable", ["revokable", "revokeable"]], ["revolt", ["revolute"]], ["salience", ["saliency"]], ["salutary", ["salutiferous"]], ["sensory", ["sensatory"]], ["sessional", ["sessionary"]], ["shareholder", ["shareowner"]], ["sickly", ["sicklily"]], ["signatory", ["signator"]], ["slander", ["slanderize"]], ["societal", ["societary"]], ["sodomite", ["sodomist"]], ["solicit", ["solicitate"]], ["speculative", ["speculatory"]], ["spirituous", ["spiritous"]], ["statutory", ["statutorial"]], ["submersible", ["submergeable"]], ["submission", ["submittal"]], ["subtle", ["subtile"]], ["succubus", ["succuba"]], ["sufficiency", ["sufficience"]], ["supplicant", ["suppliant"]], ["surmise", ["surmisal"]], ["suspendable", ["suspendible"]], ["swathe", ["enswathe"]], ["synthesize", ["synthetize"]], ["systematize", ["systemize"]], ["T-shirt", ["tee-shirt"]], ["tactile", ["tactual"]], ["tangential", ["tangental"]], ["tautological", ["tautologous"]], ["thenceforth", ["thenceforward"]], ["transience", ["transiency"]], ["transposition", ["transposal"]], ["transposition", ["transposal"]], ["unalterable", ["inalterable"]], ["uncommunicative", ["incommunicative"]], ["uncontrollable", ["incontrollable"]], ["unenforceable", ["nonenforceable"]], ["unnavigable", ["innavigable"]], ["unreasonableness", ["unreasonability"]], ["unsolvable", ["insolvable"]], ["usurpation", ["usurpature"]], ["variational", ["variative"]], ["vegetative", ["vegetive"]], ["vindictive", ["vindicative"]], ["vituperative", ["vituperous"]], ["vociferous", ["vociferant"]], ["volitional", ["volitive"]], ["wolfish", ["wolvish"]], ["wolverine", ["wolverene"]], ["Zoroastrianism", ["Zoroastrism"]], ] return preferred_forms_check(text, preferences, err, msg) proselint-0.10.2/proselint/checks/psychology/0000775000372000037200000000000013331225202022123 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/psychology/__init__.py0000664000372000037200000000003113331225053024232 0ustar travistravis00000000000000"""Advice on science.""" proselint-0.10.2/proselint/checks/psychology/misc.py0000664000372000037200000000260413331225053023436 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Psychological and psychiatric terms to avoid. --- layout: post source: Scott O. Lilienfeld, et al. source_url: http://dx.doi.org/10.3389/fpsyg.2015.01100 title: psychological and psychiatric terms to avoid date: 2014-06-10 12:31:19 categories: writing --- Psychological and psychiatric terms to avoid. """ from proselint.tools import preferred_forms_check, existence_check, memoize @memoize def check_lie_detector_test(text): """Suggest the preferred forms.""" err = "psychology.lie_detector" msg = "Polygraph machines measure arousal, not lying per se. Try {}." list = [ ["polygraph test", ["lie detector test"]], ["polygraph machine", ["lie detector machine"]], ] return preferred_forms_check(text, list, err, msg) @memoize def check_p_equals_zero(text): """Check for p = 0.000.""" err = "psychology.p_equals_zero" msg = "Unless p really equals zero, you should use more decimal places." list = [ "p = 0.00", "p = 0.000", "p = 0.0000", ] return existence_check(text, list, err, msg, join=True) @memoize def check_mental_telepathy(text): """Check for 'mental telepathy'.""" err = "psychology.mental_telepathy" msg = "This is redundant because all purported telepathy is mental." return existence_check(text, ["mental telepathy"], err, msg) proselint-0.10.2/proselint/checks/lexical_illusions/0000775000372000037200000000000013331225202023445 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/lexical_illusions/__init__.py0000664000372000037200000000003113331225053025554 0ustar travistravis00000000000000"""Lexical illusions.""" proselint-0.10.2/proselint/checks/lexical_illusions/misc.py0000664000372000037200000000124513331225053024760 0ustar travistravis00000000000000"""Lexical illusions. --- layout: post source: write-good source_url: https://github.com/btford/write-good title: Lexical illusion present date: 2014-06-10 12:31:19 categories: writing --- A lexical illusion is when a word word is unintentionally repeated twice, and and this happens most often between line breaks. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "lexical_illusions.misc" msg = u"There's a lexical illusion here: a word is repeated." list = [ "the\sthe", "am\sam", "has\shas" ] return existence_check(text, list, err, msg) proselint-0.10.2/proselint/checks/annotations/0000775000372000037200000000000013331225202022260 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/annotations/__init__.py0000664000372000037200000000002313331225053024370 0ustar travistravis00000000000000"""Annotations.""" proselint-0.10.2/proselint/checks/annotations/misc.py0000664000372000037200000000122413331225053023570 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Annotation left in text. --- layout: post source: SublimeLinter-annotations source_url: http://bit.ly/16Q7H41 title: archaism date: 2014-06-10 12:31:19 categories: writing --- Annotation left in text. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "misc.annotations" msg = u"Annotation left in text." annotations = [ "FIXME", "FIX ME", "TODO", "todo", "ERASE THIS", "FIX THIS", ] return existence_check( text, annotations, err, msg, ignore_case=False, join=True) proselint-0.10.2/proselint/checks/corporate_speak/0000775000372000037200000000000013331225202023104 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/corporate_speak/__init__.py0000664000372000037200000000003013331225053025212 0ustar travistravis00000000000000u"""Corporate-speak.""" proselint-0.10.2/proselint/checks/corporate_speak/misc.py0000664000372000037200000000241413331225053024416 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Corporate speak. --- layout: post source: Travis Bradberry for Inc.com source_url: http://bit.ly/1IxWnto title: corporate speak date: 2014-06-10 12:31:19 categories: writing --- Avoid these cases of business jargon. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "corporate_speak.misc" msg = u"Minimize your use of corporate catchphrases like this one." list = [ "at the end of the day", "back to the drawing board", "hit the ground running", "get the ball rolling", "low-hanging fruit", "thrown under the bus", "think outside the box", "let's touch base", "get my manager's blessing", "it's on my radar", "ping me", "i don't have the bandwidth", "no brainer", "par for the course", "bang for your buck", "synergy", "move the goal post", "apples to apples", "win-win", "circle back around", "all hands on deck", "take this offline", "drill-down", "elephant in the room", "on my plate", ] return existence_check(text, list, err, msg, ignore_case=True) proselint-0.10.2/proselint/checks/malapropisms/0000775000372000037200000000000013331225202022432 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/malapropisms/__init__.py0000664000372000037200000000002513331225053024544 0ustar travistravis00000000000000"""Malaproprisms.""" proselint-0.10.2/proselint/checks/malapropisms/misc.py0000664000372000037200000000112713331225053023744 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Malaproprisms. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: Malaproprisms date: 2014-06-10 12:31:19 categories: writing --- Archaism. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "malapropisms.misc" msg = u"'{}' is a malapropism." illogics = [ "the infinitesimal universe", "a serial experience", "attack my voracity", ] return existence_check(text, illogics, err, msg, offset=1) proselint-0.10.2/proselint/checks/hyperbole/0000775000372000037200000000000013331225202021714 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/hyperbole/__init__.py0000664000372000037200000000002113331225053024022 0ustar travistravis00000000000000"""Hyperbole.""" proselint-0.10.2/proselint/checks/hyperbole/misc.py0000664000372000037200000000077113331225053023232 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Hyperbolic language. --- layout: post source: ??? source_url: ??? title: hyperbolic language date: 2014-06-10 12:31:19 categories: writing --- Hyperbolic language. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "hyperbolic.misc" msg = u"'{}' is hyperbolic." words = [ "[a-z]*[!]{2,}", "[a-z]*\?{2,}" ] return existence_check(text, words, err, msg) proselint-0.10.2/proselint/checks/spelling/0000775000372000037200000000000013331225202021540 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/spelling/able_atable.py0000664000372000037200000000716013331225053024335 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """-able vs. -atable.""" from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """-able vs. -atable.""" err = "spelling.able_atable" msg = "-able vs. -atable. '{}' is the preferred spelling." preferences = [ ["abbreviable", ["abbreviatable"]], ["abdicable", ["abdicatable"]], ["abrogable", ["abrogatable"]], ["accommodable", ["accommodatable"]], ["accumulable", ["accumulatable"]], ["activable", ["activatable"]], ["administrable", ["administratable"]], ["adulterable", ["adulteratable"]], ["affiliable", ["affiliatable"]], ["aggregable", ["aggregatable"]], ["agitable", ["agitatable"]], ["alienable", ["alienatable"]], ["alleviable", ["alleviatable"]], ["allocable", ["allocatable"]], ["ameliorable", ["amelioratable"]], ["annihilable", ["annihilatable"]], ["appreciable", ["appreciatable"]], ["appropriable", ["appropriatable"]], ["arbitrable", ["arbitratable"]], ["articulable", ["articulatable"]], ["calculable", ["calculatable"]], ["communicable", ["communicatable"]], ["compensable", ["compensatable"]], ["confiscable", ["confiscatable"]], ["corroborable", ["corroboratable"]], ["cultivable", ["cultivatable"]], ["delegable", ["delegatable"]], ["delineable", ["delineatable"]], ["demonstrable", ["demonstratable"]], ["detonable", ["detonatable"]], ["differentiable", ["differentiatable"]], ["eradicable", ["eradicatable"]], ["evacuable", ["evacuatable"]], ["evaluable", ["evaluatable"]], ["expropriable", ["expropriatable"]], ["generable", ["generatable"]], ["indicable", ["indicatable"]], ["inebriable", ["inebriatable"]], ["inextirpable", ["inextirpatable"]], ["inextricable", ["inextricatable"]], ["infatuable", ["infatuatable"]], ["infuriable", ["infuriatable"]], ["invalidable", ["invalidatable"]], ["investigable", ["investigatable"]], ["isolable", ["isolatable"]], ["litigable", ["litigatable"]], ["manipulable", ["manipulatable"]], ["medicable", ["medicatable"]], ["navigable", ["navigatable"]], ["obligable", ["obligatable"]], ["obviable", ["obviatable"]], ["operable", ["operatable"]], ["originable", ["originatable"]], ["participable", ["participatable"]], ["penetrable", ["penetratable"]], ["perpetrable", ["perpetratable"]], ["perpetuable", ["perpetuatable"]], ["predicable", ["predicatable"]], ["propagable", ["propagatable"]], ["regulable", ["regulatable"]], ["replicable", ["replicatable"]], ["repudiable", ["repudiatable"]], ["segregable", ["segregatable"]], ["separable", ["separatable"]], ["subjugable", ["subjugatable"]], ["vindicable", ["vindicatable"]], ["violable", ["violatable"]], ["vitiable", ["vitiatable"]] ] return preferred_forms_check(text, preferences, err, msg) proselint-0.10.2/proselint/checks/spelling/er_or.py0000664000372000037200000000275413331225053023234 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """-er vs. -or.""" from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """-er vs. -or.""" err = "spelling.er_or" msg = "-er vs. -or. '{}' is the preferred spelling." preferences = [ ["abductor", ["abducter"]], ["abettor", ["abbeter"]], ["acquirer", ["acquiror"]], ["adapter", ["adaptor"]], ["collector", ["collecter"]], ["conjurer", ["conjuror"]], ["corrupter", ["corruptor"]], ["digester", ["digestor"]], ["dispenser", ["dispensor"]], ["distributor", ["distributer"]], ["endorser", ["endorsor"]], ["eraser", ["erasor"]], ["idolater", ["idolator"]], ["impostor", ["imposter"]], ["infiltrator", ["infiltrater"]], ["investor", ["invester"]], ["manipulator", ["manipulater"]], ["mortgagor", ["mortgager"]], ["persecutor", ["persecuter"]], ["promoter", ["promotor"]], ["promoter", ["promotor"]], ["purveyor", ["purveyer"]], ["requester", ["requestor"]], ["reviser", ["revisor"]], ["surveyor", ["surveyer"]], ] return preferred_forms_check(text, preferences, err, msg) proselint-0.10.2/proselint/checks/spelling/able_ible.py0000664000372000037200000001630713331225053024023 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """-able vs. -ible.""" from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """-able vs. -ible.""" err = "spelling.able_ible" msg = "-able vs. -ible. '{}' is the preferred spelling." preferences = [ ["actionable", ["actionible"]], ["addable", ["addible"]], ["admittable", ["admittible"]], ["advisable", ["advisible"]], ["affectable", ["affectible"]], ["allegeable", ["allegeible"]], ["analyzable", ["analyzible"]], ["annexable", ["annexible"]], ["arrestable", ["arrestible"]], ["ascendable", ["ascendible"]], ["assertable", ["assertible"]], ["assessable", ["assessible"]], ["averageable", ["averageible"]], ["bailable", ["bailible"]], ["blamable", ["blamible"]], ["changeable", ["changeible"]], ["chargeable", ["chargeible"]], ["circumscribable", ["circumscribible"]], ["commensurable", ["commensurible"]], ["committable", ["committible"]], ["condensable", ["condensible"]], ["connectable", ["connectible"]], ["contestable", ["contestible"]], ["contractable", ["contractible"]], ["conversable", ["conversible"]], ["convictable", ["convictible"]], ["correctable", ["correctible"]], ["definable", ["definible"]], ["detectable", ["detectible"]], ["diagnosable", ["diagnosible"]], ["discussable", ["discussible"]], ["endorsable", ["endorsible"]], ["enforceable", ["enforceible"]], ["evadable", ["evadible"]], ["excisable", ["excisible"]], ["excludable", ["excludible"]], ["expandable", ["expandible"]], ["extendable", ["extendible"]], ["extractable", ["extractible"]], ["ignitable", ["ignitible"]], ["immovable", ["immovible"]], ["improvable", ["improvible"]], ["includable", ["includible"]], ["inferable", ["inferible"]], ["inventable", ["inventible"]], ["investable", ["investible"]], ["lapsable", ["lapsible"]], ["lovable", ["lovible"]], ["mixable", ["mixible"]], ["movable", ["movible"]], ["noticeable", ["noticeible"]], ["offendable", ["offendible"]], ["patentable", ["patentible"]], ["persuadable", ["persuadible"]], ["preventable", ["preventible"]], ["processable", ["processible"]], ["protectable", ["protectible"]], ["ratable", ["ratible"]], ["redressable", ["redressible"]], ["referable", ["referible"]], ["retractable", ["retractible"]], ["revisable", ["revisible"]], ["rinsable", ["rinsible"]], ["salable", ["salible"]], ["suspendable", ["suspendible"]], ["tractable", ["tractible"]], ["transferable", ["transferible"]], ["transmittable", ["transmittible"]], ["willable", ["willible"]], ["accessible", ["accessable"]], ["adducible", ["adducable"]], ["admissible", ["admissable"]], ["audible", ["audable"]], ["avertible", ["avertable"]], ["collapsible", ["collapsable"]], ["collectible", ["collectable"]], ["combustible", ["combustable"]], ["compactible", ["compactable"]], ["compatible", ["compatable"]], ["comprehensible", ["comprehensable"]], ["compressible", ["compressable"]], ["concussible", ["concussable"]], ["conductible", ["conductable"]], ["contemptible", ["contemptable"]], ["controvertible", ["controvertable"]], ["convertible", ["convertable"]], ["corrodible", ["corrodable"]], ["corruptible", ["corruptable"]], ["credible", ["credable"]], ["deducible", ["deducable"]], ["deductible", ["deductable"]], ["defeasible", ["defeasable"]], ["defensible", ["defensable"]], ["descendible", ["descendable"]], ["destructible", ["destructable"]], ["diffusible", ["diffusable"]], ["digestible", ["digestable"]], ["discernible", ["discernable"]], ["dismissible", ["dismissable"]], ["divisible", ["divisable"]], ["edible", ["edable"]], ["educible", ["educable"]], ["eligible", ["eligable"]], ["erodible", ["erodable"]], ["exhaustible", ["exhaustable"]], ["expressible", ["expressable"]], ["fallible", ["fallable"]], ["feasible", ["feasable"]], ["flexible", ["flexable"]], ["forcible", ["forcable"]], ["fusible", ["fusable"]], ["gullible", ["gullable"]], ["horrible", ["horrable"]], ["impressible", ["impressable"]], ["inadmissible", ["inadmissable"]], ["incorrigible", ["incorrigable"]], ["indelible", ["indelable"]], ["inexpressible", ["inexpressable"]], ["intelligible", ["intelligable"]], ["interfusible", ["interfusable"]], ["invincible", ["invincable"]], ["irascible", ["irascable"]], ["irresistible", ["irresistable"]], ["legible", ["legable"]], ["negligible", ["negligable"]], ["omissible", ["omissable"]], ["oppressible", ["oppressable"]], ["ostensible", ["ostensable"]], ["perceptible", ["perceptable"]], ["perfectible", ["perfectable"]], ["permissible", ["permissable"]], ["plausible", ["plausable"]], ["possible", ["possable"]], ["producible", ["producable"]], ["reducible", ["reducable"]], ["remissible", ["remissable"]], ["reprehensible", ["reprehensable"]], ["repressible", ["repressable"]], ["resistible", ["resistable"]], ["responsible", ["responsable"]], ["reversible", ["reversable"]], ["revertible", ["revertable"]], ["risible", ["risable"]], ["seducible", ["seducable"]], ["sensible", ["sensable"]], ["submersible", ["submersable"]], ["submergible", ["submergable"]], ["suggestible", ["suggestable"]], ["suppressible", ["suppressable"]], ["susceptible", ["susceptable"]], ["terrible", ["terrable"]], ["transfusible", ["transfusable"]], ["transmissible", ["transmissable"]], ["uncollectible", ["uncollectable"]], ["vendible", ["vendable"]], ["visible", ["visable"]] ] return preferred_forms_check(text, preferences, err, msg) proselint-0.10.2/proselint/checks/spelling/__init__.py0000664000372000037200000000002013331225053023645 0ustar travistravis00000000000000"""Spelling.""" proselint-0.10.2/proselint/checks/spelling/misc.py0000664000372000037200000001431213331225053023052 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Misspellings. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: misspellings date: 2014-06-10 12:31:19 categories: writing --- Points out misspellings. """ from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "spelling.misc" msg = "Misspelling. '{}' is the preferred spelling." misspellings = [ ["a lot", ["alot"]], ["academically", ["academicly"]], ["accidentally", ["accidently"]], ["accommodable", ["accomodatable"]], ["anilingus", ["analingus"]], ["aren't i", ["amn't i"]], ["aren't i", ["an't i"]], ["barbed wire", ["bob wire"]], ["chargeable", ["chargable"]], ["chiffonier", ["chiffonnier"]], ["chintzy", ["chinchy"]], ["chipotle", ["chipolte"]], ["chlorophyll", ["chlorophyl"]], ["chocolaty", ["chocolatey"]], ["chronicle", ["chronical"]], ["chronicles", ["chronicals"]], ["coleslaw", ["coldslaw"]], ["choosy", ["choosey"]], ["cummerbund", ["kummerbund"]], ["financeable", ["financable"]], ["fluorescent", ["flourescent"]], ["fluoridation", ["flouridation"]], ["fluoride", ["flouride"]], ["foreclose", ["forclose"]], ["forswear", ["foreswear"]], ["free rein", ["free reign"]], ["gist", ["jist"]], ["glamour", ["glamor"]], ["granddad", ["grandad"]], ["grandpa", ["granpa"]], ["highfalutin", ["highfaluting", "highfalutin'", "hifalutin"]], ["Hippocratic", ["hypocratic"]], ["hirable", ["hireable"]], ["holistic", ["wholistic"]], ["ideology", ["idealogy"]], ["idiosyncrasy", ["ideosyncracy"]], ["improvise", ["improvize"]], ["incurrence", ["incurment"]], ["inevitability", ["inevitableness"]], ["innovate", ["inovate"]], ["inoculation", ["innoculation", "inocculation"]], ["integral", ["intergral"]], ["inundate", ["innundate"]], ["inundated", ["innundated"]], ["inundates", ["innundates"]], ["inundating", ["innundating"]], ["iridescent", ["irridescent"]], ["irrelevant", ["irrevelant"]], ["jujitsu", ["jiujutsu"]], ["kaleidoscope", ["kaleidascope"]], ["knickknack", ["knicknack"]], ["lassos", ["lassoes"]], ["lessee", ["leasee"]], ["lessor", ["leasor"]], ["liaison", ["liason"]], ["liaison", ["laison"]], ["lightning rod", ["lightening rod"]], ["struck by lightning", ["struck by lightening"]], ["liquefy", ["liquify"]], ["loathsome", ["loathesome"]], ["lodestar", ["loadstar"]], ["to make do", ["to make due"]], ["mademoiselle", ["madamoiselle"]], ["martial arts", ["marshall arts"]], ["court-martial", ["court marshall", "court-marshall"]], ["maelstrom", ["maelstorm"]], ["mafia", ["maffia"]], ["mafiosi", ["mafiosos"]], ["mangoes", ["mangos"]], ["marijuana", ["marihuana"]], ["marshmallow", ["marshmellow"]], ["martial law", ["marshall law"]], ["massacring", ["massacering", "massacreing"]], ["measles", ["measels"]], ["memento", ["momento"]], ["minuscule", ["miniscule"]], ["mileage", ["milage"]], ["milieu", ["mileau"]], ["millennium", ["millenium"]], ["millennia", ["millenia"]], ["millenniums", ["milleniums"]], ["millipede", ["millepede"]], ["millionaire", ["millionnaire"]], ["milquetoast", ["milktoast"]], ["mimicked", ["mimiced"]], ["mimicking", ["mimicing"]], ["misspelling", ["mispelling"]], ["mischievous", ["mischievious"]], ["moccasin", ["mocasin", "moccassin", "mocassin"]], ["monologue", ["monolog"]], ["monologuist", ["monologist"]], ["naphtha", ["naptha"]], ["navel orange", ["naval orange"]], ["neckwear", ["neckware"]], ["newsstand", ["newstand"]], ["non sequitur", ["non sequiter", "non sequitar", "non sequitor"]], ["nouveau riche", ["nouveau rich"]], ["occurred", ["occured"]], ["plantar fasciitis", ["planter fasciitis", "plantar fascitis"]], ["pledgeable", ["pledgable", "pledgeble"]], ["portentous", ["portentuous", "portentious"]], ["praying mantis", ["preying mantis"]], ["preestablished", ["prestablished"]], ["preexisting", ["prexisting"]], ["presumptuous", ["presumptious"]], ["rarefy", ["rarify"]], ["reckless", ["wreckless"]], ["remuneration", ["renumeration"]], ["restaurateur", ["restauranteur"]], ["retractable", ["retractible"]], ["reverie", ["revery"]], ["spicy", ["spicey"]], ["stupefy", ["stupify"]], ["subtly", ["subtley"]], ["till", ["\'till?"]], ["tinderbox", ["tenderbox"]], ["timpani", ["tympani"]], ["a timpani", ["a timpano"]], ["umpteenth", ["umteenth"]], ["verbiage", ["verbage"]], ] return preferred_forms_check(text, misspellings, err, msg) proselint-0.10.2/proselint/checks/spelling/em_im_en_in.py0000664000372000037200000000427113331225053024360 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Em vs. im, en vs. in.""" from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """em- vs. en-, im- vs. in-.""" err = "spelling.em_im_en_in" msg = "em-, im-, en-, and in-. '{}' is the preferred spelling." preferences = [ ["embalm", ["imbalm"]], ["embark", ["imbark"]], ["embed", ["imbed"]], ["embitter", ["imbitter"]], ["emblaze", ["imblaze"]], ["embody", ["imbody"]], ["embolden", ["imbolden"]], ["embosom", ["imbosom"]], ["embower", ["imbower"]], ["embrown", ["imbrown"]], ["empanel", ["impanel"]], ["empower", ["impower"]], ["encage", ["incage"]], ["encapsulate", ["incapsulate"]], ["encase", ["incase"]], ["enclasp", ["inclasp"]], ["encumber", ["incumber"]], ["encumbrance", ["incumbrance"]], ["endow", ["indow"]], ["endowment", ["indowment"]], ["endue", ["indue"]], ["enfold", ["infold"]], ["engraft", ["ingraft"]], ["engulf", ["ingulf"]], ["enlace", ["inlace"]], ["enmesh", ["inmesh"]], ["ensheathe", ["insheathe"]], ["enshrine", ["inshrine"]], ["ensnare", ["insnare"]], ["ensoul", ["insoul"]], ["ensphere", ["insphere"]], ["enthrall", ["inthrall"]], ["enthrone", ["inthrone"]], ["entitle", ["intitle"]], ["entomb", ["intomb"]], ["entreat", ["intreat"]], ["entrench", ["intrench"]], ["entrust", ["intrust"]], ["entwine", ["intwine"]], ["entwist", ["intwist"]], ["enwind", ["inwind"]], ["enwrap", ["inwrap"]], ["enwreathe", ["inwreathe"]], ["imbrue", ["embrue"]], ["impale", ["empale"]], ["impoverish", ["empoverish"]], ["inflame", ["enflame"]], ["ingrain", ["engrain"]], ["inure", ["enure"]], ] return preferred_forms_check(text, preferences, err, msg) proselint-0.10.2/proselint/checks/spelling/in_un.py0000664000372000037200000000102113331225053023220 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """in- vs. un-.""" from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """in- vs un-.""" err = "spelling.in_un" msg = "in- vs. un-. '{}' is the preferred spelling." preferences = [ ["inadvisable", ["unadvisable"]], ["inalienable", ["unalienable"]], ["inexpressive", ["unexpressive"]], ["infeasible", ["unfeasible"]], ] return preferred_forms_check(text, preferences, err, msg) proselint-0.10.2/proselint/checks/spelling/athletes.py0000664000372000037200000000265413331225053023736 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Misspellings. --- layout: post source: The Wall Street Journal source_url: http://on.wsj.com/1rksm8k title: misspellings date: 2014-06-10 12:31:19 categories: writing --- Points out misspellings. """ from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "spelling.athletes" msg = "Misspelling of athlete's name. '{}' is the preferred form." misspellings = [ ["Dwyane Wade", ["Dwayne Wade"]], ["Miikka Kiprusoff", ["Mikka Kiprusoff"]], ["Mark Buehrle", ["Mark Buerhle"]], ["Skylar Diggins", ["Skyler Diggins"]], ["Agnieszka Radwanska", ["Agnieska Radwanska"]], ["J.J. Redick", ["J.J. Reddick"]], ["Manny Pacquiao", ["Manny Packquaio"]], ["Antawn Jamison", ["Antwan Jamison"]], ["Cal Ripken", ["Cal Ripkin"]], ["Jhonny Peralta", ["Johnny Peralta"]], ["Monta Ellis", ["Monte Ellis"]], ["Alex Rodriguez", ["Alex Rodriquez"]], ["Mark Teixeira", ["Mark Texeira"]], ["Brett Favre", ["Brett Farve"]], ["Torii Hunter", ["Tori Hunter"]], ["Stephen Curry", ["Stephon Curry"]], ["Mike Krzyzewski", ["Mike Kryzewski"]], ] return preferred_forms_check(text, misspellings, err, msg) proselint-0.10.2/proselint/checks/uncomparables/0000775000372000037200000000000013331225202022556 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/uncomparables/__init__.py0000664000372000037200000000004113331225053024666 0ustar travistravis00000000000000"""Comparing an uncomparable.""" proselint-0.10.2/proselint/checks/uncomparables/misc.py0000664000372000037200000001021713331225053024070 0ustar travistravis00000000000000# -*- coding: utf-8 -*- u"""Comparing uncomparables. --- layout: post source: David Foster Wallace source_url: http://www.telegraph.co.uk/a/9715551 title: Comparing an uncomparable date: 2014-06-10 12:31:19 categories: writing --- David Foster Wallace says: > This is one of a class of adjectives, sometimes called “uncomparables”, that can be a little tricky. Among other uncomparables are precise, exact, correct, entire, accurate, preferable, inevitable, possible, false; there are probably two dozen in all. These adjectives all describe absolute, non-negotiable states: something is either false or it’s not; something is either inevitable or it’s not. Many writers get careless and try to modify uncomparables with comparatives like more and less or intensives like very. But if you really think about them, the core assertions in sentences like “War is becoming increasingly inevitable as Middle East tensions rise”; “Their cost estimate was more accurate than the other firms’”; and “As a mortician, he has a very unique attitude” are nonsense. If something is inevitable, it is bound to happen; it cannot be bound to happen and then somehow even more bound to happen. Unique already means one-of-a-kind, so the adj. phrase very unique is at best redundant and at worst stupid, like “audible to the ear” or “rectangular in shape”. You can blame the culture of marketing for some of this difficulty. As the number and rhetorical volume of US ads increase, we become inured to hyperbolic language, which then forces marketers to load superlatives and uncomparables with high-octane modifiers (special - very special - Super-special! - Mega-Special!!), and so on. A deeper issue implicit in the problem of uncomparables is the dissimilarities between Standard Written English and the language of advertising. Advertising English, which probably deserves to be studied as its own dialect, operates under different syntactic rules than SWE, mainly because AE’s goals and assumptions are different. Sentences like “We offer a totally unique dining experience”; “Come on down and receive your free gift”; and “Save up to 50 per cent… and more!” are perfectly OK in Advertising English — but this is because Advertising English is aimed at people who are not paying close attention. If your audience is by definition involuntary, distracted and numbed, then free gift and totally unique stand a better chance of penetrating — and simple penetration is what AE is all about. One axiom of Standard Written English is that your reader is paying close attention and expects you to have done the same. """ import re from proselint.tools import memoize import itertools @memoize def check(text): """Check the text.""" err = "uncomparables.misc" msg = "Comparison of an uncomparable: '{}' is not comparable." comparators = [ "most", "more", "less", "least", "very", "quite", "largely", "extremely", "increasingly", "kind of", "mildly" ] uncomparables = [ "absolute", "adequate", "chief", "complete", "correct", "devoid", "entire", "false", "fatal", "favorite", "final", "ideal", "impossible", "inevitable", "infinite", "irrevocable", "main", "manifest", "only", "paramount", "perfect", "perpetual", "possible", "preferable", "principal", "singular", "stationary", "sufficient", "true", "unanimous", "unavoidable", "unbroken", "uniform", "unique", "universal", "void", "whole", ] exceptions = [ ("more", "perfect"), ("more", "possible") # FIXME ] all = ["\\b" + i[0] + "\s" + i[1] + "[\W$]" for i in itertools.product( comparators, uncomparables) if i not in exceptions] occ = re.finditer("|".join(all), text.lower()) return [(o.start(), o.end(), err, msg.format(o.group(0)), None) for o in occ] proselint-0.10.2/proselint/checks/redundancy/0000775000372000037200000000000013331225202022057 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/redundancy/__init__.py0000664000372000037200000000002213331225053024166 0ustar travistravis00000000000000"""Redundancy.""" proselint-0.10.2/proselint/checks/redundancy/misc.py0000664000372000037200000006076513331225053023406 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Redundancy.""" from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "redundancy.wallace" msg = "Redundancy. Use '{}' instead of '{}'." redundancies = [ ["rectangular", ["rectangular in shape"]], ["audible", ["audible to the ear"]], ] return preferred_forms_check(text, redundancies, err, msg) @memoize def check_garner(text): """Suggest the preferred forms. source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY """ err = "redundancy.garner" msg = "Redundancy. Use '{}' instead of '{}'." redundancies = [ ["adequate", ["adequate enough"]], ["admitted", ["self-admitted"]], ["affidavit", ["sworn affidavit"]], ["agreement", ["mutual agreement"]], ["alumnus", ["former alumnus"]], ["antithetical", ["directly antithetical"]], ["approximately", ["approximately about"]], ["associate", ["associate together(?: in groups)?"]], ["bivouac", ["temporary bivouac", "bivouac camp"]], ["blend", ["blend together"]], ["but", ["but nevertheless"]], ["charged with...", ["accused of a charge"]], ["circumstances of", ["circumstances surrounding"]], ["circumstances", ["surrounding circumstances"]], ["close", ["close proximity"]], ["collaborate", ["collaborate together"]], ["collaborator", ["fellow collaborator"]], ["collaborators", ["fellow collaborators"]], ["collocated", ["collocated together"]], ["colleagues", ["fellow colleagues"]], ["combine", ["combine together"]], ["complacent", ["self-complacent"]], ["confessed", ["self-confessed"]], ["connect", ["connect together"]], ["consensus", ["(?:general )?consensus of opinion"]], ["consolidate", ["consolidate together"]], ["continues to", ["still continues to"]], ["contradictory", ["mutually contradictory"]], ["cooperation", ["mutual cooperation"]], ["couple", ["couple together"]], ["crisis", ["serious crisis"]], ["eliminate", ["entirely eliminate"]], ["especially", ["most especially"]], ["fact", ["actual fact"]], ["facts", ["true facts"]], ["forecast", ["future forecast"]], ["founding fathers", ["founding forefathers"]], ["free", ["free and gratis"]], ["free", ["free gratis"]], ["full", ["completely full"]], ["fundamentals", ["basic fundamentals"]], ["gift", ["free gift"]], ["innovation", ["new innovation"]], ["interact", ["interact with each other"]], ["large", ["large-size"]], ["meld", ["meld together"]], ["merge", ["merge together"]], ["mingle", ["mingle together"]], ["mix", ["mix together"]], ["mutual feelings", ["mutual feelings for eachother"]], ["mutual respect", ["mutual respect for each other"]], ["native citizen", ["native-born citizen"]], ["necessity", ["absolute necessity"]], ["obvious", ["blatantly obvious"]], ["pause", ["pause for a moment"]], ["planning", ["advance planning"]], ["plans", ["future plans"]], ["pooled", ["pooled together"]], ["potable water", ["potable drinking water"]], ["potable water", ["potable drinking water"]], ["recruit", ["new recruit"]], ["reelected", ["reelected for another term"]], ["refer", ["refer back"]], ["regress", ["regress back"]], ["repay them", ["repay them back"]], ["repay", ["repay back"]], ["repeat", ["repeat again"]], ["repeat", ["repeat back"]], ["repeat", ["repeat the same"]], ["repeated", ["repeated the same"]], ["reprieve", ["temporary reprieve"]], ["respite", ["brief respite"]], ["retirement", ["retiral", "retiracy"]], ["retreat", ["retreat back"]], ["return", ["return back"]], ["scrutinize", ["closely scrutinize"]], ["software", ["software program"]], ["surrounded", ["surrounded on all sides"]], ["the nation", ["the whole entire nation"]], ["throughout the", ["throughout the entire"]], ["timpani", ["timpani drum"]], ["twins", ["pair of twins"]], ["vacancy", ["unfilled vacancy"]], ["various", ["various different"]], ["veteran", ["former veteran"]], ["visible", ["visible to the eye"]], ["vocation", ["professional vocation"]], ["while", ["while at the same time"]], ] return preferred_forms_check(text, redundancies, err, msg) @memoize def check_nordquist(text): """Suggest the preferred forms. source: Richard Nordquist source_url: http://grammar.about.com/bio/Richard-Nordquist-22176.htm """ err = "redundancy.nordquist" msg = "Redundancy. Use '{}' instead of '{}'." redundancies = [ ["essential", ["absolutely essential"]], ["necessary", ["absolutely necessary"]], ["a.m.", ["a.m. in the morning"]], ["p.m.", ["p.m. at night"]], ] return preferred_forms_check(text, redundancies, err, msg) @memoize def check_atd(text): """Check for redundancies from After the Deadline.""" err = "after_the_deadline.redundancy" msg = "Redundancy. Use '{}' instead of '{}'." redundancies = [ [u"Bō", ["Bo Staff"]], ["Challah", ["Challah bread"]], ["Hallah", ["Hallah bread"]], ["Challah", ["Challah bread"]], ["I", ["I myself", "I personally"]], ["Mount Fuji", ["Mount Fujiyama"]], ["Milky Way", ["Milky Way galaxy"]], ["Rio Grande", ["Rio Grande river"]], ["adage", ["old adage"]], ["add", ["add a further", "add an additional"]], ["advance", ["advance forward"]], ["alternative", ["alternative choice"]], ["amaretto", ["amaretto almond"]], ["annihilate", ["completely annihilate"]], ["anniversary", ["annual anniversary"]], ["anonymous", ["unnamed anonymous"]], ["as", ["equally as"]], ["ascend", ["ascend up"]], ["ask", ["ask the question"]], ["assemble", ["assemble together"]], ["at present the", ["at the present time the"]], ["at this point", ["at this point in time"]], ["attach", ["attach together"]], ["autumn", ["autumn season"]], ["bald", ["bald-headed"]], ["balsa", ["balsa wood"]], ["belongings", ["personal belongings"]], ["benefits", ["desirable benefits"]], ["bento", ["bento box"]], ["best", ["best ever"]], ["bit", ["tiny bit"]], ["blend", ["blend together"]], ["bond", ["common bond"]], ["bonus", ["added bonus", "extra bonus"]], ["bouquet", ["bouquet of flowers"]], ["breakthrough", ["major breakthrough"]], ["bride", ["new bride"]], ["brief", ["brief in duration"]], ["bruin", ["bruin bear"]], ["hot", ["burning hot"]], ["cacophony", ["cacophony of sound"]], ["cameo", ["brief cameo", "cameo appearance"]], ["cancel", ["cancel out"]], ["cash", ["cash money"]], ["chai", ["chai tea"]], ["chance", ["random chance"]], ["charm", ["personal charm"]], ["circle", ["circle around", "round circle"]], ["circulate", ["circulate around"]], ["classify", ["classify into groups"]], ["classmates", ["fellow classmates"]], ["cliche", ["old cliche", "overused cliche"]], ["climb", ["climb up"]], ["clock", ["time clock"]], ["collaborate", ["collaborate together"]], ["collaboration", ["joint collaboration"]], ["colleague", ["fellow colleague"]], ["combine", ["combine together"]], ["commute", ["commute back and forth"]], ["compete", ["compete with each other"]], ["comprise", ["comprise of"]], ["comprises", ["comprises of"]], ["conceived", ["first conceived"]], ["conclusion", ["final conclusion"]], ["confer", ["confer together"]], ["confrontation", ["direct confrontation"]], # ["confused", ["confused state"]], ["connect", ["connect together", "connect up"]], ["consensus", ["consensus of opinion", "general consensus"]], ["consult", ["consult with"]], ["conversation", ["oral conversation"]], ["cool", ["cool down"]], ["cooperate", ["cooperate together"]], ["cooperation", ["mutual cooperation"]], ["copy", ["duplicate copy"]], ["core", ["inner core"]], ["cost", ["cost the sum of"]], ["could", ["could possibly"]], ["coupon", ["money-saving coupon"]], ["created", ["originally created"]], ["crisis", ["crisis situation"]], ["crouch", ["crouch down"]], ["currently", ["now currently"]], ["custom", ["old custom", "usual custom"]], ["danger", ["serious danger"]], ["dates", ["dates back"]], ["decision", ["definite decision"]], ["depreciate", ["depreciate in value"]], ["descend", ["descend down"]], ["destroy", ["totally destroy"]], ["destroyed", ["completely destroyed"]], ["destruction", ["total destruction"]], ["details", ["specific details"]], ["dilemma", ["difficult dilemma"]], ["disappear", ["disappear from sight"]], ["discovered", ["originally discovered"]], ["dive", ["dive down"]], ["done", ["over and done with"]], ["drawing", ["illustrated drawing"]], ["drop", ["drop down"]], ["dune", ["sand dune"]], ["during", ["during the course of"]], ["dwindle", ["dwindle down"]], ["dwindled", ["dwindled down"]], ["every", ["each and every"]], ["earlier", ["earlier in time"]], ["eliminate", ["completely eliminate", "eliminate altogether", "entirely eliminate"]], ["ember", ["glowing ember"]], ["embers", ["burning embers"]], ["emergency", ["emergency situation", "unexpected emergency"]], ["empty", ["empty out"]], ["enclosed", ["enclosed herein"]], ["end", ["final end"]], ["engulfed", ["completely engulfed"]], ["enter", ["enter in", "enter into"]], ["equal", ["equal to one another"]], ["eradicate", ["eradicate completely"]], ["essential", ["absolutely essential"]], ["estimated at", ["estimated at about", "estimated at approximately", "estimated at around"]], ["etc.", ["and etc."]], ["evolve", ["evolve over time"]], ["exaggerate", ["over exaggerate"]], ["exited", ["exited from"]], ["experience", ["actual experience", "past experience"]], ["experts", ["knowledgeable experts"]], ["extradite", ["extradite back"]], ["face the consequences", ["face up to the consequences"]], ["face the fact", ["face up to the fact"]], ["face the challenge", ["face up to the challenge"]], ["face the problem", ["face up to the problem"]], ["facilitate", ["facilitate easier"]], ["fact", ["established fact"]], ["facts", ["actual facts", "hard facts", "true facts"]], ["fad", ["passing fad"]], ["fall", ["fall down"]], ["fall", ["fall season"]], ["feat", ["major feat"]], ["feel", ["feel inside"]], ["feelings", ["inner feelings"]], ["few", ["few in number"]], ["filled", ["completely filled", "filled to capacity"]], ["first", ["first of all"]], ["first time", ["first time ever"]], ["fist", ["closed fist"]], ["fly", ["fly through the air"]], ["focus", ["focus in", "main focus"]], ["follow", ["follow after"]], ["for example", ["as for example"]], # ["foremost", ["first and foremost"]], ["forever", ["forever and ever"]], ["free", ["for free"]], ["friend", ["personal friend"]], ["friendship", ["personal friendship"]], ["full", ["full to capacity"]], ["fundamentals", ["basic fundamentals"]], ["fuse", ["fuse together"]], ["gather", ["gather together", "gather up"]], ["get up", ["get up on his feet", "get up on your feet"]], ["gift", ["free gift"]], ["gifts", ["free gifts"]], ["goal", ["ultimate goal"]], # ["graduate", ["former graduate"]], ["grow", ["grow in size"]], ["guarantee", ["absolute guarantee"]], ["gunman", ["armed gunman"]], ["gunmen", ["armed gunmen"]], ["habitat", ["native habitat"]], ["had done", ["had done previously"]], ["halves", ["two equal halves"]], # ["has", ["has got"]], # ["have", ["have got"]], ["haven", ["safe haven"]], # ["he", ["he himself"]], ["heat", ["heat up"]], ["history", ["past history"]], ["hoist", ["hoist up"]], ["hole", ["empty hole"]], ["honcho", ["head honcho"]], ["ice", ["frozen ice"]], ["ideal", ["perfect ideal"]], ["identical", ["same identical"]], ["identification", ["positive identification"]], ["imports", ["foreign imports"]], ["impulse", ["sudden impulse"]], ["in fact", ["in actual fact"]], ["in the yard", ["outside in the yard"]], ["inclusive", ["all inclusive"]], ["incredible", ["incredible to believe"]], ["incumbent", ["present incumbent"]], # ["indicted", ["indicted on a charge"]], ["industry", ["private industry"]], ["injuries", ["harmful injuries"]], ["innovation", ["new innovation"]], ["innovative", ["innovative new", "new innovative"]], # ["input", ["input into"]], ["instinct", ["natural instinct", "naturally instinct"]], ["integrate", ["integrate together", "integrate with each other"]], ["interdependent", ["interdependent on each other", "mutually interdependent"]], ["introduced", ["introduced for the first time"]], ["invention", ["new invention"]], ["kneel", ["kneel down"]], ["knots", ["knots per hour"]], # ["last", ["last of all"]], # ["later", ["later time"]], ["lift", ["lift up"]], ["lingers", ["still lingers"]], ["look to the future", ["look ahead to the future"]], ["love triangle", ["three-way love triangle"]], ["maintained", ["constantly maintained"]], ["manually", ["manually by hand"]], ["marina", ["boat marina"]], ["may", ["may possibly"]], ["meet", ["meet together", "meet with each other"]], ["memories", ["past memories"]], ["merge", ["merge together"]], ["merged", ["merged together"]], ["meshed", ["meshed together"]], ["midnight", ["twelve midnight"]], ["migraine", ["migraine headache"]], ["minestrone", ["minestrone soup"]], ["mix", ["mix together"]], ["moment", ["brief moment", "moment in time"]], ["monopoly", ["complete monopoly"]], ["mural", ["wall mural"]], ["mutual respect", ["mutual respect for each other"]], ["mutually dependent", ["mutually dependent on each other"]], ["mystery", ["unsolved mystery"]], # ["naked", ["bare naked"]], ["nape", ["nape of her neck"]], ["necessary", ["absolutely necessary"]], ["never", ["never at any time"]], ["noon", ["12 noon", "12 o'clock noon", "high noon", "twelve noon"]], ["nostalgia", ["nostalgia for the past"]], ["number of", ["number of different"]], ["opening", ["exposed opening"]], ["my opinion", ["my personal opinion"]], ["opposites", ["exact opposites", "polar opposites"]], ["opposite", ["exact opposite", "polar opposite"]], ["orbits", ["orbits around"]], ["outcome", ["final outcome"]], ["panacea", ["universal panacea"]], ["pending", ["now pending"]], ["penetrate", ["penetrate through"]], ["persists", ["still persists"]], ["pioneer", ["old pioneer"]], ["plan", ["plan ahead", "plan in advance", "proposed plan"]], ["planning", ["advance planning", "forward planning"]], ["plans", ["future plans"]], ["plan", ["future plan"]], ["point", ["point in time"]], ["point", ["sharp point"]], ["postpone", ["postpone until later"]], ["pouring rain", ["pouring down rain"]], ["preview", ["advance preview"]], ["previously listed", ["previously listed above"]], ["probed", ["probed into"]], ["proceed", ["proceed ahead"]], ["prosthesis", ["artificial prosthesis"]], # ["protrude", ["protrude out"]], ["proverb", ["old proverb"]], # ["proximity", ["close proximity"]], ["put off", ["put off until later"]], # ["raise", ["raise up"]], ["re-elect", ["re-elect for another term"]], ["reason is", ["reason is because"]], ["recur", ["recur again"]], ["recurrence", ["future recurrence"]], ["refer", ["refer back"]], ["reflect", ["reflect back"]], # ["relevant", ["highly relevant"]], ["remain", ["continue to remain"]], ["remains", ["still remains"]], ["replica", ["exact replica"]], ["reply", ["reply back"]], # ["requirements", ["necessary requirements"]], ["reservations", ["advance reservations"]], ["retreat", ["retreat back"]], ["revert", ["revert back"]], ["round", ["round in shape"]], ["rule of thumb", ["rough rule of thumb"]], ["rumor", ["unconfirmed rumor"]], ["rustic", ["rustic country"]], ["same", ["exact same", "precise same", "same exact"]], ["sanctuary", ["safe sanctuary"]], ["satisfaction", ["full satisfaction"]], ["scrutinize", ["scrutinize in detail"]], ["scrutiny", ["careful scrutiny", "close scrutiny"]], ["secret", ["secret that cannot be told"]], ["seek", ["seek to find"]], ["separated", ["separated apart from each other"]], ["share", ["share together"]], ["shiny", ["shiny in appearance"]], ["sincere", ["truly sincere"]], ["sink", ["sink down"]], ["skipped", ["skipped over"]], # ["slow", ["slow speed"]], # ["small", ["small size"]], ["soft", ["soft in texture", "soft to the touch"]], ["sole", ["sole of the foot"]], ["some time", ["some time to come"]], ["speck", ["small speck"]], ["speed", ["rate of speed"]], ["spell out", ["spell out in detail"]], ["spiked", ["spiked upward", "spiked upwards"]], ["spring", ["spring season"]], ["stranger", ["anonymous stranger"]], ["studio audience", ["live studio audience"]], ["subway", ["underground subway"]], ["sufficient", ["sufficient enough"]], ["summer", ["summer season"]], ["sure", ["absolutely sure"]], ["surprise", ["unexpected surprise"]], ["surround", ["completely surround"]], ["surrounded", ["surrounded on all sides"]], ["tall", ["tall in height", "tall in stature"]], ["telepathy", ["mental telepathy"]], ["ten", ["ten in number"]], ["these", ["these ones"]], # ["they", ["they themselves"]], ["those", ["those ones"]], ["trench", ["open trench"]], ["truth", ["honest truth"]], ["tundra", ["frozen tundra"]], ["ultimatum", ["final ultimatum"]], # ["undeniable", ["undeniable truth"]], ["undergraduate", ["undergraduate student"]], # ["unintentional", ["unintentional mistake"]], ["vacillate", ["vacillate back and forth"]], ["veteran", ["former veteran"]], ["visible", ["visible to the eye"]], ["warn", ["warn in advance"]], ["warning", ["advance warning"]], ["water heater", ["hot water heater"]], ["in which we live", ["in which we live in"]], ["winter", ["winter season"]], ["witness", ["live witness"]], ["yakitori", ["yakitori chicken"]], ["yerba mate", ["yerba mate tea"]], ["yes", ["affirmative yes"]], ] return preferred_forms_check(text, redundancies, err, msg) proselint-0.10.2/proselint/checks/redundancy/ras_syndrome.py0000664000372000037200000000246313331225053025147 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Redundant Acronym Syndrome (RAS) syndrome.""" from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "garner.redundancy.ras" msg = "RAS syndrome. Use '{}' instead of '{}'." redundancies = [ ["ABM", ["ABM missile"]], ["ACT", ["ACT test"]], ["ABMs", ["ABM missiles"]], ["ABS", ["ABS braking system"]], ["ATM", ["ATM machine"]], ["CD", ["CD disc"]], ["CPI", ["CPI Index"]], ["GPS", ["GPS system"]], ["GUI", ["GUI interface"]], ["HIV", ["HIV virus"]], ["ISBN", ["ISBN number"]], ["LCD", ["LCD display"]], ["PDF", ["PDF format"]], ["PIN", ["PIN number"]], ["RAS", ["RAS syndrome"]], ["RIP", ["RIP in peace"]], ["RSVP", ["please RSVP"]], ["SALT", ["SALT talks"]], ["SAT", ["SAT test"]], ["UPC", ["UPC codes"]], ] return preferred_forms_check(text, redundancies, err, msg) proselint-0.10.2/proselint/checks/skunked_terms/0000775000372000037200000000000013331225202022601 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/skunked_terms/__init__.py0000664000372000037200000000003313331225053024712 0ustar travistravis00000000000000"""Avoid skunked terms.""" proselint-0.10.2/proselint/checks/skunked_terms/misc.py0000664000372000037200000000137613331225053024121 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Skunked terms. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: Skunked terms. date: 2014-06-10 12:31:19 categories: writing --- Archaism. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "skunked_terms.misc" msg = u"""'{}' is a bit of a skunked term — impossible to use without issue. Find some other way to say it.""" skunked_terms = [ "bona fides", "deceptively", "decimate", "effete", "fulsome", "hopefully", "impassionate", "Thankfully,", ] return existence_check(text, skunked_terms, err, msg) proselint-0.10.2/proselint/checks/nonwords/0000775000372000037200000000000013331225202021574 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/nonwords/__init__.py0000664000372000037200000000002013331225053023701 0ustar travistravis00000000000000"""Nonwords.""" proselint-0.10.2/proselint/checks/nonwords/misc.py0000664000372000037200000000461013331225053023106 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Nonwords. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: nonwords date: 2014-06-10 12:31:19 categories: writing --- Nonwords. """ from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "nonwords.misc" msg = "Nonword, try '{}'." preferences = [ ["doubtless' or 'undoubtedly", ["doubtlessly"]], ["analysis", ["analyzation"]], ["annoyance", ["annoyment"]], ["confirmand", ["confirmant"]], ["confirmands", ["confirmants"]], ["converse", ["conversate"]], ["cranded", ["crained"]], ["disbursement' or 'dispersal", ["dispersement"]], ["discomfort' or 'discomfiture", ["discomforture"]], ["effrontery", ["affrontery"]], ["forbearance", ["forebearance"]], ["improper", ["improprietous"]], ["inclement", ["inclimate"]], ["relatively low price' or 'affordability", ["relative inexpense"]], ["inimical", ["inimicable"]], ["regardless", ["irregardless"]], ["minimize", ["minimalize"]], ["minimized", ["minimalized"]], ["minimizes", ["minimalizes"]], ["minimizing", ["minimalizing"]], # muchly ["optimize", ["optimalize"]], ["paralysis", ["paralyzation"]], ["pettifog", ["pettifogger"]], ["proper", ["proprietous"]], ["quell' or 'quash", ["squelch"]], ["seldom", ["seldomly"]], # slinged ["thus", ["thusly"]], ["categorically", ["uncategorically"]], ["undoubtedly' or 'indubitably", ["undoubtably"]], ["unequivocal", ["unequivocable"]], ["mercilessly", ["unmercilessly"]], ["unrelentingly' or relentlessly", ["unrelentlessly"]], ] return preferred_forms_check(text, preferences, err, msg) proselint-0.10.2/proselint/checks/security/0000775000372000037200000000000013331225202021572 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/security/credit_card.py0000664000372000037200000000121313331225053024410 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Credit card number printed. --- layout: post source: ??? source_url: ??? title: credit card number printed date: 2014-06-10 12:31:19 categories: writing --- Credit card number printed. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "security.credit_card" msg = u"Don't put credit card numbers in plain text." credit_card_numbers = [ "4\d{15}", "5[1-5]\d{14}", "3[4,7]\d{13}", "3[0,6,8]\d{12}", "6011\d{12}", ] return existence_check(text, credit_card_numbers, err, msg) proselint-0.10.2/proselint/checks/security/__init__.py0000664000372000037200000000002013331225053023677 0ustar travistravis00000000000000"""Security.""" proselint-0.10.2/proselint/checks/security/password.py0000664000372000037200000000134613331225053024016 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Password in plain text. --- layout: post source: ??? source_url: ??? title: password in plain text date: 2014-06-10 12:31:19 categories: writing --- Don't put pass """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "security.password" msg = u"Don't put passwords in plain text." pwd_regex = "[:]? [\S]{6,30}" password = [ "the password is{}".format(pwd_regex), "my password is{}".format(pwd_regex), "the password's{}".format(pwd_regex), "my password's{}".format(pwd_regex), "^[pP]assword{}".format(pwd_regex), ] return existence_check(text, password, err, msg) proselint-0.10.2/proselint/checks/consistency/0000775000372000037200000000000013331225202022264 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/consistency/spacing.py0000664000372000037200000000123013331225053024262 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Mixed one vs. two spaces after a period. --- layout: post source: Consistency. source_url: ??? title: Mixed use of 1 vs. 2 spaces after a period. date: 2014-06-10 12:31:19 categories: writing --- Points out instances where there are two conventions, 1 vs. 2 spaces after a period, in the same document. """ from proselint.tools import consistency_check, memoize @memoize def check(text): """Check the text.""" err = "consistency.spacing" msg = "Inconsistent spacing after period (1 vs. 2 spaces)." regex = ["[\.\?!] [A-Z]", "[\.\?!] [A-Z]"] return consistency_check(text, [regex], err, msg) proselint-0.10.2/proselint/checks/consistency/__init__.py0000664000372000037200000000004213331225053024375 0ustar travistravis00000000000000"""Various consistency checks.""" proselint-0.10.2/proselint/checks/consistency/spelling.py0000664000372000037200000000270213331225053024460 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Inconsistent spelling. --- layout: post source: Intelligent Editing Ltd. source_url: http://bit.ly/1x3hYj7 title: Inconsistent spelling date: 2014-06-10 12:31:19 categories: writing --- Intelligent Editing Ltd. says: > Some words have more than one correct spelling. American, British, Australian and Canadian English all have their own preferences. Even within those, there can be multiple spellings. For example, in the UK 'realise' is often preferred. However, 'realize' has been used in British-English for centuries and is preferred in the Oxford English Dictionary. However, no matter which spelling is preferred, one thing is always wrong: you mustn't use two different spellings in the same document. """ from proselint.tools import consistency_check, memoize @memoize def check(text): """Check the text.""" err = "consistency.spelling" msg = "Inconsistent spelling of '{}' (vs. '{}')." word_pairs = [ ["advisor", "adviser"], # ["analyse", "analyze"], ["centre", "center"], ["colour", "color"], ["emphasise", "emphasize"], ["finalise", "finalize"], ["focussed", "focused"], ["labour", "labor"], ["learnt", "learned"], ["organise", "organize"], ["organised", "organized"], ["organising", "organizing"], ["recognise", "recognize"], ] return consistency_check(text, word_pairs, err, msg) proselint-0.10.2/proselint/checks/cursing/0000775000372000037200000000000013331225202021375 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/cursing/nfl.py0000664000372000037200000005722613331225053022546 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Words the NFL won't print on a jersey. --- layout: post source: The National Football League source_url: http://bit.ly/1ISK0rb title: words the NFL won't print on a jersey date: 2014-06-10 12:31:19 categories: writing --- Words the NFL won't print on a jersey. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "cursing.nfl" msg = u"The NFL won't print this word on a jersey." list = [ "420", "666", "2 on 1", "3rd eye", "3rd leg", "3rdeye", "3rdleg", "3some", "4 twenty", "4twenty", "60 nine", "60nine", "a.s.s.", "anal", "anal annie", "anal sex", "analannie", "analsex", "anus", "arse", "ass", "ass bagger", "ass blaster", "ass clown", "ass cowboy", "ass fuck", "ass fucker", "ass hole", "ass holes", "ass hore", "ass jockey", "ass kiss", "ass kisser", "ass klown", "ass lick", "ass licker", "ass lover", "ass man", "ass monkey", "ass munch", "ass muncher", "ass packer", "ass pirate", "ass puppies", "ass ranger", "ass whore", "ass wipe", "assbagger", "assblaster", "assclown", "asscowboy", "assfuck", "assfucker", "asshole", "assholes", "asshore", "assjockey", "asskiss", "asskisser", "assklown", "asslick", "asslicker", "asslover", "assman", "assmonkey", "assmunch", "assmuncher", "asspacker", "asspirate", "asspuppies", "assranger", "asswhore", "asswipe", "athletes foot", "athletesfoot", "axing the weasel", "b hard", "back door", "back door man", "backdoor", "backdoorman", "backseat", "bad ass", "bad fuck", "badfuck", "ball licker", "ball sack", "balllicker", "balls", "ballsack", "banging", "barely legal", "barelylegal", "barf", "barf face", "barface", "barfface", "bastard", "bazongas", "bazooms", "beastality", "beastiality", "beat off", "beat your meat", "beatoff", "beat-off", "beatyourmeat", "bi", "bi sexual", "biatch", "big ass", "big bitch", "big bitch", "big butt", "bigass", "bigbastard", "bigbutt", "bisexual", "bi-sexual", "bitch", "bitches", "bitchin", "bitchy", "bite me", "biteme", "black out", "blackout", "blow job", "blowjob", "bm", "boner", "bong", "boobies", "boobs", "boody", "breast", "breast job", "breast lover", "breast man", "breastjob", "breastlover", "breastman", "budweiser", "bull crap", "bull dike", "bull dyke", "bull shit", "bullcrap", "bulldike", "bulldyke", "bullshit", "bumble fuck", "bumblefuck", "bumfuck", "bunghole", "butch babes", "butch dike", "butch dyke", "butchbabes", "butchdike", "butchdyke", "butt bang", "butt fuck", "butt fucker", "butt fuckers", "butt head", "butt man", "butt plug", "butt stain", "buttbang", "butt-bang", "buttface", "buttfuck", "butt-fuck", "buttfucker", "butt-fucker", "buttfuckers", "butt-fuckers", "butthead", "buttman", "buttpirate", "buttplug", "buttstain", "camel toe", "cameltoe", "carpet muncher", "carpetmuncher", "carruth", "cherry popper", "cherrypopper", "chick slick", "chickslick", "clam digger", "clam diver", "clamdigger", "clamdiver", "clit", "clitoris", "cock", "cock block", "cock blocker", "cock cowboy", "cock fight", "cock knob", "cock licker", "cock lover", "cock nob", "cock queen", "cock rider", "cock smith", "cock sucker", "cock tail", "cock tease", "cockblock", "cockblocker", "cockcowboy", "cockfight", "cockhead", "cockknob", "cocklicker", "cocklover", "cocknob", "cockqueen", "cockrider", "cocks man", "cocksman", "cocksmith", "cocksucer", "cocksucker", "cocktail", "cocktease", "cocky", "condom", "copulate", "corn hole", "cornhole", "crabs", "crack", "crack pipe", "crack whore", "crackpipe", "crackwhore", "crack-whore", "crap", "crappy", "creamy", "crotch", "crotch jockey", "crotch monkey", "crotch rot", "crotchjockey", "crotchmonkey", "crotchrot", "cum", "cum bubble", "cum fest", "cum jockey", "cum quat", "cum queen", "cum shot", "cumbubble", "cumfest", "cumjockey", "cumm", "cumming", "cumquat", "cumqueen", "cumshot", "cunnilingus", "cunt", "cunt fuck", "cunt fucker", "cunt licker", "cuntfuck", "cuntfucker", "cuntlicker", "cyber sex", "cyber slimer", "cybersex", "cyberslimer", "dahmer", "damn", "damn it", "damnit", "datnigga", "dd", "deap throat", "deaper", "deapthroat", "deep throat", "deeper", "deepthroat", "defecate", "deposit", "devil", "dick brain", "dick fart", "dick for brains", "dick head", "dick lick", "dick licker", "dick likcer", "dick wad", "dick weed", "dickbrain", "dickforbrains", "dickhead", "dickless", "dicklick", "dicklicker", "dickman", "dickwad", "dickweed", "dike", "dildo", "dip stick", "dipstick", "dirty ho", "dix", "dixie dike", "dixie dyke", "dixiedike", "dixiedyke", "do me", "doggie style", "doggiestyle", "doggy stlye", "doggystyle", "dome", "dong", "dope", "double d", "doubled", "drag queen", "dragqueen", "dragqween", "dre", "drip dick", "dripdick", "drunk", "drunken", "dumb ass", "dumb bitch", "dumb fuck", "dumbass", "dumbbitch", "dumbfuck", "easy slut", "easyslut", "eat me", "eat pussy", "eatballs", "eatme", "eatpussy", "ejaculate", "erection", "evl", "excrement", "f toyota", "f.i.n.e.", "f.u.c.k.", "face fucker", "facefucker", "faggot", "fagot", "fairy", "fanny fucker", "fannyfucker", "fart", "fast fuck", "fastfuck", "fat ass", "fat fuck", "fat fucker", "fatass", "fatfuck", "fatfucker", "fatso", "fellatio", "femme", "finger food", "finger fuck", "finger fucker", "fingerfood", "fingerfuck", "fingerfucker", "fist fuck", "fist fucker", "fistfuck", "fistfucker", "fisting", "flasher", "flatulence", "floggin the dolphin", "fondle", "foot fuck", "foot fucker", "foot licker", "footaction", "footfuck", "footfucker", "footlicker", "footstar", "fore skin", "foreskin", "fornicate", "four 20", "four twenty", "four20", "fourtwenty", "freak fuck", "freakfuck", "freaky fucker", "freakyfucker", "free 4 all", "free for all", "free fuck", "free4all", "freeforall", "freefuck", "fuck", "fuck bag", "fuck buddy", "fuck face", "fuck fest", "fuck freak", "fuck friend", "fuck head", "fuck her", "fuck it", "fuck knob", "fuck me", "fuck me hard", "fuck monkey", "fuck off", "fuck pig", "fuck them", "fuck whore", "fuck you", "fucka", "fuckable", "fuckbag", "fuckbuddy", "fucked", "fucked up", "fuckedup", "fucker", "fuckers", "fuckface", "fuckfest", "fuckfreak", "fuckfriend", "fuckhead", "fuckher", "fuckin", "fuckin a", "fuckin nuts", "fuckin right", "fuckina", "fucking", "fucking a", "fucking bitch", "fucking nuts", "fuckingbitch", "fuckinnuts", "fuckinright", "fuckit", "fuckknob", "fuckme", "fuckmehard", "fuckmonkey", "fuckoff", "fuckpig", "fuckwhore", "fuckyou", "fudge pakcers", "fun fuck", "funfuck", "fuuck", "g unit", "gang bang", "gang banger", "gangbang", "gangbanger", "gay", "gay ass", "gay mutha fuckin queer", "gay pride", "gaymuthafuckinwhore", "genital", "get it on", "getiton", "giehn", "give head", "givehead", "glazed donut", "glazeddonut", "go me", "go to hell", "god", "god damed mutha fucka", "god damit", "god damn", "god damned", "god manit", "goddamit", "goddamn", "goddamned", "goddamnes", "goddamnit", "goddamnmuthafucker", "gonorrehea", "gonzagas", "gook", "got jesus", "got2haveit", "gotohell", "g-unit", "hand job", "handjob", "hard on", "harder", "hardon", "harem", "he hate me", "head fuck", "head lights", "headfuck", "headlights", "hehateme", "hell", "hell no", "hell yes", "hellno", "hellyes", "hen house", "henhouse", "herpes", "hershey hi way", "hersheyhighway", "hersheyhiway", "hershy high way", "ho", "ho mo", "hobo", "hole", "hole stuffer", "holestuffer", "homo", "homo bangers", "homo sexual", "homobangers", "homosexual", "honkers", "honkey", "hooker", "hookers", "hooters", "hore", "horney", "horny", "horseshit", "hose job", "hosejob", "hoser", "hostage", "hot damn", "hot pussy", "hot to trot", "hot2trot", "hotdamn", "hotpussy", "hottotrot", "hussy", "hustler", "i love beer", "i luv beer", "id ten t", "id10t", "idiot", "idoit", "in the ass", "in the buff", "ingin", "insest", "inter course", "inter racial", "intercourse", "interracial", "intheass", "inthebuff", "jack the ripper", "jackass", "jackoff", "jacktheripper", "jap", "jap crap", "japcrap", "jerk off", "jerkoff", "jesus chirst", "jesuschrist", "jism", "jiz", "jiz juice", "jizim", "jizjuice", "jizz", "jizzim", "joint", "juggalo", "jugs", "k mart", "kill", "killer", "killing", "kiss ass", "kissass", "kkk", "kmart", "knockers", "koon", "kotex", "krap", "krappy", "kum", "kum bubble", "kum quat", "kumbubble", "kumbullbe", "kumquat", "kunt", "ky", "ky jelly", "lactate", "lady boog", "laid", "lap dance", "lapdance", "lesbain", "lesbayn", "lesbian", "lesbin", "lesbo", "lez", "lez be", "lez be friends", "lezbe", "lezbefriends", "lezbo", "lezz", "lezzo", "lick me", "licker", "lickme", "limp dick", "limpdick", "limy", "live sex", "livesex", "loaded gun", "loadedgun", "lolita", "looser", "lotion", "love bone", "love goo", "love gun", "love juice", "love muscle", "love pistol", "love rocket", "lovebone", "lovegoo", "lovegun", "lovejuice", "lovemuscle", "lovepistol", "loverocket", "low life", "lowlife", "lube job", "lubejob", "lucky camel toe", "luckycammeltoe", "magic wand", "magicwand", "mams", "man hater", "man paste", "manhater", "manpaste", "mary jane", "maryjane", "mastabate", "mastabater", "master blaster", "masterbate", "masterblaster", "mastrabator", "mattress princess", "mattressprincess", "meat beatter", "meatbeatter", "molest", "molester", "molestor", "money shot", "moneyshot", "mother fucker", "mother love bone", "motherfuck", "motherfucker", "motherlovebone", "muff", "muff dive", "muff diver", "muff licker", "muffdive", "muffdiver", "muffin diver", "muffindiver", "mufflikcer", "murder", "mutha fucker", "naked", "nasty bitch", "nasty ho", "nasty slut", "nasty whore", "nastybitch", "nastyho", "nastyslut", "nastywhore", "neon deon", "nig", "niger", "nigga", "nigger", "nipple", "nipple ring", "nipplering", "nit tit", "nittit", "no fucking way", "no sex", "nofuckingway", "nookie", "nooner", "nude", "nut fucker", "nutfucker", "oicu812", "on the rag", "ontherag", "orgasm", "orgy", "ou812", "oui", "p i m p", "pearl necklace", "pearlnecklace", "pecker", "pee", "peep show", "peepshow", "peepshpw", "penetration", "penis", "penthouse", "period", "phque", "pimp", "pimp simp", "pimped", "pimper", "pimpjuic", "pimpjuice", "pimpsimp", "piss", "piss head", "pissed", "pisser", "pisshead", "play boy", "play girl", "playboy", "playgirl", "pocket pool", "pocketpool", "polack", "poon tang", "poontang", "poop", "pooper", "poor white trash", "poorwhitetrash", "popimp", "porch monkey", "porchmonkey", "porn", "porn flick", "porn king", "porn princess", "pornflick", "pornking", "porno", "pornprincess", "pot", "premature", "prick", "prick head", "prickhead", "primetime", "prostitute", "pubic", "pubic lice", "pubiclice", "pud", "pud boy", "pudboy", "pudd", "pudd boy", "puddboy", "pun tang", "puntang", "purina princess", "purinapricness", "pussy", "pussy cat", "pussy eater", "pussy fucker", "pussy licker", "pussy lips", "pussy lover", "pussy pounder", "pussycat", "pussyeater", "pussyfucker", "pussylicker", "pussylips", "pussylover", "pussypounder", "putt pirate", "pwt", "queef", "queer", "quickie", "rae carruth", "rape", "rapist", "rear end", "rear entry", "rearend", "rearentry", "rectum", "red light", "redlight", "reefer", "rent a fuck", "rentafuck", "retard", "retarded", "ribbed", "rim job", "rimjob", "roach", "robber", "s and m", "s&m", "samckdaddy", "sandm", "satan", "schlong", "screw", "screw you", "screwyou", "scrotum", "semen", "sex", "sex farm", "sex hound", "sex house", "sex kitten", "sex pot", "sex slave", "sex to go", "sex toy", "sex toys", "sex whore", "sexfarm", "sexhound", "sexhouse", "sexkitten", "sexpot", "sexslave", "sextogo", "sextoy", "sextoys", "sexual", "sexwhore", "sexy", "sexy biatch", "sexy bitch", "sexy moma", "sexy slim", "sexymoma", "sexy-slim", "shag", "shaggin", "shagging", "shawtypimp", "shit", "shit dick", "shit eater", "shit face", "shit for brains", "shit fuck", "shit fucker", "shit happens", "shit head", "shit out of luck", "shit stain", "shit4brains", "shitdick", "shiteater", "shitface", "shitforbrains", "shitfuck", "shitfucker", "shithapens", "shithappens", "shithead", "shitoutofluck", "shits", "shitstain", "shitter", "shitting", "shitty", "short fuck", "shortfuck", "showtime", "six six six", "sixsixsix", "sixty 9", "sixty nine", "sixty9", "sixtynine", "skank", "skank bitch", "skank fuck", "skank whore", "skankbitch", "skankfuck", "skankwhore", "skanky bitch", "skanky whore", "skankybitch", "skankywhore", "skin flute", "skinflute", "skum", "skum bag", "skumbag", "slant", "slant eye", "slanteye", "slave", "slave driver", "slavedriver", "sleeze bag", "sleeze ball", "sleezebag", "sleezeball", "slide it in", "slideitin", "slime", "slime ball", "slime bucket", "slimeball", "slimebucket", "slut", "slut wear", "slut whore", "sluts", "slutt", "slutting", "slutty", "slutwear", "slutwhore", "smack daddy", "smack the monkey", "smackthemonkey", "smagma", "smart ass", "snatch", "snatch patch", "snatchpatch", "sniper", "snot", "sob", "sodomite", "sodomy", "son of a bitch", "sonofabitch", "sonofbitch", "spank the monkey", "spankthemonkey", "sperm", "sperm bag", "sperm hearder", "sperm herder", "spermacide", "spermbag", "spermhearder", "spermherder", "spic", "spick", "spit", "spitter", "split tail", "split tial", "splittail", "stagg", "strap on", "strapon", "stringer", "strip club", "stripclub", "stroke", "stroking", "stupid", "stupid fuck", "stupid fucker", "stupidfuck", "stupidfucker", "suck", "suck dick", "suck me", "suck my ass", "suck my dick", "suck my tit", "suck off", "suckdick", "sucker", "suckme", "suckmyass", "suckmydick", "suckmytit", "suckoff", "suicide", "swallow", "swallower", "swalow", "sweetness", "swign dixx", "swing dixx", "swingin dixx", "swinging dicks", "syphilis", "tampon", "tang", "testicle", "testicles", "third eye", "third leg", "thirdeye", "thirdleg", "three some", "threesome", "tit", "tit bit nipply", "tit fuck", "tit fucker", "tit fuckin", "tit job", "tit licker", "tit lover", "titbitnipply", "titfuck", "titfucker", "titfuckin", "titjob", "titlicker", "titlover", "tits", "titties", "titty", "toilet", "toilet bowl", "tongethruster", "tongue", "tongue thruster", "tongue tramp", "tonguethrust", "tonguetramp", "toung thruster", "tounge baller", "tounge thrust", "trailer trash", "trailertrash", "tramp", "tri sexual", "triple x", "triplex", "trisexual", "trojan", "trots", "tunnel of love", "tunneloflove", "turd", "two bit whore", "two on one", "twobitwhore", "unfuckable", "up the ass", "up the butt", "upskirt", "uptheass", "upthebutt", "urinate", "urine", "uterus", "vagina", "vaginal", "vd", "vibrater", "vibrator", "virgin", "virgin breaker", "virginbreaker", "vulva", "waysted", "weenie", "wet spot", "wetspot", "whacker", "whiskey dick", "whiskeydick", "whisky dick", "whiskydick", "white trash", "whitetrash", "whore", "whore fucker", "whore house", "whorefucker", "whorehouse", "wigger", "willie wanker", "williewanker", "wuutang", "xxx", "yellow man", "yellowman" ] return existence_check(text, list, err, msg) proselint-0.10.2/proselint/checks/cursing/filth.py0000664000372000037200000000130613331225053023061 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Filthy words. --- layout: post source: George Carlin source_url: https://youtu.be/kyBH5oNQOS0 title: filthy words date: 2014-06-10 12:31:19 categories: writing --- Filthy words. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "cursing.filth" msg = u"""Nobody ever tells you this as a kid, but you're supposed to avoid this word.""" list = [ "shit", "piss", "fuck", "cunt", "cocksucker", "motherfucker", "tits", "fart", "turd", "twat", ] return existence_check(text, list, err, msg) proselint-0.10.2/proselint/checks/cursing/__init__.py0000664000372000037200000000001713331225053023510 0ustar travistravis00000000000000"""Cursing.""" proselint-0.10.2/proselint/checks/cursing/nword.py0000664000372000037200000000107613331225053023110 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """On 'the N word'. --- layout: post source: Louis CK source_url: https://youtu.be/dF1NUposXVQ?t=30s title: the 'n-word' date: 2014-06-10 12:31:19 categories: writing --- Take responsibility with the shitty words you wanna say. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "cursing.nword" msg = u"Take responsibility for the shitty words you want to say." list = [ "the n-word", ] return existence_check(text, list, err, msg) proselint-0.10.2/proselint/checks/lgbtq/0000775000372000037200000000000013331225202021034 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/lgbtq/__init__.py0000664000372000037200000000001513331225053023145 0ustar travistravis00000000000000"""GLAAD.""" proselint-0.10.2/proselint/checks/lgbtq/offensive_terms.py0000664000372000037200000000212313331225053024606 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """GLAAD. --- layout: post source: GLAAD Media Reference Guide - 9th Edition source_url: http://www.glaad.org/reference title: GLAAD Guidelines date: 2016-07-06 categories: writing --- This check looks for offensive terms related to LGBTQ issues and raises an error marking them as offensive. The New York Times and Associated Press have also adopted this style guide. """ from proselint.tools import memoize, existence_check @memoize def check(text): """Flag offensive words based on the GLAAD reference guide.""" err = "glaad.offensive_terms" msg = "Offensive term. Remove it or consider the context." list = [ "fag", "faggot", "dyke", "sodomite", "homosexual agenda", "gay agenda", "transvestite", "homosexual lifestyle", "gay lifestyle" # homo - may create false positives without additional context # FIXME use topic detetor to decide whether "homo" is offensive ] return existence_check(text, list, err, msg, join=True, ignore_case=False) proselint-0.10.2/proselint/checks/lgbtq/terms.py0000664000372000037200000000237513331225053022553 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """GLAAD. --- layout: post source: GLAAD Media Reference Guide - 9th Edition source_url: http://www.glaad.org/reference title: GLAAD Guidelines date: 2016-07-06 categories: writing --- This check looks for possibly offensive terms related to LGBTQ issues and makes more acceptable recommendations. TheNew York Times and Associated Press have also adopted this style guide. """ from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest preferred forms given the reference document.""" err = "glaad.terms" msg = "Possibly offensive term. Consider using '{}' instead of '{}'." list = [ ["gay man", ["homosexual man"]], ["gay men", ["homosexual men"]], ["lesbian", ["homosexual woman"]], ["lesbians", ["homosexual women"]], ["gay people", ["homosexual people"]], ["gay couple", ["homosexual couple"]], ["sexual orientation", ["sexual preference"]], ["openly gay", ["admitted homosexual", "avowed homosexual"]], ["equal rights", ["special rights"]] ] return preferred_forms_check(text, list, err, msg, ignore_case=False) proselint-0.10.2/proselint/checks/archaism/0000775000372000037200000000000013331225202021512 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/archaism/__init__.py0000664000372000037200000000002013331225053023617 0ustar travistravis00000000000000"""Archaism.""" proselint-0.10.2/proselint/checks/archaism/misc.py0000664000372000037200000000346713331225053023035 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Archaism. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: archaism date: 2014-06-10 12:31:19 categories: writing --- Archaism. """ from proselint.tools import existence_check, memoize @memoize def check(text): """Check the text.""" err = "archaism.misc" msg = u"'{}' is archaic." archaisms = [ "alack", "anent", # "anon", "begat", "belike", "betimes", "boughten", "brocage", "brokage", "camarade", "chiefer", "chiefest", "Christiana", "completely obsolescent", "cozen", "divers", "deflexion", "durst", "fain", "forsooth", "foreclose from", "haply", "howbeit", "illumine", "in sooth", "maugre", "meseems", "methinks", "nigh", "peradventure", "perchance", "saith", "shew", "sistren", "spake", "to wit", "verily", "whilom", "withal", "wot", "enclosed please find", "please find enclosed", "enclosed herewith", "enclosed herein", "inforce", "ex postfacto", "foreclose from", "forewent", "for ever", # "designer", when used to mean a plotter against Christ # "demean", when used to mean "to behave" in legal contexts # "by the bye", # variant, modern is "by the by" # "comptroller" # in British English # "abortive" Abortive is archaic in reference to abortions of fetuses, # except in the sense “causing an abortion.” ] return existence_check(text, archaisms, err, msg, join=True) proselint-0.10.2/proselint/checks/cliches/0000775000372000037200000000000013331225202021335 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/cliches/__init__.py0000664000372000037200000000002513331225053023447 0ustar travistravis00000000000000"""Avoid cliches.""" proselint-0.10.2/proselint/checks/cliches/hell.py0000664000372000037200000000104613331225053022640 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Too much yelling. --- layout: post source: ??? source_url: ??? title: yelling date: 2014-06-10 12:31:19 categories: writing --- Never use the phrase 'all hell broke loose'. """ from proselint.tools import existence_check, memoize @memoize def check_repeated_exclamations(text): """Check the text.""" err = "leonard.hell" msg = u"Never use the words 'all hell broke loose'." regex = r"all hell broke loose" return existence_check( text, [regex], err, msg, max_errors=1) proselint-0.10.2/proselint/checks/cliches/misc.py0000664000372000037200000006142313331225053022654 0ustar travistravis00000000000000# -*- coding: utf-8 -*- u"""Cliches are cliché.""" from proselint.tools import memoize, existence_check @memoize def check_cliches_garner(text): """Check the text. source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY """ err = "cliches.garner" msg = u"'{}' is cliché." cliches = [ "a fate worse than death", "alas and alack", "at the end of the day", "bald-faced lie", "between a rock and a hard place", "between Scylla and Charybdis", "between the devil and the deep blue sea", "betwixt and between", "blissful ignorance", "blow a fuse", "bulk large", "but that's another story", "cast aspersions", "chase a red herring", "comparing apples and oranges", "compleat", "conspicuous by its absence", "crystal clear", "cutting edge", "decision-making process", "dubious distinction", "duly authorized", "eyes peeled", "far be it from me", "fast and loose", "fills the bill", "first and foremost", "for free", "get with the program", "gilding the lily", "have a short fuse", "he's got his hands full", "his own worst enemy", "his work cut out for him", "hither and yon", "Hobson's choice", "horns of a dilemma", "if you catch my drift", "in light of", "in the final analysis", "in the last analysis", "innocent bystander", "it's not what you know, it's who you know", "last but not least", "make a mockery of", "male chauvinism", "moment of truth", "more in sorrow than in anger", "more sinned against than sinning", "my better half", "nip in the bud", "olden days", "on the same page", "presidential timber", "pulled no punches", "quantum jump", "quantum leap", "redound to one's credit", "redound to the benefit of", "sea change", "shirked his duties", "six of one, half a dozen of the other", "stretched to the breaking point", "than you can shake a stick at", "the cream of the crop", "the cream rises to the top", "the straw that broke the camel's back", "thick as thieves", "thinking outside the box", "thought leaders?", "throw the baby out with the bathwater", "various and sundry", "viable alternative", "wax eloquent", "wax poetic", "we've got a situation here", "whet (?:the|your) appetite", "wool pulled over our eyes", "writ large", ] return existence_check(text, cliches, err, msg, join=True) @memoize def check_cliches_write_good(text): """Check the text. source: write-good source_url: https://github.com/btford/write-good """ err = "cliches.write_good" msg = u"'{}' is a cliché." cliches = [ "a chip off the old block", "a clean slate", "a dark and stormy night", "a far cry", "a fine kettle of fish", "a loose cannon", "a penny saved is a penny earned", "a tough row to hoe", "a word to the wise", "ace in the hole", "acid test", "add insult to injury", "against all odds", "air your dirty laundry", "all fun and games", "all in a day's work", "all talk, no action", "all thumbs", "all your eggs in one basket", "all's fair in love and war", "all's well that ends well", "almighty dollar", "American as apple pie", "an axe to grind", "another day, another dollar", "armed to the teeth", "as luck would have it", "as old as time", "as the crow flies", "at loose ends", "at my wits end", "avoid like the plague", "babe in the woods", "back against the wall", "back in the saddle", "back to square one", "back to the drawing board", "bad to the bone", "badge of honor", "bald faced liar", "ballpark figure", "banging your head against a brick wall", "baptism by fire", "barking up the wrong tree", "bat out of hell", "be all and end all", "beat a dead horse", "beat around the bush", "been there, done that", "beggars can't be choosers", "behind the eight ball", "bend over backwards", "benefit of the doubt", "bent out of shape", "best thing since sliced bread", "bet your bottom dollar", "better half", "better late than never", "better mousetrap", "better safe than sorry", "between a rock and a hard place", "beyond the pale", "bide your time", "big as life", "big cheese", "big fish in a small pond", "big man on campus", "bigger they are the harder they fall", "bird in the hand", "bird's eye view", "birds and the bees", "birds of a feather flock together", "bit the hand that feeds you", "bite the bullet", "bite the dust", "bitten off more than he can chew", "black as coal", "black as pitch", "black as the ace of spades", "blast from the past", "bleeding heart", "blessing in disguise", "blind ambition", "blind as a bat", "blind leading the blind", "blood is thicker than water", "blood sweat and tears", "blow off steam", "blow your own horn", "blushing bride", "boils down to", "bolt from the blue", "bone to pick", "bored stiff", "bored to tears", "bottomless pit", "boys will be boys", "bright and early", "brings home the bacon", "broad across the beam", "broken record", "brought back to reality", "bull by the horns", "bull in a china shop", "burn the midnight oil", "burning question", "burning the candle at both ends", "burst your bubble", "bury the hatchet", "busy as a bee", "by hook or by crook", "call a spade a spade", "called onto the carpet", "calm before the storm", "can of worms", "can't cut the mustard", "can't hold a candle to", "case of mistaken identity", "cat got your tongue", "cat's meow", "caught in the crossfire", "caught red-handed", "checkered past", "chomping at the bit", "cleanliness is next to godliness", "clear as a bell", "clear as mud", "close to the vest", "cock and bull story", "cold shoulder", "come hell or high water", "cool as a cucumber", "cool, calm, and collected", "cost a king's ransom", "count your blessings", "crack of dawn", "crash course", "creature comforts", "cross that bridge when you come to it", "crushing blow", "cry like a baby", "cry me a river", "cry over spilt milk", "crystal clear", "curiosity killed the cat", "cut and dried", "cut through the red tape", "cut to the chase", "cute as a bugs ear", "cute as a button", "cute as a puppy", "cuts to the quick", "dark before the dawn", "day in, day out", "dead as a doornail", "devil is in the details", "dime a dozen", "divide and conquer", "dog and pony show", "dog days", "dog eat dog", "dog tired", "don't burn your bridges", "don't count your chickens", "don't look a gift horse in the mouth", "don't rock the boat", "don't step on anyone's toes", "don't take any wooden nickels", "down and out", "down at the heels", "down in the dumps", "down the hatch", "down to earth", "draw the line", "dressed to kill", "dressed to the nines", "drives me up the wall", "dull as dishwater", "dyed in the wool", "eagle eye", "ear to the ground", "early bird catches the worm", "easier said than done", "easy as pie", "eat your heart out", "eat your words", "eleventh hour", "even the playing field", "every dog has its day", "every fiber of my being", "everything but the kitchen sink", "eye for an eye", "face the music", "facts of life", "fair weather friend", "fall by the wayside", "fan the flames", "feast or famine", "feather your nest", "feathered friends", "few and far between", "fifteen minutes of fame", "filthy vermin", "fine kettle of fish", "fish out of water", "fishing for a compliment", "fit as a fiddle", "fit the bill", "fit to be tied", "flash in the pan", "flat as a pancake", "flip your lid", "flog a dead horse", "fly by night", "fly the coop", "follow your heart", "for all intents and purposes", "for the birds", "for what it's worth", "force of nature", "force to be reckoned with", "forgive and forget", "fox in the henhouse", "free and easy", "free as a bird", "fresh as a daisy", "full steam ahead", "fun in the sun", "garbage in, garbage out", "gentle as a lamb", "get a kick out of", "get a leg up", "get down and dirty", "get the lead out", "get to the bottom of", "get your feet wet", "gets my goat", "gilding the lily", "give and take", "go against the grain", "go at it tooth and nail", "go for broke", "go him one better", "go the extra mile", "go with the flow", "goes without saying", "good as gold", "good deed for the day", "good things come to those who wait", "good time was had by all", "good times were had by all", "greased lightning", "greek to me", "green thumb", "green-eyed monster", "grist for the mill", "growing like a weed", "hair of the dog", "hand to mouth", "happy as a clam", "happy as a lark", "hasn't a clue", "have a nice day", "have high hopes", "have the last laugh", "haven't got a row to hoe", "head honcho", "head over heels", "hear a pin drop", "heard it through the grapevine", "heart's content", "heavy as lead", "hem and haw", "high and dry", "high and mighty", "high as a kite", "hit paydirt", "hold your head up high", "hold your horses", "hold your own", "hold your tongue", "honest as the day is long", "horns of a dilemma", "horse of a different color", "hot under the collar", "hour of need", "I beg to differ", "icing on the cake", "if the shoe fits", "if the shoe were on the other foot", "in a jam", "in a jiffy", "in a nutshell", "in a pig's eye", "in a pinch", "in a word", "in hot water", "in the gutter", "in the nick of time", "in the thick of it", "in your dreams", "it ain't over till the fat lady sings", "it goes without saying", "it takes all kinds", "it takes one to know one", "it's a small world", "it's only a matter of time", "ivory tower", "Jack of all trades", "jockey for position", "jog your memory", "joined at the hip", "judge a book by its cover", "jump down your throat", "jump in with both feet", "jump on the bandwagon", "jump the gun", "jump to conclusions", "just a hop, skip, and a jump", "just the ticket", "justice is blind", "keep a stiff upper lip", "keep an eye on", "keep it simple, stupid", "keep the home fires burning", "keep up with the Joneses", "keep your chin up", "keep your fingers crossed", "kick the bucket", "kick up your heels", "kick your feet up", "kid in a candy store", "kill two birds with one stone", "kiss of death", "knock it out of the park", "knock on wood", "knock your socks off", "know him from Adam", "know the ropes", "know the score", "knuckle down", "knuckle sandwich", "knuckle under", "labor of love", "ladder of success", "land on your feet", "lap of luxury", "last but not least", "last hurrah", "last-ditch effort", "law of the jungle", "law of the land", "lay down the law", "leaps and bounds", "let sleeping dogs lie", "let the cat out of the bag", "let the good times roll", "let your hair down", "let's talk turkey", "letter perfect", "lick your wounds", "lies like a rug", "life's a bitch", "life's a grind", "light at the end of the tunnel", "lighter than a feather", "lighter than air", "like clockwork", "like father like son", "like taking candy from a baby", "like there's no tomorrow", "lion's share", "live and learn", "live and let live", "long and short of it", "long lost love", "look before you leap", "look down your nose", "look what the cat dragged in", "looking a gift horse in the mouth", "looks like death warmed over", "loose cannon", "lose your head", "lose your temper", "loud as a horn", "lounge lizard", "loved and lost", "low man on the totem pole", "luck of the draw", "luck of the Irish", "make hay while the sun shines", "make money hand over fist", "make my day", "make the best of a bad situation", "make the best of it", "make your blood boil", "man of few words", "man's best friend", "mark my words", "meaningful dialogue", "missed the boat on that one", "moment in the sun", "moment of glory", "moment of truth", "money to burn", "more power to you", "more than one way to skin a cat", "movers and shakers", "moving experience", "naked as a jaybird", "naked truth", "neat as a pin", "needle in a haystack", "needless to say", "neither here nor there", "never look back", "never say never", "nip and tuck", "nip it in the bud", "no guts, no glory", "no love lost", "no pain, no gain", "no skin off my back", "no stone unturned", "no time like the present", "no use crying over spilled milk", "nose to the grindstone", "not a hope in hell", "not a minute's peace", "not in my backyard", "not playing with a full deck", "not the end of the world", "not written in stone", "nothing to sneeze at", "nothing ventured nothing gained", "now we're cooking", "off the top of my head", "off the wagon", "off the wall", "old hat", "older and wiser", "older than dirt", "older than Methuselah", "on a roll", "on cloud nine", "on pins and needles", "on the bandwagon", "on the money", "on the nose", "on the rocks", "on the spot", "on the tip of my tongue", "on the wagon", "on thin ice", "once bitten, twice shy", "one bad apple doesn't spoil the bushel", "one born every minute", "one brick short", "one foot in the grave", "one in a million", "one red cent", "only game in town", "open a can of worms", "open and shut case", "open the flood gates", "opportunity doesn't knock twice", "out of pocket", "out of sight, out of mind", "out of the frying pan into the fire", "out of the woods", "out on a limb", "over a barrel", "over the hump", "pain and suffering", "pain in the", "panic button", "par for the course", "part and parcel", "party pooper", "pass the buck", "patience is a virtue", "pay through the nose", "penny pincher", "perfect storm", "pig in a poke", "pile it on", "pillar of the community", "pin your hopes on", "pitter patter of little feet", "plain as day", "plain as the nose on your face", "play by the rules", "play your cards right", "playing the field", "playing with fire", "pleased as punch", "plenty of fish in the sea", "point with pride", "poor as a church mouse", "pot calling the kettle black", "pretty as a picture", "pull a fast one", "pull your punches", "pulling your leg", "pure as the driven snow", "put it in a nutshell", "put one over on you", "put the cart before the horse", "put the pedal to the metal", "put your best foot forward", "put your foot down", "quick as a bunny", "quick as a lick", "quick as a wink", "quick as lightning", "quiet as a dormouse", "rags to riches", "raining buckets", "raining cats and dogs", "rank and file", "rat race", "reap what you sow", "red as a beet", "red herring", "reinvent the wheel", "rich and famous", "rings a bell", "ripe old age", "ripped me off", "rise and shine", "road to hell is paved with good intentions", "rob Peter to pay Paul", "roll over in the grave", "rub the wrong way", "ruled the roost", "running in circles", "sad but true", "sadder but wiser", "salt of the earth", "scared stiff", "scared to death", "sealed with a kiss", "second to none", "see eye to eye", "seen the light", "seize the day", "set the record straight", "set the world on fire", "set your teeth on edge", "sharp as a tack", "shoot for the moon", "shoot the breeze", "shot in the dark", "shoulder to the wheel", "sick as a dog", "sigh of relief", "signed, sealed, and delivered", "sink or swim", "six of one, half a dozen of another", "skating on thin ice", "slept like a log", "slinging mud", "slippery as an eel", "slow as molasses", "smart as a whip", "smooth as a baby's bottom", "sneaking suspicion", "snug as a bug in a rug", "sow wild oats", "spare the rod, spoil the child", "speak of the devil", "spilled the beans", "spinning your wheels", "spitting image of", "spoke with relish", "spread like wildfire", "spring to life", "squeaky wheel gets the grease", "stands out like a sore thumb", "start from scratch", "stick in the mud", "still waters run deep", "stitch in time", "stop and smell the roses", "straight as an arrow", "straw that broke the camel's back", "strong as an ox", "stubborn as a mule", "stuff that dreams are made of", "stuffed shirt", "sweating blood", "sweating bullets", "take a load off", "take one for the team", "take the bait", "take the bull by the horns", "take the plunge", "takes one to know one", "takes two to tango", "the more the merrier", "the real deal", "the real McCoy", "the red carpet treatment", "the same old story", "there is no accounting for taste", "thick as a brick", "thick as thieves", "thin as a rail", "think outside of the box", "third time's the charm", "this day and age", "this hurts me worse than it hurts you", "this point in time", "three sheets to the wind", "through thick and thin", "throw in the towel", "tie one on", "tighter than a drum", "time and time again", "time is of the essence", "tip of the iceberg", "tired but happy", "to coin a phrase", "to each his own", "to make a long story short", "to the best of my knowledge", "toe the line", "tongue in cheek", "too good to be true", "too hot to handle", "too numerous to mention", "touch with a ten foot pole", "tough as nails", "trial and error", "trials and tribulations", "tried and true", "trip down memory lane", "twist of fate", "two cents worth", "two peas in a pod", "ugly as sin", "under the counter", "under the gun", "under the same roof", "under the weather", "until the cows come home", "unvarnished truth", "up the creek", "uphill battle", "upper crust", "upset the applecart", "vain attempt", "vain effort", "vanquish the enemy", "vested interest", "waiting for the other shoe to drop", "wakeup call", "warm welcome", "watch your p's and q's", "watch your tongue", "watching the clock", "water under the bridge", "weather the storm", "weed them out", "week of Sundays", "went belly up", "wet behind the ears", "what goes around comes around", "what you see is what you get", "when it rains, it pours", "when push comes to shove", "when the cat's away", "when the going gets tough, the tough get going", "white as a sheet", "whole ball of wax", "whole hog", "whole nine yards", "wild goose chase", "will wonders never cease?", "wisdom of the ages", "wise as an owl", "wolf at the door", "words fail me", "work like a dog", "world weary", "worst nightmare", "worth its weight in gold", "wrong side of the bed", "yanking your chain", "yappy as a dog", "years young", "you are what you eat", "you can run but you can't hide", "you only live once", "you're the boss ", "young and foolish", "young and vibrant", ] return existence_check(text, cliches, err, msg, join=True) @memoize def check_cliches_gnu_diction(text): """Check the text. source: GNU diction source_url: https://directory.fsf.org/wiki/Diction """ err = "cliches.gnu_diction" msg = u"'{}' is a cliché." list = [ "a matter of concern", "all things being equal", "as a last resort", "attached hereto", "by no means", "conspicuous by its absence", "easier said than done", "enclosed herewith", "if and when", "in reference to", "in short supply", "in the foreseeable future", "in the long run", "in the matter of", "it stands to reason", "many and diverse", "on the right track", "par for the course", "please feel free to", "pursuant to your request", "regarding the matter of", "slowly but surely", "this will acknowledge", "we are pleased to advice", "we regret to inform you", "we wish to state", "you are hereby advised that", ] return existence_check(text, list, err, msg, join=True, ignore_case=True) proselint-0.10.2/proselint/checks/terms/0000775000372000037200000000000013331225202021055 5ustar travistravis00000000000000proselint-0.10.2/proselint/checks/terms/eponymous_adjectives.py0000664000372000037200000000125013331225053025670 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Eponymous adjectives. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: Eponymous adjectives date: 2014-06-10 12:31:19 categories: writing --- Eponymous adjectives. """ from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "garner.eponymous_adjective" msg = "'{}' is the preferred eponymous adjective." preferences = [ ["Mephistophelean", ["Mephistophelian"]], ["Shakespearean", ["Shakespearian"]], ] return preferred_forms_check(text, preferences, err, msg) proselint-0.10.2/proselint/checks/terms/animal_adjectives.py0000664000372000037200000000461013331225053025076 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Animal adjectives. --- layout: post source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY title: animal words date: 2014-06-10 12:31:19 categories: writing --- Animal words. """ from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms.""" err = "garner.animal_labels" msg = "There's a word for this: '{}'." preferences = [ ["accipitrine", ["hawk-like"]], ["anserine", ["goose-like"]], ["aquiline", ["eagle-like"]], ["avine", ["bird-like"]], ["cancrine", ["crab-like"]], ["hircine", ["goat-like"]], ["damine", ["deer-like"]], ["corvine", ["crow-like", "raven-like"]], ["crocodiline", ["crocodile-like"]], ["crotaline", ["rattlesnake-like"]], ["falconine", ["falcon-like"]], ["ferine", ["wild animal-like"]], ["hippopotamine", ["hippopotamus-like"]], ["hirundine", ["swallow-like"]], ["hystricine", ["porcupine-like"]], ["lacertine", ["lizard-like"]], ["laridine", ["gull-like"]], ["leporine", ["hare-like"]], ["lumbricine", ["earthworm-like"]], ["lupine", ["wolf-like"]], ["murine", ["mouse-like"]], ["ovine", ["sheep-like"]], ["pardine", ["leopard-like", "panther-like"]], ["passerine", ["sparrow-like"]], ["pavonine", ["peacock-like"]], ["picine", ["woodpecker-like"]], ["piscine", ["fish-like"]], ["ranine", ["frog-like"]], ["scolopendrine", ["centipede-like"]], ["soricine", ["shrew-like"]], ["struthionine", ["ostrich-like"]], ["suilline", ["swine-like"]], ["taurine", ["bull-like", "ox-like"]], ["tigrine", ["tiger-like"]], ["vespine", ["wasp-like"]], ["viperine", ["viper-like"]], ["vituline", ["calf-like", "veal-like"]], ["viverrine", ["mongoose-like"]], ["vulpine", ["fox-like"]], ["vulturine", ["vulture-like"]], ["zebrine", ["zebra-like"]], ["zibeline", ["sable-like"]], ] return preferred_forms_check(text, preferences, err, msg) proselint-0.10.2/proselint/checks/terms/__init__.py0000664000372000037200000000001513331225053023166 0ustar travistravis00000000000000"""Terms.""" proselint-0.10.2/proselint/checks/terms/denizen_labels.py0000664000372000037200000000640313331225053024414 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Denizen labels.""" from proselint.tools import memoize, preferred_forms_check @memoize def check(text): """Suggest the preferred forms. source: Garner's Modern American Usage source_url: http://bit.ly/1T4alrY """ err = "terms.denizen_labels.garner" msg = "'{}' is the preferred denizen label." preferences = [ ["Afrikaner", ["Afrikaaner"]], ["Afrikaner", ["Afrikander"]], ["Alabamian", ["Alabaman"]], ["Albuquerquean", ["Albuquerquian"]], ["Anchorageite", ["Anchoragite"]], ["Angeleno", ["Los Angelean"]], ["Arizonan", ["Arizonian"]], ["Arkansan", ["Arkansawyer"]], ["Belarusian", ["Belarusan"]], ["Caymanian", ["Cayman Islander"]], ["Coloradan", ["Coloradoan"]], ["Fairbanksan", ["Fairbanksian"]], ["Fort Worthian", ["Fort Worther"]], ["Grenadan", ["Grenadian"]], ["Hong Konger", ["Hong Kongite", "Hong Kongian"]], ["Hoosier", ["Indianan", "Indianian"]], ["Illinoisan", ["Illinoisian"]], ["Iowan", ["Iowegian"]], ["Louisianian", ["Louisianan"]], ["Michigander", ["Michiganite", "Michiganian"]], ["Missourian", ["Missouran"]], ["Monegasque", ["Monacan"]], ["Neapolitan", ["Neopolitan"]], ["New Hampshirite", ["New Hampshireite", "New Hampshireman"]], ["New Jerseyan", ["New Jerseyite"]], ["New Orleanian", ["New Orleansian"]], ["Nutmegger", ["Connecticuter"]], ["Oklahoma Cityan", ["Oklahoma Citian"]], ["Oklahoman", ["Oklahomian"]], ["Seattleite", ["Seattlite"]], ["Surinamese", ["Surinamer"]], ["Tallahasseean", ["Tallahassean"]], ["Tennessean", ["Tennesseean"]], ["Tusconan", ["Tusconian", "Tusconite"]], ["Utahn", ["Utahan"]], ["Saudi", ["Saudi Arabian"]], ] return preferred_forms_check(text, preferences, err, msg) @memoize def check_denizen_labels_norris(text): """Suggest the preferred forms. source: Mary Norris source_url: http://nyr.kr/1rGienj """ err = "terms.denizen_labels.norris" msg = "Would you like '{}'?" preferences = [ ["Mancunian", ["Manchesterian"]], ["Mancunians", ["Manchesterians"]], ["Vallisoletano", ["Valladolidian"]], ["Wulfrunian", ["Wolverhamptonian", "Wolverhamptonite"]], ["Novocastrian", ["Newcastleite", "Newcastlite"]], ["Trifluvian", [u"Trois-Rivièrester"]], ["Leodenisian", ["Leedsian"]], ["Minneapolitan", ["Minneapolisian"]], ["Hartlepudlian", ["Hartlepoolian"]], ["Liverpudlian", ["Liverpoolian"]], ["Haligonian", ["Halifaxer"]], ["Varsovian", ["Warsawer", "Warsawian"]], ["Providentian", ["Providencian", "Providencer"]], ["Tridentine", ["Trentian", "Trentonian"]], ] return preferred_forms_check(text, preferences, err, msg) proselint-0.10.2/proselint/checks/terms/venery.py0000664000372000037200000000511313331225053022743 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Names for groups of animals. --- layout: post source: Oxford Dictionaries source_url: http://www.oxforddictionaries.com/words/what-do-you-call-a-group-of title: Names for groups of animals date: 2014-06-10 12:31:19 categories: writing --- Names for groups of animals. """ from proselint.tools import preferred_forms_check, memoize @memoize def check(text): """Check the text.""" err = "oxford.venery_terms" msg = "The venery term is '{}'." term_list = [ ["alligators", "congregation"], ["antelopes", "herd"], ["baboons", "troop"], ["badgers", "cete"], ["bats", "colony"], ["bears", "sloth"], ["buffalo", "herd"], ["bullfinches", "bellowing"], ["caribou", "herd"], ["cats", "glaring"], ["caterpillars", "army"], ["cockroaches", "intrusion"], ["coyotes", "pack"], ["crows", "murder"], ["dogs", "pack"], ["eagles", "convocation"], ["emus", "mob"], ["flamingos", "stand"], ["frogs", "army"], ["goldfinches", "charm"], ["gorillas", "band"], ["guineafowl", "rasp"], ["hedgehogs", "array"], ["herons", "siege"], ["hogs", "parcel"], ["hyenas", "cackle"], ["ibex", "herd"], ["iguanas", "mess"], ["lions", "pride"], ["locusts", "plague"], ["mackerel", "shoal"], ["mares", "stud"], ["minnows", "shoal"], ["moose", "herd"], ["mosquitoes", "scourge"], ["nightingales", "watch"], ["oysters", "bed"], ["partridges", "covey"], ["pelicans", "pod"], ["raccoons", "gaze"], ["ravens", "unkindness"], ["rhinoceroses", "crash"], ["sea urchins", "sea"], ["starlings", "murmuration"], ["toads", "knot"], ["wombats", "wisdom"], ["woodcocks", "fall"], ["woodpeckers", "descent"], ["wrens", "herd"], ] generic_terms = [ "group", "bunch", ] list = [] for term_pair in term_list: for generic in generic_terms: wrong = "a {} of {}".format(generic, term_pair[0]) right = "a {} of {}".format(term_pair[1], term_pair[0]) list += [[right, [wrong]]] return preferred_forms_check(text, list, err, msg) proselint-0.10.2/proselint/score.py0000664000372000037200000000514313331225053020157 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Compute the lintscore on the corpus.""" from __future__ import print_function from builtins import input from builtins import int import os import subprocess import re proselint_path = os.path.dirname(os.path.realpath(__file__)) def score(check=None): """Compute the linter's score on the corpus. Proselint's score reflects the desire to have a linter that catches many errors, but which takes false alarms seriously. It is better not to say something than to say the wrong thing, and the harm from saying the wrong thing is greater than the benefit of saying the right thing. Thus our score metric is defined as: TP * (TP / (FP + TP)) ^ k, where TP is the number of true positives (hits), FP is the number of false positives (false alarms), and k > 0 is a temperature parameter that determines the penalty for imprecision. In general, we should choose a large value of k, one that strongly discourages the creation of rules that can't be trusted. Suppose that k = 2. Then if the linter detects 100 errors, of which 10 are false positives, the score is 81. """ tp = 0 fp = 0 parent_directory = os.path.dirname(proselint_path) path_to_corpus = os.path.join(parent_directory, "corpora", "0.1.0") for root, _, files in os.walk(path_to_corpus): files = [f for f in files if f.endswith(".md")] for f in files: fullpath = os.path.join(root, f) # Run the linter. print("Linting {}".format(f)) out = subprocess.check_output(["proselint", fullpath]) # Determine the number of errors. regex = r".+?:(?P\d+):(?P\d+): (?P.+)" num_errors = len(tuple(re.finditer(regex, out))) print("Found {} errors.".format(num_errors)) # Open the document. subprocess.call(["open", fullpath]) # Ask the scorer how many of the errors were false alarms? input_val = None while not isinstance(input_val, int): try: input_val = input("# of false alarms? ") if input_val == "exit": return else: input_val = int(input_val) fp += input_val tp += (num_errors - input_val) except ValueError: pass print("Currently {} hits and {} false alarms\n---".format(tp, fp)) if (tp + fp) > 0: return tp * (1.0 * tp / (tp + fp)) ** 2 else: return 0 proselint-0.10.2/proselint/__main__.py0000664000372000037200000000021613331225053020560 0ustar travistravis00000000000000""" __main__.py. This lets you run python -m proselint. """ from .command_line import proselint if __name__ == '__main__': proselint() proselint-0.10.2/proselint/__init__.py0000664000372000037200000000015413331225053020600 0ustar travistravis00000000000000"""Proselint applies advice from great writers to your writing.""" from . import tools __all__ = ('tools') proselint-0.10.2/proselint/version.py0000664000372000037200000000007013331225053020523 0ustar travistravis00000000000000"""Proselint version number.""" __version__ = "0.10.2" proselint-0.10.2/proselint/.proselintrc0000664000372000037200000000746413331225053021047 0ustar travistravis00000000000000{ "max_errors": 1000, "checks": { "airlinese.misc" : true, "annotations.misc" : true, "archaism.misc" : true, "cliches.hell" : true, "cliches.misc" : true, "consistency.spacing" : true, "consistency.spelling" : true, "corporate_speak.misc" : true, "cursing.filth" : true, "cursing.nfl" : false, "cursing.nword" : true, "dates_times.am_pm" : true, "dates_times.dates" : true, "hedging.misc" : true, "hyperbole.misc" : true, "jargon.misc" : true, "lexical_illusions.misc" : true, "lgbtq.offensive_terms" : true, "lgbtq.terms" : true, "links.broken" : false, "malapropisms.misc" : true, "misc.apologizing" : true, "misc.back_formations" : true, "misc.bureaucratese" : true, "misc.but" : true, "misc.capitalization" : true, "misc.chatspeak" : true, "misc.commercialese" : true, "misc.composition" : true, "misc.currency" : true, "misc.debased" : true, "misc.false_plurals" : true, "misc.illogic" : true, "misc.inferior_superior" : true, "misc.institution_name" : true, "misc.latin" : true, "misc.many_a" : true, "misc.metaconcepts" : true, "misc.metadiscourse" : true, "misc.narcissism" : true, "misc.not_guilty" : true, "misc.phrasal_adjectives" : true, "misc.preferred_forms" : true, "misc.pretension" : true, "misc.professions" : true, "misc.punctuation" : true, "misc.scare_quotes" : true, "misc.suddenly" : true, "misc.tense_present" : true, "misc.waxed" : true, "misc.whence" : true, "mixed_metaphors.misc" : true, "mondegreens.misc" : true, "needless_variants.misc" : true, "nonwords.misc" : true, "oxymorons.misc" : true, "psychology.misc" : true, "redundancy.misc" : true, "redundancy.ras_syndrome" : true, "skunked_terms.misc" : true, "spelling.able_atable" : true, "spelling.able_ible" : true, "spelling.athletes" : true, "spelling.em_im_en_in" : true, "spelling.er_or" : true, "spelling.in_un" : true, "spelling.misc" : true, "security.credit_card" : true, "security.password" : true, "sexism.misc" : true, "terms.animal_adjectives" : true, "terms.denizen_labels" : true, "terms.eponymous_adjectives" : true, "terms.venery" : true, "typography.diacritical_marks" : true, "typography.exclamation" : true, "typography.symbols" : true, "uncomparables.misc" : true, "weasel_words.misc" : true, "weasel_words.very" : true } } proselint-0.10.2/proselint/demo.md0000664000372000037200000001371713331225053017746 0ustar travistravis00000000000000# Proselint Writing is notoriously hard, even for the best writers. Yet there is a tremendous amount of knowledge about the discipline 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 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. This is a live demo. Obviously, you can hover over the underlined text to see what the issue is, then fix it. # Dates & times The 1950's were a swell time. The 50's were a swell time. Things happened from 1980-1999 and from 240-398 A.D. March, 2013 was notable in that In February of 2010, the mayor considered It's 5 pm somewhere. It's 12 a.m., time to eat lunch. It's 11 p.m. at night. # Consistency This is a sentence! One space after a period. This is a sentence. Two spaces after a period. This is a sentence? Two spaces after a period. This is a sentence. One space after a period. This is a sentence. One space after a period. This is a sentence. One space after a period. This is a sentence. One space after a period. centre centre center organize, organized, organizing, organise recognize, recognise, recognise, recognise # Symbols $1000 USD I hit him over the head with a 2 x 4. # Venery terms A bunch of antelopes walked by the road. A group of emus attacked me. She swam by a bunch of oysters. # Mondegreens They hae slain the Earl o' Moray and Lady Mondegreen. A girl with colitis goes by. # Skunked terms The building is deceptively large. The project would decimate the fragile wetland wilderness. Hopefully, one day we will all grow older. # Links www.google.com http://broken.proselint.com http://news.ycombinator.com # Hyperbolic language and so I said PLEASE STOP YELLING so excited! so excited!! so excited!!! so excited!!!! really?? and so I said PLEASE STOP YELLING and so I said PLEASE STOP YELLING okay? THESE ARE SMALL CAPS at the beginning of a new line. # Preferred forms abbreviatable to NASA academicly superior. transhipped an aider and abbeter it's adducable let's look for an acquiror i wonder what tort-feasor means Get that off of me before I catch on fire! There are many a person I have met and worked with who simply deride themselves into taking some action In the meanwhile, he looked loving at the sheep. Suddenly, I see. # Mixed metaphors Get ready: button your seatbelts. The cream rises to the crop. The biggest bottleneck is that... # Illogic and redundancy he is very smart approximately about 5 atm machines atm machine we associate together it's blatantly obvious that this obviously works. a very unique idea a more perfect union the surrounding circumstances he filled a much-needed gap To coin a phrase from the movie, # Blowing the punchline Suddenly, the car came to a stop. All hell broke loose on the farm. # Clichés under the weather He's a chip off the old block a quantum leap Our cutting edge decision-making process will make your life crystal clear. He's a thought leader. # Security John's cc#: 378282246310005 the password is tnoernturpn my password is long and 'long' my password is amazing # Commercialese inst. please be advised that # Archaism boughten # Dismissive tone this obviously works # Chatspeak brb rofl # Ogilvy's pretension We'll need to reconceptualize this sentence. # Airlinese enplanement We'll be taking off momentarily. # Tense present Save up to 50% or More! between you and i I did it on accident I feel nauseous # Phrasal adjectives It was a highly-anticipated event. The English speaking people speak English. A big ticket item. A right wing militia. # Various misspellings highfaluting the statement was inadmissable in court Nikita Khruschev I feel innundated with email Nicknack He's a shoe-in Brett Farve and Dwayne Wade are good friends. The Chronicals of Narnia # Strunk & White composition & regex checks I did not pay for the check. Honestly, attention to detail is useful. I did not pay attention to detail. I did not pay any attention to detail. # Typography (c) 2015 (R) The Corporation Use ellipsis not three dots... # Denizen labels The Manchesterian was a good Brit. One from Michigan is not a Michiganite but a Michigander. One from Colorado is not a Coloradoan but a Coloradan. # Sexism The lady lawyer handled my case. John and Mary married. Now they are man and wife. Chairman Mao was the chairman of the communist party. # Punctuation Smith, et. al (2006) said # Quoted text John said that I am "very unique." John knows that I am very unique. John knows every unique snowflake is cold. # Metadiscourse The preceeding discussion # Narcisism, metadiscourse, latin, and hedging The 'take-home message' is that more research is needed The rest of this article argues that, to a certain degree in recent years, an increasing number of psychologists have mutatis mutandis proselint-0.10.2/proselint/command_line.py0000664000372000037200000001204313331225053021466 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Command line utility for proselint.""" from __future__ import print_function from __future__ import absolute_import from builtins import str import click import os from .tools import ( close_cache_shelves_after, close_cache_shelves, errors_to_json, lint, ) import shutil import subprocess import sys from .version import __version__ import traceback CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) base_url = "proselint.com/" proselint_path = os.path.dirname(os.path.realpath(__file__)) demo_file = os.path.join(proselint_path, "demo.md") def timing_test(corpus="0.1.0"): """Measure timing performance on the named corpus.""" import time dirname = os.path.dirname corpus_path = os.path.join( dirname(dirname(os.path.realpath(__file__))), "corpora", corpus) start = time.time() for file in os.listdir(corpus_path): filepath = os.path.join(corpus_path, file) if ".md" == filepath[-3:]: subprocess.call(["proselint", filepath, ">/dev/null"]) return time.time() - start def clear_cache(): """Delete the contents of the cache.""" click.echo("Deleting the cache...") # see issue #624 _delete_compiled_python_files() _delete_cache() def _delete_compiled_python_files(): """Remove files with a 'pyc' extension.""" for path, _, files in os.walk(os.getcwd()): for fname in [f for f in files if os.path.splitext(f)[1] == ".pyc"]: try: os.remove(os.path.join(path, fname)) except OSError: pass def _delete_cache(): """Remove the proselint cache.""" proselint_cache = os.path.join("proselint", "cache") try: shutil.rmtree(proselint_cache) except OSError: pass def print_errors(filename, errors, output_json=False, compact=False): """Print the errors, resulting from lint, for filename.""" if output_json: click.echo(errors_to_json(errors)) else: for error in errors: (check, message, line, column, start, end, extent, severity, replacements) = error if compact: filename = "-" click.echo( filename + ":" + str(1 + line) + ":" + str(1 + column) + ": " + check + " " + message) @click.command(context_settings=CONTEXT_SETTINGS) @click.version_option(__version__, '--version', '-v', message='%(version)s') @click.option('--debug', '-d', is_flag=True, help="Give verbose output.") @click.option('--clean', '-c', is_flag=True, help="Clear the cache.") @click.option('--json', '-j', 'output_json', is_flag=True, help="Output as JSON.") @click.option('--time', '-t', is_flag=True, help="Time on a corpus.") @click.option('--demo', is_flag=True, help="Run over demo file.") @click.option('--compact', is_flag=True, help="Shorten output.") @click.argument('paths', nargs=-1, type=click.Path()) @close_cache_shelves_after def proselint(paths=None, version=None, clean=None, debug=None, output_json=None, time=None, demo=None, compact=None): """A CLI for proselint, a linter for prose.""" if time: click.echo(timing_test()) return # In debug or clean mode, delete cache & *.pyc files before running. if debug or clean: clear_cache() # Use the demo file by default. if demo: paths = [demo_file] # Expand the list of directories and files. filepaths = extract_files(list(paths)) # Lint the files num_errors = 0 # Use stdin if no paths were specified if len(paths) == 0: filepaths.append('-') for fp in filepaths: try: if fp == '-': fp = '' f = sys.stdin else: f = click.open_file( fp, 'r', encoding="utf-8", errors="replace") errors = lint(f, debug=debug) num_errors += len(errors) print_errors(fp, errors, output_json, compact=compact) except Exception: traceback.print_exc() # Return an exit code close_cache_shelves() if num_errors > 0: sys.exit(1) else: sys.exit(0) def extract_files(files): """Expand list of paths to include all text files matching the pattern.""" expanded_files = [] legal_extensions = [".md", ".txt", ".rtf", ".html", ".tex", ".markdown"] for f in files: # If it's a directory, recursively walk through it and find the files. if os.path.isdir(f): for dir_, _, filenames in os.walk(f): for filename in filenames: fn, file_extension = os.path.splitext(filename) if file_extension in legal_extensions: joined_file = os.path.join(dir_, filename) expanded_files.append(joined_file) # Otherwise add the file directly. else: expanded_files.append(f) return expanded_files if __name__ == '__main__': proselint() proselint-0.10.2/setup.cfg0000664000372000037200000000037213331225202016267 0ustar travistravis00000000000000[bumpversion] current_version = 0.10.2 commit = True tag = True tag_name = {new_version} message = Bump version to {new_version} [bumpversion:file:proselint/version.py] [metadata] description-file = README.md [egg_info] tag_build = tag_date = 0 proselint-0.10.2/tests/0000775000372000037200000000000013331225202015606 5ustar travistravis00000000000000proselint-0.10.2/tests/test_misc_currency.py0000664000372000037200000000103013331225053022062 0ustar travistravis00000000000000"""Tests for misc.currency check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import currency as chk class TestCheck(Check): """The test class for misc.currency.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.currency.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""It cost $10 dollars.""") proselint-0.10.2/tests/test_leonard.py0000664000372000037200000000154213331225053020651 0ustar travistravis00000000000000"""Test garner.dates.""" from __future__ import absolute_import from __future__ import print_function from .check import Check from proselint.checks.typography import exclamation class TestCheck(Check): """Test class for leonard.exclamation.""" __test__ = True def test_capitalization_and_no_exclamation(self): """Don't throw error when phrase has capitalization.""" text = """ The QUICK BROWN fox juMPED over the lazy cat. """ errors = exclamation.check_repeated_exclamations(text) assert len(errors) == 0 def test_exclamation(self): """Test leonard.exclamation. with exclamation marks.""" text = """Sally sells seashells and they were too expensive!!!!""" errors = exclamation.check_repeated_exclamations(text) print(errors) assert len(errors) == 1 proselint-0.10.2/tests/test_redundancy_misc.py0000664000372000037200000000264513331225053022401 0ustar travistravis00000000000000"""Tests for redundancy.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.redundancy import misc as chk class TestCheck(Check): """The test class for redundancy.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke_check(self): """Basic smoke test for redundancy.misc.check.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""The table was rectangular in shape.""") def test_smoke_garner(self): """Basic smoke test for redundancy.misc.check_garner.""" assert chk.check_garner( """Smoke phrase with nothing flagged.""") == [] assert chk.check_garner( """It was blatantly obvious what to do next.""") != [] def test_smoke_nordquist(self): """Basic smoke test for redundancy.misc.check_norquist.""" assert chk.check_nordquist( """Smoke phrase with nothing flagged.""") == [] assert chk.check_nordquist( """Taking the package was absolutely essential.""") != [] def test_smoke_atd(self): """Basic smoke test for redundancy.misc.check_norquist.""" assert chk.check_atd( """Smoke phrase with nothing flagged.""") == [] assert chk.check_atd( """He often repeated the old adage.""") != [] proselint-0.10.2/tests/test_typography_exclamation.py0000664000372000037200000000205513331225053024017 0ustar travistravis00000000000000"""Tests for typography.exclamation check.""" from __future__ import absolute_import from .check import Check from proselint.checks.typography import exclamation as chk class TestCheck(Check): """The test class for typography.exclamation.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke_repeated_exclamations(self): """Basic smoke test. Test for typography.exclamation.check_repeated_exclamations. """ assert chk.check_repeated_exclamations( """Smoke phrase with nothing flagged.""") == [] assert chk.check_repeated_exclamations( """I'm really excited!!""") != [] def test_smoke_exclamations_ppm(self): """Basic smoke test. Test for typography.exclamation.check_exclamations_ppm. """ assert chk.check_exclamations_ppm( """Smoke phrase with nothing flagged.""") == [] assert chk.check_exclamations_ppm( """I'm really excited! Really!""") != [] proselint-0.10.2/tests/test_spelling_able_ible.py0000664000372000037200000000106313331225053023016 0ustar travistravis00000000000000"""Tests for spelling.able_ible check.""" from __future__ import absolute_import from .check import Check from proselint.checks.spelling import able_ible as chk class TestCheck(Check): """The test class for spelling.able_ible.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for spelling.able_ible.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""It was a sensable decision.""") proselint-0.10.2/tests/test_consistency_spelling.py0000664000372000037200000000134313331225053023462 0ustar travistravis00000000000000"""Tests for consistency.spelling check.""" from __future__ import absolute_import from .check import Check from proselint.checks.consistency import spelling as chk class TestCheck(Check): """The test class for consistency.spelling.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for consistency.spelling.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert self.passes("""The centre for the arts is the art centre.""") assert self.passes("""The center for the arts is the art center.""") assert not self.passes("""The centre of the arts is the art center.""") proselint-0.10.2/tests/test_consistency_spacing.py0000664000372000037200000000124413331225053023271 0ustar travistravis00000000000000"""Tests for consistency.spacing check.""" from __future__ import absolute_import from .check import Check from proselint.checks.consistency import spacing as chk class TestCheck(Check): """The test class for consistency.spacing.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for consistency.spacing.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert self.passes( """This is good. Only one space each time. Every time.""") assert not self.passes("""This is bad. Not consistent. At all.""") proselint-0.10.2/tests/test_misc_debased.py0000664000372000037200000000103713331225053021626 0ustar travistravis00000000000000"""Tests for misc.debased check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import debased as chk class TestCheck(Check): """The test class for misc.debased.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.debased.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""This leaves much to be desired.""") proselint-0.10.2/tests/test_cursing_nword.py0000664000372000037200000000101713331225053022105 0ustar travistravis00000000000000"""Tests for cursing.nword check.""" from __future__ import absolute_import from .check import Check from proselint.checks.cursing import nword as chk class TestCheck(Check): """The test class for cursing.nword.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for cursing.nword.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""The n-word.""") proselint-0.10.2/tests/test_misc_suddenly.py0000664000372000037200000000104013331225053022060 0ustar travistravis00000000000000"""Tests for misc.suddenly check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import suddenly as chk class TestCheck(Check): """The test class for misc.suddenly.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.suddenly.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""Suddenly, it all made sense.""") proselint-0.10.2/tests/test_malaproprisms.py0000664000372000037200000000107313331225053022115 0ustar travistravis00000000000000"""Tests for malaproprisms.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.malapropisms import misc as chk class TestCheck(Check): """The test class for malaproprisms.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for malaproprisms.misc.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""Found in the Infinitesimal Universe.""") proselint-0.10.2/tests/test_misc_commercialese.py0000664000372000037200000000107013331225053023044 0ustar travistravis00000000000000"""Tests for misc.commercialese check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import commercialese as chk class TestCheck(Check): """The test class for misc.commercialese.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.commercialese.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""We regret to inform you of this.""") proselint-0.10.2/tests/test_spelling_in_un.py0000664000372000037200000000104013331225053022223 0ustar travistravis00000000000000"""Tests for spelling.in_un check.""" from __future__ import absolute_import from .check import Check from proselint.checks.spelling import in_un as chk class TestCheck(Check): """The test class for spelling.in_un.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for spelling.in_un.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""The plan was unfeasible.""") proselint-0.10.2/tests/test_misc_latin.py0000664000372000037200000000103113331225053021340 0ustar travistravis00000000000000"""Tests for misc.latin check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import latin as chk class TestCheck(Check): """The test class for misc.latin.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.latin.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""And ceteris paribus, it was good.""") proselint-0.10.2/tests/test_misc_waxed.py0000664000372000037200000000103113331225053021341 0ustar travistravis00000000000000"""Tests for misc.waxed check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import waxed as chk class TestCheck(Check): """The test class for misc.waxed.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.waxed.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""They really could wax poetically.""") proselint-0.10.2/tests/test_misc_apologizing.py0000664000372000037200000000105013331225053022554 0ustar travistravis00000000000000"""Tests for misc.apologizing check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import apologizing as chk class TestCheck(Check): """The test class for misc.apologizing.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.apologizing.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""More research is needed.""") proselint-0.10.2/tests/test_misc_not_guilty.py0000664000372000037200000000110513331225053022430 0ustar travistravis00000000000000"""Tests for misc.not_guilty check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import not_guilty as chk class TestCheck(Check): """The test class for misc.not_guilty.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.not_guilty.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes( """She is not guilty beyond a reasonable doubt.""") proselint-0.10.2/tests/test_strunk_white_eos.py0000664000372000037200000000130313331225053022614 0ustar travistravis00000000000000"""Unit tests for strunk_white_eos.""" # from __future__ import absolute_import # from .check import Check # from proselint.checks.strunkwhite import elementary_composition as chk # class TestCheck(Check): # """Define the suite of checks.""" # __test__ = True # @property # def this_check(self): # return chk # def test_with_utilized(self): # """Don't produce an error when 'use' is used correctly.""" # assert self.check("I use a hammer to drive nails into wood.") # def test_no_utilized(self): # """Produce an error when 'utilize' is used in place of 'use'.""" # assert not self.check("I utilize a hammer to drive nails into wood.") proselint-0.10.2/tests/test_spelling_able_atable.py0000664000372000037200000000110613331225053023331 0ustar travistravis00000000000000"""Tests for spelling.able_atable check.""" from __future__ import absolute_import from .check import Check from proselint.checks.spelling import able_atable as chk class TestCheck(Check): """The test class for spelling.able_atable.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for spelling.able_atable.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""There was a demonstratable difference.""") proselint-0.10.2/tests/test_misc_usage.py0000664000372000037200000000063113331225053021342 0ustar travistravis00000000000000"""Tests for misc.usage check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import usage as chk class TestCheck(Check): """The test class for misc.usage.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.usage.""" pass proselint-0.10.2/tests/test_misc_composition.py0000664000372000037200000000105013331225053022575 0ustar travistravis00000000000000"""Tests for misc.composition check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import composition as chk class TestCheck(Check): """The test class for misc.composition.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.composition.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""His story is not honest.""") proselint-0.10.2/tests/test_misc_preferred_forms.py0000664000372000037200000000106713331225053023426 0ustar travistravis00000000000000"""Tests for misc.preferred_forms check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import preferred_forms as chk class TestCheck(Check): """The test class for misc.preferred_forms.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.preferred_forms.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""It was almost haloween.""") proselint-0.10.2/tests/test_psychology.py0000664000372000037200000000245413331225053021430 0ustar travistravis00000000000000"""Tests for psychology.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.psychology import misc as chk class TestCheck(Check): """The test class for psychology.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke_lie_detector_test(self): """Basic smoke test for psychology.misc.check_lie_detector_test.""" assert chk.check_lie_detector_test( """Smoke phrase with nothing flagged.""") == [] assert chk.check_lie_detector_test( """The defendant took a lie detector test.""") != [] def test_smoke_p_equals_zero(self): """Basic smoke test for psychology.misc.check_p_equals_zero.""" assert chk.check_p_equals_zero( """Smoke phrase with nothing flagged.""") == [] assert chk.check_p_equals_zero( """The effect was highly signficant at p = 0.00.""") != [] def test_smoke_mental_telepathy(self): """Basic smoke test for psychology.misc.check_mental_telepathy.""" assert chk.check_mental_telepathy( """Smoke phrase with nothing flagged.""") == [] assert chk.check_mental_telepathy( """I've been practicing mental telepathy.""") != [] proselint-0.10.2/tests/test_spelling_er_or.py0000664000372000037200000000104213331225053022223 0ustar travistravis00000000000000"""Tests for spelling.er_or check.""" from __future__ import absolute_import from .check import Check from proselint.checks.spelling import er_or as chk class TestCheck(Check): """The test class for spelling.er_or.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for spelling.er_or.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""She met with the invester.""") proselint-0.10.2/tests/test_clear_cache.py0000664000372000037200000001067313331225053021443 0ustar travistravis00000000000000# -*- coding: utf-8 -*- """Tests for the clear cache operation from proselint.command_line.""" import os import unittest from proselint import command_line as cl try: from unittest import mock except ImportError: # Py2.x import mock try: from builtins import PermissionError except ImportError: class PermissionError(OSError): """Introduced in Py3.3, emulate for earlier versions.""" def __init__(self, *args, **kwargs): """Constructor.""" OSError.__init__(self, *args, **kwargs) try: from builtins import FileNotFoundError except ImportError: class FileNotFoundError(OSError): """Introduced in Py3.3, emulate for earlier versions.""" def __init__(self, *args, **kwargs): """Constructor.""" OSError.__init__(self, *args, **kwargs) try: from builtins import IsADirectoryError except ImportError: class IsADirectoryError(OSError): """Introduced in Py3.3, emulate for earlier versions.""" def __init__(self, *args, **kwargs): """Constructor.""" OSError.__init__(self, *args, **kwargs) class Test__delete_compiled_python_files(unittest.TestCase): """proselint.command_line._delete_compiled_python_files().""" def setUp(self): """init common data.""" self.base_dir = '.' self.python_file = 'a.py' self.pyc_file = 'a.pyc' self.dot_pyc = '.pyc' self.files = [ (self.base_dir, ('dummy',), (self.pyc_file, self.python_file, self.dot_pyc)) ] self.pyc_file_path = os.path.join(self.base_dir, self.pyc_file) self.python_file_path = os.path.join(self.base_dir, self.python_file) self.dot_pyc_path = os.path.join(self.base_dir, self.python_file) @mock.patch('os.walk') @mock.patch('os.remove') def test_delete_pyc_file(self, mock_remove, mock_walk): """Ensure 'pyc' files are removed.""" mock_walk.return_value = self.files cl._delete_compiled_python_files() mock_remove.assert_called_with(self.pyc_file_path) @mock.patch('os.walk') @mock.patch('os.remove') def test_files_not_deleted(self, mock_remove, mock_walk): """Ensure non 'pyc' files are not removed.""" mock_walk.return_value = self.files cl._delete_compiled_python_files() with self.assertRaises(AssertionError): mock_remove.assert_called_with(self.python_file_path) with self.assertRaises(AssertionError): mock_remove.assert_called_with(self.dot_pyc_path) @mock.patch('os.walk') @mock.patch('os.remove', side_effect=PermissionError) def test_no_permission(self, mock_remove, mock_walk): """Ignore if unable to delete files.""" mock_walk.return_value = self.files cl._delete_compiled_python_files() @mock.patch('os.walk') @mock.patch('os.remove', side_effect=OSError) def test_on_oserror(self, mock_remove, mock_walk): """Ignore if OSError.""" mock_walk.return_value = self.files cl._delete_compiled_python_files() @mock.patch('os.walk') @mock.patch('os.remove', side_effect=FileNotFoundError) def test_files_not_found(self, mock_remove, mock_walk): """Ignore if file not found.""" mock_walk.return_value = self.files cl._delete_compiled_python_files() @mock.patch('os.walk') @mock.patch('os.remove', side_effect=IsADirectoryError) def test__remove_dir(self, mock_remove, mock_walk): """Ignore if attempt to delete a directory.""" mock_walk.return_value = self.files cl._delete_compiled_python_files() class Test__delete_cache(unittest.TestCase): """proselint.command_line.__delete_cache().""" def setUp(self): """Init common data.""" self.cache_path = os.path.join("proselint", "cache") @mock.patch('shutil.rmtree') def test_rm_cache(self, mock_rmtree): """Correct directory is removed.""" cl._delete_cache() mock_rmtree.assert_called_with(self.cache_path) @mock.patch('shutil.rmtree', side_effect=PermissionError) def test_no_permission(self, mock_rmtree): """Ignore if unable to delete.""" cl._delete_cache() @mock.patch('shutil.rmtree', side_effect=OSError) def test_on_oserror(self, mock_rmtree): """Ignore if general OSError.""" cl._delete_cache() proselint-0.10.2/tests/test_misc_tense_present.py0000664000372000037200000000106613331225053023117 0ustar travistravis00000000000000"""Tests for misc.tense_present check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import tense_present as chk class TestCheck(Check): """The test class for misc.tense_present.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.tense_present.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""I did it on accident honestly.""") proselint-0.10.2/tests/test_misc_punctuation.py0000664000372000037200000000104113331225053022603 0ustar travistravis00000000000000"""Tests for misc.punctuation check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import punctuation as chk class TestCheck(Check): """The test class for misc.punctuation.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.punctuation.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""See Smith et. al.""") proselint-0.10.2/tests/test_misc_professions.py0000664000372000037200000000106013331225053022605 0ustar travistravis00000000000000"""Tests for misc.professions check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import professions as chk class TestCheck(Check): """The test class for misc.professions.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.professions.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""I really need a shoe repair guy.""") proselint-0.10.2/tests/test_weasel_words_very.py0000664000372000037200000000106213331225053022765 0ustar travistravis00000000000000"""Tests for weasel_words.very check.""" from __future__ import absolute_import from .check import Check from proselint.checks.weasel_words import very as chk class TestCheck(Check): """The test class for weasel_words.very.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for weasel_words.very.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""The book was very interesting.""") proselint-0.10.2/tests/test_weasel_words_misc.py0000664000372000037200000000111613331225053022733 0ustar travistravis00000000000000"""Tests for weasel_words.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.weasel_words import misc as chk from nose import SkipTest class TestCheck(Check): """The test class for weasel_words.misc.""" raise SkipTest __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for weasel_words.misc.""" assert self.passes("""Smoke phrase with nothing flagged.""") # FIXME add test when check is implemented proselint-0.10.2/tests/test_oxymorons.py0000664000372000037200000000104413331225053021277 0ustar travistravis00000000000000"""Tests for oxymorons.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.oxymorons import misc as chk class TestCheck(Check): """The test class for oxymorons.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for oxymorons.misc.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""He needed an exact estimate.""") proselint-0.10.2/tests/test_mixed_metaphors.py0000664000372000037200000000161113331225053022412 0ustar travistravis00000000000000"""Tests for mixed_metaphors.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.mixed_metaphors import misc as chk class TestCheck(Check): """The test class for mixed_metaphors.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke_bottleneck(self): """Basic smoke test for check_bottleneck.""" assert chk.check_bottleneck( """Smoke phrase with nothing flagged.""") == [] assert chk.check_bottleneck( """The project produced a huge bottleneck.""") != [] def test_smoke_misc(self): """Basic smoke test for check_misc.""" assert chk.check_misc( """Smoke phrase with nothing flagged.""") == [] assert chk.check_misc( """Writing tests is not rocket surgery.""") != [] proselint-0.10.2/tests/test_cursing_nfl.py0000664000372000037200000000103013331225053021526 0ustar travistravis00000000000000"""Tests for cursing.nfl check.""" from __future__ import absolute_import from .check import Check from proselint.checks.cursing import nfl as chk class TestCheck(Check): """The test class for cursing.nfl.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for cursing.nfl.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""The QB is named ball licker.""") proselint-0.10.2/tests/test_misc_metadiscourse.py0000664000372000037200000000107713331225053023112 0ustar travistravis00000000000000"""Tests for misc.metadiscourse check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import metadiscourse as chk class TestCheck(Check): """The test class for misc.metadiscourse.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.metadiscourse.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""It's based on the rest of this article.""") proselint-0.10.2/tests/__init__.py0000664000372000037200000000003313331225053017717 0ustar travistravis00000000000000"""Tests for proselint.""" proselint-0.10.2/tests/test_misc_inferior_superior.py0000664000372000037200000000113713331225053024005 0ustar travistravis00000000000000"""Tests for misc.inferior_superior check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import inferior_superior as chk class TestCheck(Check): """The test class for misc.inferior_superior.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.inferior_superior.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes( """It was more inferior than the alternative.""") proselint-0.10.2/tests/test_misc_bureaucratese.py0000664000372000037200000000112013331225053023062 0ustar travistravis00000000000000"""Tests for misc.bureaucratese check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import bureaucratese as chk class TestCheck(Check): """The test class for misc.bureaucratese.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.bureaucratese.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes( """I hope the report meets with your approval.""") proselint-0.10.2/tests/test_misc_metaconcepts.py0000664000372000037200000000066513331225053022732 0ustar travistravis00000000000000"""Tests for misc.metaconcepts check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import metaconcepts as chk class TestCheck(Check): """The test class for misc.metaconcepts.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.metaconcepts.""" pass proselint-0.10.2/tests/test_typography_diacritical_marks.py0000664000372000037200000000114213331225053025154 0ustar travistravis00000000000000"""Tests for typography.diacritical_marks check.""" from __future__ import absolute_import from .check import Check from proselint.checks.typography import diacritical_marks as chk class TestCheck(Check): """The test class for typography.diacritical_marks.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for typography.diacritical_marks.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""He saw the performance by Beyonce.""") proselint-0.10.2/tests/test_misc_back_formations.py0000664000372000037200000000107313331225053023400 0ustar travistravis00000000000000"""Tests for misc.back_formations check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import back_formations as chk class TestCheck(Check): """The test class for misc.back_formations.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.back_formations.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""It is an improprietous use.""") proselint-0.10.2/tests/test_misc_false_plurals.py0000664000372000037200000000144713331225053023100 0ustar travistravis00000000000000"""Tests for misc.false_plurals check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import false_plurals as chk class TestCheck(Check): """The test class for misc.false_plurals.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.false_plurals.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""There were several phenomenons.""") def test_smoke_kudos(self): """Basic smoke test for misc.false_plurals.kudos.""" assert chk.check_kudos("""Smoke phrase with nothing flagged.""") == [] assert chk.check_kudos("""I give you many kudos.""") != [] proselint-0.10.2/tests/test_misc_narcissism.py0000664000372000037200000000117513331225053022415 0ustar travistravis00000000000000"""Tests for misc.narcissism check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import narcissism as chk class TestCheck(Check): """The test class for misc.narcissism.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.narcissism.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes( """In recent years, an increasing number of scientists have studied the problem in detail.""") proselint-0.10.2/tests/test_lgbtq_terms.py0000664000372000037200000000162213331225053021547 0ustar travistravis00000000000000"""Tests for lgbtq.offensive_terms check.""" from __future__ import absolute_import from .check import Check from proselint.checks.lgbtq import terms as chk class TestCheck(Check): """The test class for lgbtq.terms.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for lgbtq.terms.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert self.passes("""They were a gay couple.""") assert not self.passes("""He was a homosexual man.""") def test_homosexual_term(self): """Check that the term homosexual does not get caught.""" assert self.passes("""Homosexual.""") def test_sexual_prefence(self): """Check that sexual preference is flagged.""" assert not self.passes("""My sexual preference is for women.""") proselint-0.10.2/tests/test_preferred_forms_check.py0000664000372000037200000000231313331225053023543 0ustar travistravis00000000000000"""Test the preferred_forms_check function from the tools.py module.""" from __future__ import absolute_import from .check import Check from proselint.tools import preferred_forms_check as chk class TestCheck(Check): """The test class for tools.preferred_forms_check.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def setUp(self): """Create some test fixtures.""" self.l = [['use', ['utilize']]] self.l_caps = [["Stone Age", ["stone age"]]] self.err = 'error message' self.msg = 'use the preferred form' def test_smoke(self): """Basic smoke test for preferred_forms_check.""" assert chk( "We utilize this tech", self.l, self.err, self.msg) != [] assert chk( "We use this tech", self.l, self.err, self.msg) == [] def test_capitalization(self): """Test for preferred forms involving capitalization.""" assert not chk( "In the stone age", self.l_caps, self.err, self.msg, ignore_case=False) assert chk( "In the Stone Age", self.l_caps, self.err, self.msg, ignore_case=False) == [] proselint-0.10.2/tests/test_cliches.py0000664000372000037200000000340613331225053020640 0ustar travistravis00000000000000"""Test the Cliches.misc module.""" from __future__ import absolute_import from .check import Check from proselint.checks.cliches import misc as chk class TestCheck(Check): """The test class for cliches.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def setUp(self): """Create test sentences.""" self.l_garner = """Worse than a fate worse than death.""" self.l_write_good = """He's a chip off the old block.""" self.l_gnu_diction = """It's a matter of concern.""" def test_cliches_garner_basic(self): """Basic checks on check_cliches_garner.""" assert chk.check_cliches_garner("""No cliches here.""") == [] # use one of the example cliches to verify basic functionality assert chk.check_cliches_garner(self.l_garner) != [] assert "cliches.garner" in chk.check_cliches_garner(self.l_garner)[0] def test_cliches_write_good_basic(self): """Basic checks on check_cliches_write_good.""" assert chk.check_cliches_write_good("""No cliches here.""") == [] # use one of the example cliches to verify basic functionality assert chk.check_cliches_write_good(self.l_write_good) != [] assert "cliches.write_good" in chk.check_cliches_write_good( self.l_write_good)[0] def test_cliches_gnu_diction_basic(self): """Basic check on check_cliches_gnu_diction.""" assert chk.check_cliches_gnu_diction("""No cliches here.""") == [] # use one of the example cliches to verify basic functionality assert chk.check_cliches_gnu_diction(self.l_gnu_diction) != [] assert "cliches.gnu_diction" in chk.check_cliches_gnu_diction( self.l_gnu_diction)[0] proselint-0.10.2/tests/test_terms_venery.py0000664000372000037200000000104013331225053021740 0ustar travistravis00000000000000"""Tests for terms.venery check.""" from __future__ import absolute_import from .check import Check from proselint.checks.terms import venery as chk class TestCheck(Check): """The test class for terms.venery.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for terms.venery.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""There was a group of alligators.""") proselint-0.10.2/tests/test_existence_check.py0000664000372000037200000000355413331225053022356 0ustar travistravis00000000000000"""Test the existence_check function from the tools.py module.""" from __future__ import absolute_import from .check import Check from proselint.tools import existence_check as chk class TestCheck(Check): """The test class for tools.existence_check.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def setUp(self): """setUp method creating some test fixtures.""" self.l = ['abc'] self.err = 'error message' self.msg = 'it exists' def test_smoke(self): """Basic smoke test to determine that existence_check is working.""" assert chk( """abc is as easy as 123""", self.l, self.err, self.msg) != [] assert chk( """easy breezy""", self.l, self.err, self.msg) == [] assert self.err in chk( """abc is as easy as 123""", self.l, self.err, self.msg)[0] assert self.msg in chk( """abc is as easy as 123""", self.l, self.err, self.msg)[0] def test_multiple_matches(self): """Test that multiple matches are found correctly.""" assert len( chk("""abc and abc are as easy as 123""", self.l, self.err, self.msg)) == 2 assert len( chk("""ABC and abc are as easy as 123""", self.l, self.err, self.msg, ignore_case=True)) == 2 assert chk( """abcabc are easy as 123""", self.l, self.err, self.msg) == [] def test_string_types(self): """Test that the function works with different string types.""" assert chk('abc is easy as 123', self.l, self.err, self.msg) != [] assert chk("abc is easy as 123", self.l, self.err, self.msg) != [] assert chk(u'abc is easy as 123', self.l, self.err, self.msg) != [] assert chk(u"abc is easy as 123", self.l, self.err, self.msg) != [] proselint-0.10.2/tests/test_topic_detector.py0000664000372000037200000000130513331225053022231 0ustar travistravis00000000000000"""Test the topic detector tool.""" from proselint.tools import topics def test_50_Cent_detector_on_topic(): """Check precision of the 50 Cent topic-detector.""" text = """With the aid of Eminem and Dr. Dre (who produced his first major-label album, Get Rich or Die Tryin'), Jackson became one of the world's best selling rappers and rose to prominence with East Coast hip hop group G-Unit (which he leads de facto). """ assert("50 Cent" in topics(text)) text = """Hip hop was started in the early 50's.""" assert("50 Cent" not in topics(text)) text = """Nowadays it costs 50 cents to buy a lollipop.""" assert("50 Cent" not in topics(text)) proselint-0.10.2/tests/test_jargon.py0000664000372000037200000000103413331225053020501 0ustar travistravis00000000000000"""Tests for jargon.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.jargon import misc as chk class TestCheck(Check): """The test class for jargon.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for jargon.misc.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""I agree it's in the affirmative.""") proselint-0.10.2/tests/test_misc_greylist.py0000664000372000037200000000104513331225053022100 0ustar travistravis00000000000000"""Tests for misc.greylist check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import greylist as chk class TestCheck(Check): """The test class for misc.greylist.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.greylist.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""She should utilize her knowledge.""") proselint-0.10.2/tests/test_nonwords.py0000664000372000037200000000104313331225053021072 0ustar travistravis00000000000000"""Tests for nonwords.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.nonwords import misc as chk class TestCheck(Check): """The test class for nonwords.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for nonwords.misc.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""The test was good irregardless.""") proselint-0.10.2/tests/test_corporate_speak.py0000664000372000037200000000117513331225053022410 0ustar travistravis00000000000000"""Tests for corporate_speak.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.corporate_speak import misc as chk class TestCheck(Check): """The test class for corporate_speak.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for corporate_speak.misc.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert self.passes("""We will discuss it later.""") assert not self.passes("""We will circle back around to it.""") proselint-0.10.2/tests/test_garner_dates.py0000664000372000037200000000210013331225053021652 0ustar travistravis00000000000000"""Test garner.dates.""" from __future__ import absolute_import from __future__ import print_function from .check import Check from proselint.checks.dates_times import dates class TestCheck(Check): """Test class for garner.dates.""" __test__ = True def test_50s_hyphenation(self): """Find unneeded hyphen in 50's.""" text = """The 50's were swell.""" errors = dates.check_decade_apostrophes_short(text) assert len(errors) == 1 def test_50_Cent_hyphenation(self): """Don't flag 50's when it refers to 50 Cent's manager.""" text = """ Dr. Dre suggested to 50's manager that he look into signing Eminem to the G-Unit record label. """ errors = dates.check_decade_apostrophes_short(text) assert len(errors) == 0 def test_dash_and_from(self): """Test garner.check_dash_and_from.""" text = """From 1999-2002, Sally served as chair of the committee.""" errors = dates.check_dash_and_from(text) print(errors) assert len(errors) == 1 proselint-0.10.2/tests/test_skunked_terms.py0000664000372000037200000000112513331225053022100 0ustar travistravis00000000000000"""Tests for skunked_terms.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.skunked_terms import misc as chk class TestCheck(Check): """The test class for skunked_terms.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for skunked_terms.misc.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes( """I gave an impassionate defence of the situation.""") proselint-0.10.2/tests/test_redundancy_ras_syndrome.py0000664000372000037200000000111113331225053024136 0ustar travistravis00000000000000"""Tests for redundancy.ras_syndrome check.""" from __future__ import absolute_import from .check import Check from proselint.checks.redundancy import ras_syndrome as chk class TestCheck(Check): """The test class for redundancy.ras_syndrome.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for redundancy.ras_syndrome.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""Please enter your PIN number.""") proselint-0.10.2/tests/test_dates_times_am_pm.py0000664000372000037200000000377713331225053022713 0ustar travistravis00000000000000"""Tests for dates_times.am_pm check.""" from __future__ import absolute_import from .check import Check from proselint.checks.dates_times import am_pm as chk class TestCheck(Check): """The test class for dates_times.am_pm.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke_check_lowercase_periods(self): """Basic smoke test. This is for the function dates_times.am_pm.check_lowercase_periods. """ assert chk.check_lowercase_periods( "Basic smoke phrase without issues.") == [] assert chk.check_lowercase_periods( "It happened at 7 a.m.") == [] assert chk.check_lowercase_periods( "It happened at 7 am.") != [] def test_smoke_check_spacing(self): """Basic smoke test. This is for the function dates_times.am_pm.check_spacing. """ assert chk.check_spacing( "Basic smoke phrase without issues.") == [] assert chk.check_spacing( "It happened at 7 a.m.") == [] assert chk.check_spacing( "It happened at 7a.m.") != [] def test_smoke_check_midnight_noon(self): """Basic smoke test. This for the function dates_times.am_pm.midnight_noon. """ assert chk.check_midnight_noon( "Basic smoke phrase without issues.") == [] assert chk.check_midnight_noon( "It happened at noon.") == [] assert chk.check_midnight_noon( "It happened at 12 a.m.") != [] def test_smoke_check_redundancy(self): """Basic smoke test. This for the function dates_times.am_pm.check_redundancy. """ assert chk.check_redundancy( "Basic smoke phrase without issues.") == [] assert chk.check_redundancy( "It happened at 7 a.m.") == [] assert chk.check_redundancy( "It happened at 7a.m. in the morning.") != [] proselint-0.10.2/tests/test_misc_illogic.py0000664000372000037200000000225713331225053021666 0ustar travistravis00000000000000"""Tests for misc.illogic check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import illogic as chk class TestCheck(Check): """The test class for misc.illogic.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.illogic.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""We should preplan the trip.""") def test_smoke_coin_a_phrase_from(self): """Basic smoke test for misc.illogic.check_coin_a_phrase_from.""" assert chk.check_coin_a_phrase_from( """Smoke phrase with nothing flagged.""") == [] assert chk.check_coin_a_phrase_from( """To coin a phrase from him, No diggity""") != [] def test_smoke_check_without_your_collusion(self): """Basic smoke test for misc.illogic.""" assert chk.check_without_your_collusion( """Smoke phrase with nothing flagged.""") == [] assert chk.check_without_your_collusion( """Not Without your collusion you won't'.""") != [] proselint-0.10.2/tests/test_exit_codes.py0000664000372000037200000000107113331225053021350 0ustar travistravis00000000000000"""Check that the CLI returns the appropriate exit code.""" import subprocess def test_exit_code_demo(): """Ensure that linting the demo returns an exit code of 1.""" try: subprocess.check_output(["proselint", "--demo"]) except subprocess.CalledProcessError as grepexc: assert(grepexc.returncode == 1) def test_exit_code_version(): """Ensure that getting the version returns an exit code of 0.""" try: subprocess.check_output(["proselint", "--version"]) except subprocess.CalledProcessError: assert(False) proselint-0.10.2/tests/_test_version.py0000664000372000037200000000074513331225053021055 0ustar travistravis00000000000000"""Test version number.""" from __future__ import absolute_import from __future__ import print_function from .check import Check from proselint.version import __version__ import subprocess class TestCheck(Check): """Test class for version number.""" __test__ = True def test_version(self): """Make sure the version number is correct.""" out = subprocess.check_output(["proselint", "--version"]) assert out.decode('utf-8') == __version__ + "\n" proselint-0.10.2/tests/test_hedging.py0000664000372000037200000000104713331225053020632 0ustar travistravis00000000000000"""Tests for hedging.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.hedging import misc as chk class TestCheck(Check): """The test class for hedging.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for hedging.misc.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""I would argue that this is a good test.""") proselint-0.10.2/tests/test_dates_times_dates.py0000664000372000037200000000514613331225053022712 0ustar travistravis00000000000000"""Tests for dates_times.dates check.""" from __future__ import absolute_import from .check import Check from proselint.checks.dates_times import dates as chk class TestCheck(Check): """The test class for dates_times.dates.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke_check_decade_apostrophes_short(self): """Basic smoke test. This for the function dates_times.dates.check_decade_apostrophes_short. """ assert chk.check_decade_apostrophes_short( "Basic smoke phrase without issues.") == [] assert chk.check_decade_apostrophes_short( "It happened in the 90s.") == [] assert chk.check_decade_apostrophes_short( "It happened in the 90's.") != [] def test_smoke_check_decade_apostrophes_long(self): """Basic smoke test. This is for the function dates_times.dates.decade_apostrophes_long. """ assert chk.check_decade_apostrophes_long( "Basic smoke phrase without issues.") == [] assert chk.check_decade_apostrophes_long( "It happened in the 1980s.") == [] assert chk.check_decade_apostrophes_long( "It happened in the 1980's.") != [] def test_smoke_check_dash_and_from(self): """Basic smoke test. This for the function dates_times.dates.dash_and_from. """ assert chk.check_dash_and_from( "Basic smoke phrase without issues.") == [] assert chk.check_dash_and_from( "It happened from 2000 to 2005.") == [] assert chk.check_dash_and_from( "It happened from 2000-2005.") != [] def test_smoke_check_month_year_comma(self): """Basic smoke test. This is for the function dates_times.dates.check_month_year_comma. """ assert chk.check_month_year_comma( "Basic smoke phrase without issues.") == [] assert chk.check_month_year_comma( "It happened in August 2008.") == [] assert chk.check_month_year_comma( "It happened in August, 2008.") != [] def test_smoke_check_month_of_year(self): """Basic smoke test. This is for the function dates_times.dates.check_month_of_year. """ assert chk.check_month_of_year( "Basic smoke phrase without issues.") == [] assert chk.check_month_of_year( "It happened in August 2008.") == [] assert chk.check_month_of_year( "It happened in August of 2008.") != [] proselint-0.10.2/tests/test_needless_variants.py0000664000372000037200000000110713331225053022733 0ustar travistravis00000000000000"""Tests for needless_variants.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.needless_variants import misc as chk class TestCheck(Check): """The test class for needless_variants.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for needless_variants.misc.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""It was an extensible telescope.""") proselint-0.10.2/tests/test_lexical_illusions.py0000664000372000037200000000110413331225053022741 0ustar travistravis00000000000000"""Tests for lexical_illusions.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.lexical_illusions import misc as chk class TestCheck(Check): """The test class for lexical_illusions.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for lexical_illusions.misc.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""Paris in the the springtime.""") proselint-0.10.2/tests/test_hyperbole.py0000664000372000037200000000103113331225053021207 0ustar travistravis00000000000000"""Tests for hyperbole.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.hyperbole import misc as chk class TestCheck(Check): """The test class for hyperbole.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for hyperbole.misc.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""So exaggerated!!!""") proselint-0.10.2/tests/test_spelling_em_im_en_in.py0000664000372000037200000000107413331225053023360 0ustar travistravis00000000000000"""Tests for spelling.em_im_en_in check.""" from __future__ import absolute_import from .check import Check from proselint.checks.spelling import em_im_en_in as chk class TestCheck(Check): """The test class for spelling.em_im_en_in.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for spelling.em_im_en_in.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""We shall imbark on a voyage.""") proselint-0.10.2/tests/test_misc_but.py0000664000372000037200000000102613331225053021027 0ustar travistravis00000000000000"""Tests for misc.but check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import but as chk class TestCheck(Check): """The test class for misc.but.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.but.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""But I never start with the word "but".""") proselint-0.10.2/tests/test_misc_scare_quotes.py0000664000372000037200000000106513331225053022735 0ustar travistravis00000000000000"""Tests for misc.scare_quotes check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import scare_quotes as chk class TestCheck(Check): """The test class for misc.scare_quotes.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.scare_quotes.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""What was the 'take-home message'?""") proselint-0.10.2/tests/test_misc_phrasal_adjectives.py0000664000372000037200000000165313331225053024076 0ustar travistravis00000000000000"""Tests for misc.phrasal_adjectives check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import phrasal_adjectives as chk class TestCheck(Check): """The test class for misc.phrasal_adjectives.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.phrasal_adjectives.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""There were across the board discounts.""") def test_smoke_ly(self): """Basic smoke test for misc.phrasal_adjectives.check_ly.""" assert chk.check_ly("""Smoke phrase with nothing flagged.""") == [] assert chk.check_ly("""He ran swiftly-fast.""") assert chk.check_ly("""The not-so-hotly-contested result was fine.""") == [] proselint-0.10.2/tests/illegal-chars.txt0000664000372000037200000000010113331225053021052 0ustar travistravis00000000000000This file contains an illegal character on the next line... don proselint-0.10.2/tests/test_security_credit_card.py0000664000372000037200000000122513331225053023415 0ustar travistravis00000000000000"""Tests for security.credit_card check.""" from __future__ import absolute_import from .check import Check from proselint.checks.security import credit_card as chk class TestCheck(Check): """The test class for security.credit_card.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for security.credit_card. This makes use of a test MasterCard number. """ assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes( """My credit card number is 5555555555554444.""") proselint-0.10.2/tests/test_uncomparables.py0000664000372000037200000000106113331225053022054 0ustar travistravis00000000000000"""Tests for uncomparables.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.uncomparables import misc as chk class TestCheck(Check): """The test class for uncomparables.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for uncomparables.misc.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""The item was more unique.""") proselint-0.10.2/tests/test_spelling_athletes.py0000664000372000037200000000106213331225053022730 0ustar travistravis00000000000000"""Tests for spelling.athletes check.""" from __future__ import absolute_import from .check import Check from proselint.checks.spelling import athletes as chk class TestCheck(Check): """The test class for spelling.athletes.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for spelling.athletes.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""One of the greats: Cal Ripkin.""") proselint-0.10.2/tests/test_dfw_uncomparables.py0000664000372000037200000000135313331225053022720 0ustar travistravis00000000000000"""Test dfw.uncomparables.""" from __future__ import absolute_import from .check import Check from proselint.checks.uncomparables import misc as chk class TestCheck(Check): """The test class for dfw.uncomparables.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_sample_phrases(self): """Find 'very unique'.""" assert not self.passes("""This sentence is very unique.""") def test_linebreaks(self): """Handle linebreaks correctly.""" assert not self.passes("""This sentence is very\nunique.""") def test_constitutional(self): """Don't flag 'more perfect'.""" assert self.passes("""A more perfect union.""") proselint-0.10.2/tests/test_cursing_filth.py0000664000372000037200000000103413331225053022061 0ustar travistravis00000000000000"""Tests for cursing.filth check.""" from __future__ import absolute_import from .check import Check from proselint.checks.cursing import filth as chk class TestCheck(Check): """The test class for cursing.filth.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for cursing.filth.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""Bad shit in this phrase.""") proselint-0.10.2/tests/test_terms_denizen_labels.py0000664000372000037200000000110113331225053023404 0ustar travistravis00000000000000"""Tests for terms.denizen_labels check.""" from __future__ import absolute_import from .check import Check from proselint.checks.terms import denizen_labels as chk class TestCheck(Check): """The test class for terms.denizen_labels.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for terms.denizen_labels.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""He was definitely a Hong Kongite.""") proselint-0.10.2/tests/test_illegal_chars.py0000664000372000037200000000223613331225053022017 0ustar travistravis00000000000000"""Check that the CLI can handle invalid characters.""" import os.path as pth import subprocess def test_invalid_characters(): """Ensure that a file with illegal characters does not break us.""" try: output = "" curr_dir = pth.dirname(pth.abspath(__file__)) test_file = pth.join(curr_dir, "illegal-chars.txt") # We only print out exception text and continue after printing a trace, # so the only way (currently) to test for failure is to look for the # exception text. Refactoring the command line function would let us # write better tests (one day). output = str(subprocess.check_output( ["proselint", test_file], stderr=subprocess.STDOUT )) except subprocess.CalledProcessError as e: # Non-zero return codes are OK, but what did we catch? print("Non-zero return value: will proceed. %s" % e) output += str(e.output) except Exception: assert(not "Unknown Exception Occurred") assert("UnicodeDecodeError" not in output) # Failed to process the file assert("FileNotFoundError" not in output) # Failed to find our test file proselint-0.10.2/tests/test_consistency_check.py0000664000372000037200000000163613331225053022727 0ustar travistravis00000000000000"""Test the consistency_check function from the tools.py module.""" from __future__ import absolute_import from .check import Check from proselint.tools import consistency_check as chk class TestCheck(Check): """The test class for tools.consistency_check.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def setUp(self): """Create some test fixtures.""" self.l = [['colour', 'color']] self.err = 'error message' self.msg = 'inconsistent form of {} vs {}' def test_smoke(self): """Basic smoke test for consistency_check.""" assert chk( "Painting colour on color", self.l, self.err, self.msg) != [] assert chk( "Painting colour on colour", self.l, self.err, self.msg) == [] assert chk( "Painting color on color", self.l, self.err, self.msg) == [] proselint-0.10.2/tests/check.py0000664000372000037200000000336513331225053017250 0ustar travistravis00000000000000"""Check that a check is working.""" from past.builtins import basestring from unittest import TestCase import os import codecs class Check(TestCase): """All tests inherit from Check.""" __test__ = False def setUp(self): """Placeholder for setup procedure.""" pass def tearDown(self): """Placeholder for teardown procedure.""" from proselint.tools import close_cache_shelves close_cache_shelves() @property def this_check(self): """The specific check.""" raise NotImplementedError def passes(self, lst): """Check if the test runs cleanly on the given text.""" if isinstance(lst, basestring): lst = [lst] errors = [] for text in lst: errors.append(self.this_check.check(text)) return len(errors[0]) == 0 def wpe_too_high(self): """Check whether the check is too noisy.""" min_wpe = 50 examples_dir = os.path.join(os.getcwd(), "tests", "corpus") examples = os.listdir(examples_dir) for example in examples: example_path = os.path.join(examples_dir, example) if ".DS_Store" in example_path: break # Compute the number of words per (wpe) error. with codecs.open(example_path, "r", encoding='utf-8') as f: text = f.read() num_errors = len(self.this_check.check(text)) num_words = len(text) try: wpe = 1.0 * num_words / num_errors except ZeroDivisionError: wpe = float('Inf') # Make sure that assert wpe > min_wpe, \ "{} has only {} wpe.".format(example, round(wpe, 2)) proselint-0.10.2/tests/test_sexism.py0000664000372000037200000000107213331225053020533 0ustar travistravis00000000000000"""Tests for sexism.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.sexism import misc as chk class TestCheck(Check): """The test class for sexism.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for sexism.misc.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes( """The legal team had two lawyers and a lady lawyer.""") proselint-0.10.2/tests/test_butterick_symbols.py0000664000372000037200000000313113331225053022765 0ustar travistravis00000000000000"""Test Butterick's symbols.""" from __future__ import absolute_import from .check import Check from proselint.checks.typography import symbols as chk class TestCheck(Check): """The test class for typography.symbols.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_ellipsis(self): """Find ... in a string.""" assert chk.check_ellipsis("""The long and winding road...""") def test_copyright(self): """Find a (c) or (C) in a string.""" assert chk.check_copyright_symbol("""Show me the money! (C)""") assert chk.check_copyright_symbol("""Show me the money! (c)""") def test_trademark(self): """Find a (TM) or (tm) in a string.""" assert chk.check_trademark_symbol("""The Fresh Maker (TM)""") assert chk.check_trademark_symbol("""The Fresh Maker (tm)""") def test_registered_trademark(self): """Find a (r) or (R) in a string.""" assert chk.check_registered_trademark_symbol("""Just Do It (R)""") assert chk.check_registered_trademark_symbol("""Just Do It (r)""") def test_sentence_spacing(self): """Find a sentence followed by three or more spaces.""" assert chk.check_sentence_spacing( """This is a sentence. This is another.""") def test_multiplication(self): """Find an x between two digits.""" assert chk.check_multiplication_symbol( """It is obvious that 2 x 2 = 4.""") def test_curly_quotes(self): # FIXME """Find "" quotes in a string.""" pass proselint-0.10.2/tests/test_terms_animal_adjectives.py0000664000372000037200000000111313331225053024073 0ustar travistravis00000000000000"""Tests for terms.animal_adjectives check.""" from __future__ import absolute_import from .check import Check from proselint.checks.terms import animal_adjectives as chk class TestCheck(Check): """The test class for terms.animal_adjectives.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for terms.animal_adjectives.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""It was some bird-like creature.""") proselint-0.10.2/tests/test_demo.py0000664000372000037200000000015413331225053020147 0ustar travistravis00000000000000"""Run the demo.""" import subprocess subprocess.call(["proselint", "--debug", ">/dev/null"], shell=True) proselint-0.10.2/tests/test_typography_symbols.py0000664000372000037200000000313113331225053023177 0ustar travistravis00000000000000"""Test Butterick's symbols.""" from __future__ import absolute_import from .check import Check from proselint.checks.typography import symbols as chk class TestCheck(Check): """The test class for typography.symbols.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_ellipsis(self): """Find ... in a string.""" assert chk.check_ellipsis("""The long and winding road...""") def test_copyright(self): """Find a (c) or (C) in a string.""" assert chk.check_copyright_symbol("""Show me the money! (C)""") assert chk.check_copyright_symbol("""Show me the money! (c)""") def test_trademark(self): """Find a (TM) or (tm) in a string.""" assert chk.check_trademark_symbol("""The Fresh Maker (TM)""") assert chk.check_trademark_symbol("""The Fresh Maker (tm)""") def test_registered_trademark(self): """Find a (r) or (R) in a string.""" assert chk.check_registered_trademark_symbol("""Just Do It (R)""") assert chk.check_registered_trademark_symbol("""Just Do It (r)""") def test_sentence_spacing(self): """Find a sentence followed by three or more spaces.""" assert chk.check_sentence_spacing( """This is a sentence. This is another.""") def test_multiplication(self): """Find an x between two digits.""" assert chk.check_multiplication_symbol( """It is obvious that 2 x 2 = 4.""") def test_curly_quotes(self): # FIXME """Find "" quotes in a string.""" pass proselint-0.10.2/tests/test_gmeu/0000775000372000037200000000000013331225202017602 5ustar travistravis00000000000000proselint-0.10.2/tests/test_gmeu/test_a_C.py0000664000372000037200000000030313331225053021675 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """Test GMEU entry 'a', part C. This entry is about pronunciation of the word 'a' and is unlikely to be relevant to usage in written language. """ proselint-0.10.2/tests/test_gmeu/test_a_B.py0000664000372000037200000000131013331225053021673 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """Test GMEU entry 'a', part B.""" from proselint.tools import assert_error from nose import SkipTest def test_a_distributive(): """Use a over per in the distributive sense.""" raise SkipTest sentences = [ "An apple per day keeps the doctor away.", "I sleep eight hours per night.", "Their policy allows one golf cart a couple.", "The company donated five books a student.", "Our a-unit cost is less than $1000.", "The $50-a-parent fee seems unreasonably high." ] error_check_name = "misc.a_distributive" for sentence in sentences: yield assert_error, sentence, error_check_name proselint-0.10.2/tests/test_gmeu/test_a_A.py0000664000372000037200000000412513331225053021701 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """Test GMEU entry 'a', part A.""" from proselint.tools import assert_error from nose import SkipTest def test_a_vs_an(): """Use the correct determiner.""" raise SkipTest sentences = [ "Are you an Yankee fan?", "Coffee tastes less sweet in an white mug.", "One of them wore a opalescent vest.", "You're a intelligent guy, often misguided.", "Ezra gave an eulogy.", "What capital of an European country is the farthest north?", "His sole reward was an one-year term as Ambassador to Thailand.", "I will be relying on a roulette wheel and an Ouija board.", "Anyone in an uniform is fair game.", "Grimm started working as a F.B.I. agent in 1995.", "Out of 186 managers participating, 57 had a MBA degree.", "Smith announced that a SEC filing is pending.", "This argument is an historical desecration.", u"The treatment of crime in Britain shows an historic shift away…", "It is, in some ways, an humble form.", "The thief turned out to be an habitual offender from Darlington.", "This stage displays an hallucinatory image that signifies itself.", "He saw an hallucinatory image before passing out.", "A triumphant Adolf Hitler addressed an hysterical crowd.", "Kun pieced together an history of gender-segregated dining in L.A.", "An historian who fled the Nazis and still wants us to read Hitler.", "It is nominally an historical novel.", "It feels good to validate an hypothesis.", "An hereditary title can be passed to a member of the family.", "The Clinton Presidency was an historic era of prosperity.", "There comes to be an habitual pattern between neurons in the brain.", "They had the authority to start an humanitarian intervention.", "She laughed aloud, an hysterical sort of giggled, quickly stifled", ] error_check_name = "misc.a_vs_an" for sentence in sentences: yield assert_error, sentence, error_check_name proselint-0.10.2/tests/test_archaism.py0000664000372000037200000000115413331225053021013 0ustar travistravis00000000000000"""Tests for archaism.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.archaism import misc as chk class TestCheck(Check): """The test class for archaism.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for archaism.misc.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert self.passes("""I want to sleep, and maybe dream.""") assert not self.passes("""I want to sleep, perchance to dream.""") proselint-0.10.2/tests/test_lgbtq_offensive_terms.py0000664000372000037200000000114313331225053023611 0ustar travistravis00000000000000"""Tests for lgbtq.terms check.""" from __future__ import absolute_import from .check import Check from proselint.checks.lgbtq import offensive_terms as chk class TestCheck(Check): """The test class for lgbtq.offensive_terms.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for lgbtq.offensive_terms.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert self.passes("""I once met a gay man.""") assert not self.passes("""I once met a fag.""") proselint-0.10.2/tests/test_misc_pretension.py0000664000372000037200000000106313331225053022424 0ustar travistravis00000000000000"""Tests for misc.pretension check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import pretension as chk class TestCheck(Check): """The test class for misc.pretension.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.pretension.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""We need to reconceptualize the project.""") proselint-0.10.2/tests/test_spelling_misc.py0000664000372000037200000000102513331225053022051 0ustar travistravis00000000000000"""Tests for spelling.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.spelling import misc as chk class TestCheck(Check): """The test class for spelling.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for spelling.misc.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""I like this alot.""") proselint-0.10.2/tests/test_misc_chatspeak.py0000664000372000037200000000103313331225053022176 0ustar travistravis00000000000000"""Tests for misc.chatspeak check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import chatspeak as chk class TestCheck(Check): """The test class for misc.chatspeak.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.chatspeak.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""BRB getting coffee.""") proselint-0.10.2/tests/test_misc_whence.py0000664000372000037200000000103113331225053021502 0ustar travistravis00000000000000"""Tests for misc.whence check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import whence as chk class TestCheck(Check): """The test class for misc.whence.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.whence.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""Go back from whence you came!""") proselint-0.10.2/tests/test_mondegreens.py0000664000372000037200000000114713331225053021534 0ustar travistravis00000000000000"""Tests for mondegreens.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.mondegreens import misc as chk class TestCheck(Check): """The test class for mondegreens.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for mondegreens.misc.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert self.passes("""... and laid him on the green.""") assert not self.passes("""..and Lady Mondegreen.""") proselint-0.10.2/tests/test_annotations.py0000664000372000037200000000114413331225053021560 0ustar travistravis00000000000000"""Tests for annotations.misc check.""" from __future__ import absolute_import from .check import Check from proselint.checks.annotations import misc as chk class TestCheck(Check): """The test class for annotations.misc.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for annotations.misc.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert self.passes("""Add it to the to do list.""") assert not self.passes("""Add it to the TODO list.""") proselint-0.10.2/tests/test_misc_many_a.py0000664000372000037200000000106213331225053021501 0ustar travistravis00000000000000"""Tests for misc.many_a check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import many_a as chk class TestCheck(Check): """The test class for misc.many_a.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.many_a.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes( """There were many a day I thought about it.""") proselint-0.10.2/tests/test_tools.py0000664000372000037200000000202313331225053020360 0ustar travistravis00000000000000"""Test the tools module.""" from __future__ import absolute_import from .check import Check from proselint.tools import lint as lint class TestLint(Check): """The test class for tools.lint.""" __test__ = True def setUp(self): """setUp method creating text fixtures.""" self.text = """But this is a very bad sentence. This is also a no-good sentence. """ self.text_with_no_newline = """A very bad sentence.""" def extract_line_col(self, error): """Extract the line and column number from an error tuple.""" _, _, line, column, _, _, _, _, _ = error return line, column def test_errors_sorted(self): """Test that errors are sorted by line and column number.""" lines_and_cols = [self.extract_line_col(e) for e in lint(self.text)] assert sorted(lines_and_cols) == lines_and_cols def test_on_no_newlines(self): """Test that lint works on text without a terminal newline.""" assert len(lint(self.text_with_no_newline)) == 1 proselint-0.10.2/tests/test_terms_eponymous_adjectives.py0000664000372000037200000000113113331225053024670 0ustar travistravis00000000000000"""Tests for terms.eponymous_adjectives check.""" from __future__ import absolute_import from .check import Check from proselint.checks.terms import eponymous_adjectives as chk class TestCheck(Check): """The test class for terms.eponymous_adjectives.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for terms.eponymous_adjectives.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""The writing wasn't Shakespearian.""") proselint-0.10.2/tests/test_misc_capitalization.py0000664000372000037200000000206513331225053023254 0ustar travistravis00000000000000"""Tests for misc.capitalization check.""" from __future__ import absolute_import from .check import Check from proselint.checks.misc import capitalization as chk class TestCheck(Check): """The test class for misc.capitalization.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for misc.capitalization.check.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""It goes back to the stone age.""") def test_smoke_check_months(self): """Basic smoke test for misc.capitalization.check_months.""" assert chk.check_months("""Smoke phrase with nothing flagged""") == [] assert chk.check_months("""A nice day in june.""") != [] def test_smoke_check_days(self): """Basic smoke test for misc.capitalization.check_days.""" assert chk.check_days("""Smoke phrase with nothing flagged""") == [] assert chk.check_days("""It happened on friday.""") != [] proselint-0.10.2/tests/test_security_password.py0000664000372000037200000000115213331225053023013 0ustar travistravis00000000000000"""Tests for security.password check.""" from __future__ import absolute_import from .check import Check from proselint.checks.security import password as chk class TestCheck(Check): """The test class for security.password.""" __test__ = True @property def this_check(self): """Boilerplate.""" return chk def test_smoke(self): """Basic smoke test for security.password.""" assert self.passes("""Smoke phrase with nothing flagged.""") assert not self.passes("""The password is 123456.""") assert not self.passes("""My password is PASSWORD.""") proselint-0.10.2/MANIFEST.in0000664000372000037200000000014113331225053016202 0ustar travistravis00000000000000include README.md LICENSE.md CHANGELOG.md tests/illegal-chars.txt tests/*.py tests/test_gmeu/*.pyproselint-0.10.2/PKG-INFO0000664000372000037200000003457413331225202015556 0ustar travistravis00000000000000Metadata-Version: 2.1 Name: proselint Version: 0.10.2 Summary: A linter for prose. Home-page: http://github.com/amperser/proselint Author: Amperser Labs Author-email: hello@amperser.com License: BSD Download-URL: http://github.com/amperser/proselint/tarball/0.10.2 Description: proselint logo [![Build Status](https://travis-ci.org/amperser/proselint.svg)](https://travis-ci.org/amperser/proselint) [![Build status](https://ci.appveyor.com/api/projects/status/hfgv05nkjxkg2gcc/branch/master?svg=true)](https://ci.appveyor.com/project/suchow/proselint-knwyf/branch/master) [![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com) [![Code Climate](https://codeclimate.com/repos/5538989ee30ba0793100090f/badges/e10a2fe18a9256d69e2a/gpa.svg)](https://codeclimate.com/repos/5538989ee30ba0793100090f/feed) [![Coverage Status](https://coveralls.io/repos/github/amperser/proselint/badge.svg?branch=master)](https://coveralls.io/github/amperser/proselint?branch=master) [![Dependency Status](https://gemnasium.com/amperser/proselint.svg)](https://gemnasium.com/amperser/proselint) [![License](https://img.shields.io/badge/License-BSD-blue.svg)](https://en.wikipedia.org/wiki/BSD_licenses) 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](https://packaging.python.org/installing/#use-pip-for-installing): ``` 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 ``` ### Plugins for other software `proselint` is available on: - [x] A [demo editor](http://proselint.com/write) - [x] [Sublime Text](https://github.com/amperser/proselint/tree/master/plugins/sublime/SublimeLinter-contrib-proselint) - [x] [Atom Editor](https://github.com/smockle/linter-proselint) (thanks to [Clay Miller](https://github.com/smockle)). - [x] [Emacs via Flycheck](http://www.flycheck.org/). - [x] Vim via [ALE](https://github.com/w0rp/ale) or [Syntastic](https://github.com/vim-syntastic/syntastic) (thanks to @lcd047, @Carreau, and [Daniel M. Capella](https://github.com/polyzen)) - [x] [Phabricator's `arc` CLI](https://github.com/google/arc-proselint) (thanks to [Jeff Verkoeyen](https://github.com/jverkoey)) - [x] [Danger](https://github.com/dbgrandi/danger-prose) (thanks to [David Grandinetti](https://github.com/dbgrandi) and [Orta Therox](https://github.com/orta)) - [x] [Visual Studio Code](https://github.com/ppeszko/vscode-proselint) (thanks to [Patryk Peszko](https://github.com/ppeszko)) - [x] [coala](https://github.com/coala-analyzer/bear-docs/blob/master/docs/ProseLintBear.rst) (thanks to the [coala Development Group](https://github.com/coala-analyzer)) - [x] [IntelliJ](https://github.com/kropp/intellij-proselint) (by [Victor Kropp](https://github.com/kropp)) - [x] [pre-commit](https://pre-commit.com/) (by [Andy Airey](https://github.com/aairey)) ### 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: ```bash ❯ proselint text.md ``` This prints a list of suggestions to stdout, one per line. Each suggestion has the form: ```bash text.md::: ``` For example, ```bash 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: ```javascript { // 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`: ```python import proselint suggestions = proselint.tools.lint("This sentence is very unique") ``` This will return a list of suggestions: ```python [('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 `$XDG_CONFIG_HOME/proselint/config`. If `$XDG_CONFIG_HOME` is not set or empty, `~/.config/proselint/config` will be used. Additionally for compatible reason, the legacy configuration `~/.proselintrc` will be used if `$XDG_CONFIG_HOME/proselint/config` does not exist. ```json { "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](http://proselint.com/contributing/), where we describe how you can help us build `proselint` into the greatest writing tool in the world. - [Issue Tracker](http://github.com/amperser/proselint/issues) - [Source Code](http://github.com/amperser/proselint) ### Support If you run into a problem, please [open an issue](http://github.com/amperser/proselint/issues) 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 [pytest](https://docs.pytest.org/en/latest/) and run the following commands: ```bash pytest ``` and watch the output. Nose is compatible with Python versions 2.7, 3.4, 3.5 and 3.6. 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. Platform: UNKNOWN Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: Implementation :: CPython Description-Content-Type: text/markdown proselint-0.10.2/proselint.egg-info/0000775000372000037200000000000013331225202020155 5ustar travistravis00000000000000proselint-0.10.2/proselint.egg-info/top_level.txt0000664000372000037200000000001213331225202022700 0ustar travistravis00000000000000proselint proselint-0.10.2/proselint.egg-info/not-zip-safe0000664000372000037200000000000113331225202022403 0ustar travistravis00000000000000 proselint-0.10.2/proselint.egg-info/requires.txt0000664000372000037200000000002113331225202022546 0ustar travistravis00000000000000click future six proselint-0.10.2/proselint.egg-info/PKG-INFO0000664000372000037200000003457413331225202021267 0ustar travistravis00000000000000Metadata-Version: 2.1 Name: proselint Version: 0.10.2 Summary: A linter for prose. Home-page: http://github.com/amperser/proselint Author: Amperser Labs Author-email: hello@amperser.com License: BSD Download-URL: http://github.com/amperser/proselint/tarball/0.10.2 Description: proselint logo [![Build Status](https://travis-ci.org/amperser/proselint.svg)](https://travis-ci.org/amperser/proselint) [![Build status](https://ci.appveyor.com/api/projects/status/hfgv05nkjxkg2gcc/branch/master?svg=true)](https://ci.appveyor.com/project/suchow/proselint-knwyf/branch/master) [![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com) [![Code Climate](https://codeclimate.com/repos/5538989ee30ba0793100090f/badges/e10a2fe18a9256d69e2a/gpa.svg)](https://codeclimate.com/repos/5538989ee30ba0793100090f/feed) [![Coverage Status](https://coveralls.io/repos/github/amperser/proselint/badge.svg?branch=master)](https://coveralls.io/github/amperser/proselint?branch=master) [![Dependency Status](https://gemnasium.com/amperser/proselint.svg)](https://gemnasium.com/amperser/proselint) [![License](https://img.shields.io/badge/License-BSD-blue.svg)](https://en.wikipedia.org/wiki/BSD_licenses) 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](https://packaging.python.org/installing/#use-pip-for-installing): ``` 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 ``` ### Plugins for other software `proselint` is available on: - [x] A [demo editor](http://proselint.com/write) - [x] [Sublime Text](https://github.com/amperser/proselint/tree/master/plugins/sublime/SublimeLinter-contrib-proselint) - [x] [Atom Editor](https://github.com/smockle/linter-proselint) (thanks to [Clay Miller](https://github.com/smockle)). - [x] [Emacs via Flycheck](http://www.flycheck.org/). - [x] Vim via [ALE](https://github.com/w0rp/ale) or [Syntastic](https://github.com/vim-syntastic/syntastic) (thanks to @lcd047, @Carreau, and [Daniel M. Capella](https://github.com/polyzen)) - [x] [Phabricator's `arc` CLI](https://github.com/google/arc-proselint) (thanks to [Jeff Verkoeyen](https://github.com/jverkoey)) - [x] [Danger](https://github.com/dbgrandi/danger-prose) (thanks to [David Grandinetti](https://github.com/dbgrandi) and [Orta Therox](https://github.com/orta)) - [x] [Visual Studio Code](https://github.com/ppeszko/vscode-proselint) (thanks to [Patryk Peszko](https://github.com/ppeszko)) - [x] [coala](https://github.com/coala-analyzer/bear-docs/blob/master/docs/ProseLintBear.rst) (thanks to the [coala Development Group](https://github.com/coala-analyzer)) - [x] [IntelliJ](https://github.com/kropp/intellij-proselint) (by [Victor Kropp](https://github.com/kropp)) - [x] [pre-commit](https://pre-commit.com/) (by [Andy Airey](https://github.com/aairey)) ### 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: ```bash ❯ proselint text.md ``` This prints a list of suggestions to stdout, one per line. Each suggestion has the form: ```bash text.md::: ``` For example, ```bash 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: ```javascript { // 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`: ```python import proselint suggestions = proselint.tools.lint("This sentence is very unique") ``` This will return a list of suggestions: ```python [('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 `$XDG_CONFIG_HOME/proselint/config`. If `$XDG_CONFIG_HOME` is not set or empty, `~/.config/proselint/config` will be used. Additionally for compatible reason, the legacy configuration `~/.proselintrc` will be used if `$XDG_CONFIG_HOME/proselint/config` does not exist. ```json { "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](http://proselint.com/contributing/), where we describe how you can help us build `proselint` into the greatest writing tool in the world. - [Issue Tracker](http://github.com/amperser/proselint/issues) - [Source Code](http://github.com/amperser/proselint) ### Support If you run into a problem, please [open an issue](http://github.com/amperser/proselint/issues) 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 [pytest](https://docs.pytest.org/en/latest/) and run the following commands: ```bash pytest ``` and watch the output. Nose is compatible with Python versions 2.7, 3.4, 3.5 and 3.6. 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. Platform: UNKNOWN Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: Implementation :: CPython Description-Content-Type: text/markdown proselint-0.10.2/proselint.egg-info/dependency_links.txt0000664000372000037200000000000113331225202024223 0ustar travistravis00000000000000 proselint-0.10.2/proselint.egg-info/entry_points.txt0000664000372000037200000000010013331225202023442 0ustar travistravis00000000000000[console_scripts] proselint = proselint.command_line:proselint proselint-0.10.2/proselint.egg-info/SOURCES.txt0000664000372000037200000001700713331225202022046 0ustar travistravis00000000000000CHANGELOG.md LICENSE.md MANIFEST.in README.md setup.cfg setup.py proselint/.proselintrc proselint/__init__.py proselint/__main__.py proselint/command_line.py proselint/demo.md proselint/score.py proselint/tools.py proselint/version.py proselint.egg-info/PKG-INFO proselint.egg-info/SOURCES.txt proselint.egg-info/dependency_links.txt proselint.egg-info/entry_points.txt proselint.egg-info/not-zip-safe proselint.egg-info/requires.txt proselint.egg-info/top_level.txt proselint/checks/__init__.py proselint/checks/airlinese/__init__.py proselint/checks/airlinese/misc.py proselint/checks/annotations/__init__.py proselint/checks/annotations/misc.py proselint/checks/archaism/__init__.py proselint/checks/archaism/misc.py proselint/checks/cliches/__init__.py proselint/checks/cliches/hell.py proselint/checks/cliches/misc.py proselint/checks/consistency/__init__.py proselint/checks/consistency/spacing.py proselint/checks/consistency/spelling.py proselint/checks/corporate_speak/__init__.py proselint/checks/corporate_speak/misc.py proselint/checks/cursing/__init__.py proselint/checks/cursing/filth.py proselint/checks/cursing/nfl.py proselint/checks/cursing/nword.py proselint/checks/dates_times/__init__.py proselint/checks/dates_times/am_pm.py proselint/checks/dates_times/dates.py proselint/checks/hedging/__init__.py proselint/checks/hedging/misc.py proselint/checks/hyperbole/__init__.py proselint/checks/hyperbole/misc.py proselint/checks/jargon/__init__.py proselint/checks/jargon/misc.py proselint/checks/lexical_illusions/__init__.py proselint/checks/lexical_illusions/misc.py proselint/checks/lgbtq/__init__.py proselint/checks/lgbtq/offensive_terms.py proselint/checks/lgbtq/terms.py proselint/checks/links/__init__.py proselint/checks/links/broken.py proselint/checks/malapropisms/__init__.py proselint/checks/malapropisms/misc.py proselint/checks/misc/__init__.py proselint/checks/misc/apologizing.py proselint/checks/misc/back_formations.py proselint/checks/misc/bureaucratese.py proselint/checks/misc/but.py proselint/checks/misc/capitalization.py proselint/checks/misc/chatspeak.py proselint/checks/misc/commercialese.py proselint/checks/misc/composition.py proselint/checks/misc/currency.py proselint/checks/misc/debased.py proselint/checks/misc/false_plurals.py proselint/checks/misc/greylist.py proselint/checks/misc/illogic.py proselint/checks/misc/inferior_superior.py proselint/checks/misc/institution_name.py proselint/checks/misc/latin.py proselint/checks/misc/many_a.py proselint/checks/misc/metaconcepts.py proselint/checks/misc/metadiscourse.py proselint/checks/misc/narcissism.py proselint/checks/misc/not_guilty.py proselint/checks/misc/phrasal_adjectives.py proselint/checks/misc/preferred_forms.py proselint/checks/misc/pretension.py proselint/checks/misc/professions.py proselint/checks/misc/punctuation.py proselint/checks/misc/scare_quotes.py proselint/checks/misc/suddenly.py proselint/checks/misc/tense_present.py proselint/checks/misc/usage.py proselint/checks/misc/waxed.py proselint/checks/misc/whence.py proselint/checks/mixed_metaphors/__init__.py proselint/checks/mixed_metaphors/misc.py proselint/checks/mondegreens/__init__.py proselint/checks/mondegreens/misc.py proselint/checks/needless_variants/__init__.py proselint/checks/needless_variants/misc.py proselint/checks/nonwords/__init__.py proselint/checks/nonwords/misc.py proselint/checks/oxymorons/__init__.py proselint/checks/oxymorons/misc.py proselint/checks/psychology/__init__.py proselint/checks/psychology/misc.py proselint/checks/redundancy/__init__.py proselint/checks/redundancy/misc.py proselint/checks/redundancy/ras_syndrome.py proselint/checks/security/__init__.py proselint/checks/security/credit_card.py proselint/checks/security/password.py proselint/checks/sexism/__init__.py proselint/checks/sexism/misc.py proselint/checks/skunked_terms/__init__.py proselint/checks/skunked_terms/misc.py proselint/checks/spelling/__init__.py proselint/checks/spelling/able_atable.py proselint/checks/spelling/able_ible.py proselint/checks/spelling/athletes.py proselint/checks/spelling/em_im_en_in.py proselint/checks/spelling/er_or.py proselint/checks/spelling/in_un.py proselint/checks/spelling/misc.py proselint/checks/terms/__init__.py proselint/checks/terms/animal_adjectives.py proselint/checks/terms/denizen_labels.py proselint/checks/terms/eponymous_adjectives.py proselint/checks/terms/venery.py proselint/checks/typography/__init__.py proselint/checks/typography/diacritical_marks.py proselint/checks/typography/exclamation.py proselint/checks/typography/symbols.py proselint/checks/uncomparables/__init__.py proselint/checks/uncomparables/misc.py proselint/checks/weasel_words/__init__.py proselint/checks/weasel_words/misc.py proselint/checks/weasel_words/very.py tests/__init__.py tests/_test_version.py tests/check.py tests/illegal-chars.txt tests/test_annotations.py tests/test_archaism.py tests/test_butterick_symbols.py tests/test_clear_cache.py tests/test_cliches.py tests/test_consistency_check.py tests/test_consistency_spacing.py tests/test_consistency_spelling.py tests/test_corporate_speak.py tests/test_cursing_filth.py tests/test_cursing_nfl.py tests/test_cursing_nword.py tests/test_dates_times_am_pm.py tests/test_dates_times_dates.py tests/test_demo.py tests/test_dfw_uncomparables.py tests/test_existence_check.py tests/test_exit_codes.py tests/test_garner_dates.py tests/test_hedging.py tests/test_hyperbole.py tests/test_illegal_chars.py tests/test_jargon.py tests/test_leonard.py tests/test_lexical_illusions.py tests/test_lgbtq_offensive_terms.py tests/test_lgbtq_terms.py tests/test_malaproprisms.py tests/test_misc_apologizing.py tests/test_misc_back_formations.py tests/test_misc_bureaucratese.py tests/test_misc_but.py tests/test_misc_capitalization.py tests/test_misc_chatspeak.py tests/test_misc_commercialese.py tests/test_misc_composition.py tests/test_misc_currency.py tests/test_misc_debased.py tests/test_misc_false_plurals.py tests/test_misc_greylist.py tests/test_misc_illogic.py tests/test_misc_inferior_superior.py tests/test_misc_latin.py tests/test_misc_many_a.py tests/test_misc_metaconcepts.py tests/test_misc_metadiscourse.py tests/test_misc_narcissism.py tests/test_misc_not_guilty.py tests/test_misc_phrasal_adjectives.py tests/test_misc_preferred_forms.py tests/test_misc_pretension.py tests/test_misc_professions.py tests/test_misc_punctuation.py tests/test_misc_scare_quotes.py tests/test_misc_suddenly.py tests/test_misc_tense_present.py tests/test_misc_usage.py tests/test_misc_waxed.py tests/test_misc_whence.py tests/test_mixed_metaphors.py tests/test_mondegreens.py tests/test_needless_variants.py tests/test_nonwords.py tests/test_oxymorons.py tests/test_preferred_forms_check.py tests/test_psychology.py tests/test_redundancy_misc.py tests/test_redundancy_ras_syndrome.py tests/test_security_credit_card.py tests/test_security_password.py tests/test_sexism.py tests/test_skunked_terms.py tests/test_spelling_able_atable.py tests/test_spelling_able_ible.py tests/test_spelling_athletes.py tests/test_spelling_em_im_en_in.py tests/test_spelling_er_or.py tests/test_spelling_in_un.py tests/test_spelling_misc.py tests/test_strunk_white_eos.py tests/test_terms_animal_adjectives.py tests/test_terms_denizen_labels.py tests/test_terms_eponymous_adjectives.py tests/test_terms_venery.py tests/test_tools.py tests/test_topic_detector.py tests/test_typography_diacritical_marks.py tests/test_typography_exclamation.py tests/test_typography_symbols.py tests/test_uncomparables.py tests/test_weasel_words_misc.py tests/test_weasel_words_very.py tests/test_gmeu/test_a_A.py tests/test_gmeu/test_a_B.py tests/test_gmeu/test_a_C.pyproselint-0.10.2/LICENSE.md0000664000372000037200000000276413331225053016065 0ustar travistravis00000000000000Copyright © 2014–2015, Jordan Suchow, Michael Pacer, and Lara A. Ross All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.