Git Product home page Git Product logo

writegood-mode's Introduction

Writegood Mode

This is a minor mode to aid in finding common writing problems. Matt Might’s weaselwords scripts inspired this mode.

It highlights text based on a set of weasel-words, passive-voice and duplicate words.

Basic Usage

First, load in the mode.

(add-to-list 'load-path "path/to/writegood-mode")
(require 'writegood-mode)
(global-set-key "\C-cg" 'writegood-mode)

I use the command key above to start the mode when I wish to check my writing.

Alternatively, this package is also available on MELPA. If installed through the package manager, then only the global key customization would be necessary.

Readability tests

There are now two functions to perform Flesch-Kincaid scoring and grade-level estimation. These follow the known algorithms, but may differ from other implementations due to the syllable estimation.

I use these global keys to get to the readability tests:

(global-set-key "\C-c\C-gg" 'writegood-grade-level)
(global-set-key "\C-c\C-ge" 'writegood-reading-ease)

Customization

The user is free to customize three main portions of the mode.

Faces

The three faces used pull from the default warning face and add subtle backgrounds. There is a separate face for each check performed.

  • Weasel words (writegood-weasels-face)
  • Passive voice (writegood-passive-voice-face)
  • Duplicate words (writegood-duplicates-face)

Weasel Words

There is a large list of included weasel words, but you may have your own. See the write-good-weasel-words variable to modify this list.

Additionally, if you require more than a list of words to mark up your content, then there is a custom variable, writegood-weasel-words-additional-regexp that allows a custom regular expression for matching whatever you heart desires (expressed as a regex).

Passive Voice Irregulars

There is also a list of irregular passive voice verbs. These are the verbs that do not end in ‘ed’ to signify past tense. This variable allow the user to modify the list as needed.

Similar to weasel words, the custom variable writegood-passive-voice-irregulars-additional-regexp allows the use of an additional regular expression to highlight passive voice irregulars.

Alternatives

Artbollocks looks to be an alternative mode to this one.

writegood-mode's People

Contributors

bennn avatar bnbeckwith avatar fehrenbach avatar frankshearar avatar nbfalcon avatar reedrelay avatar sten0 avatar zimoun avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

writegood-mode's Issues

Calculate score on the fly

Hi,

Thanks for this mode: it very useful for my writing activities!
I liked the ease score functionality so much that I wanted it on the fly.
Now every time I add a dot to close a sentence, every time I fill the paragraph,
and every time I save the buffer the easy score is calculated for a sentence, paragraph, whole buffer respectively.
If you think that it would be useful for others I can try to generalise this and open a pull request.

I leave my code as reference at the bottom.

Thanks again for this mode!

(defun writegood-fk-parameters (&optional rstart rend)
  "Flesch-Kincaid reading parameters"
  (let* ((start (cond (rstart rstart)
                      ((and transient-mark-mode mark-active) (region-beginning))
                      ('t (point-min))))
         (end   (cond (rend rend)
                      ((and transient-mark-mode mark-active) (region-end))
                      ('t (point-max))))
         (words     (float (writegood-count-words start end)))
         (syllables (float (writegood-count-syllables start end)))
         (sentences (float (writegood-count-sentences start end))))
    (list sentences words syllables)))

(defun writegood-reading-ease-score->comment (score)
  "Rough interpreation of the Flesch-Kincaid Reading ease SCORE.

From Wikipedia URL `https://en.wikipedia.org/wiki/Flesch–Kincaid_readability_tests'."
   (cond
    ((< score 0) "Ouch! (Proust literature)")
    ((and (<= 0 score) (< score 30.0)) "Very difficult (college graduate)")
    ((and (<= 30.0 score) (< score 50.0)) "Difficult (almost college)")
    ((and (<= 50.0 score) (< score 60.0)) "Fairly difficult (10-12th grade)")
    ((and (<= 60.0 score) (< score 70.0)) "Plain English (8-9th grade)")
    ((and (<= 70.0 score) (< score 80.0)) "Fairly easy (7th grade)")
    ((and (<= 80.0 score) (< score 90.0)) "Easy (6th grade)")
    ((<= 90.0 score) "Very easy (5th grade)")))

(defun writegood-calculate-reading-ease (&optional start end)
  "Calculate score of Flesch-Kincaid reading ease test in the region bounded by START and END.

Scores roughly between 0 and 100."
   (let* ((params (writegood-fk-parameters start end))
          (sentences (nth 0 params))
          (words     (nth 1 params))
          (syllables (nth 2 params))
          (score  (- 206.835 (* 1.015 (/ words sentences)) (* 84.6 (/ syllables words)))))
     score))

(defun writegood-reading-ease (&optional start end)
  "Flesch-Kincaid reading ease test in the region bounded by START and END.

Scores roughly between 0 and 100."
   (interactive)
   (let ((score (writegood-calculate-reading-ease start end)))
     (message "Flesch-Kincaid reading ease score: %.2f %s" score
            (writegood-reading-ease-score->comment score))))

(defun writegoodmode-reading-ease-thing-at-point (thing)
  (let* ((bounds (bounds-of-thing-at-point thing))
         (b (car bounds))
         (e (cdr bounds)))
    (if (and
         (not (null b))
         (not (null e))
         ;; this is a guess: when the interval between boundaries is
         ;; huge, the paragraph is too big to be validated.
         (< (- e b) 100000))
        (let ((score (writegood-calculate-reading-ease b e)))
          (message "%s reading ease score: %.2f %s" (symbol-name thing) score
            (writegood-reading-ease-score->comment score))))))

(defun writegoodmode-reading-ease-sentence ()
  (interactive)
  (writegoodmode-reading-ease-thing-at-point 'sentence))

(defun writegoodmode-reading-ease-paragraph ()
  (interactive)
  (writegoodmode-reading-ease-thing-at-point 'paragraph))

(defun writegoodmode-reading-ease-page ()
  (interactive)
  (writegoodmode-reading-ease-thing-at-point 'page))

(defun writegood-after-sentence ()
  "Calculate reading ease after a sentence is completed. Here we
consider the sentence completion the addition of a dot."
  (if (and (string-match-p (regexp-quote "self-insert-command") (symbol-name last-command)) (eq (char-before) 46)) (writegoodmode-reading-ease-sentence)))

(defun writegood-after-paragraph ()
  "Calculate reading ease after a paragraph is completed. Here we
consider the paragraph completion to be the call of a
,*-fill-paragraph command."
  (if (string-match-p (regexp-quote "fill-paragraph") (symbol-name last-command)) (writegoodmode-reading-ease-paragraph)))

(setq text-modes '("text-mode" "org-mode" "latex-mode" "rst-mode" "markdown-mode" "mu4e-compose-mode"))

(defun apply-only-in-text-major-modes (fn)
  (if (and
       ;; only for text modes
       (member (symbol-name major-mode) text-modes)
       ;; not in a org source block
       (null (org-babel-get-src-block-info 'light)))
      (funcall fn)))

(defun writegood-after-sentence-hook () (apply-only-in-text-major-modes 'writegood-after-sentence))
(defun writegood-after-paragraph-hook () (apply-only-in-text-major-modes 'writegood-after-paragraph))
(defun writegood-after-page-hook () (apply-only-in-text-major-modes 'writegoodmode-reading-ease-page))
(add-hook 'post-command-hook 'writegood-after-sentence-hook)
(add-hook 'post-command-hook 'writegood-after-paragraph-hook)
(add-hook 'after-save-hook 'writegood-after-page-hook)

prosolint support

Seems like a perfect match with this mode. It is not heavy weight as well so shouldn't be a huge dependency.

No autoload statement.

Could you add proper autoload statements to writegood-mode?

I think all you need to do is add,

;;;###autoload

before line 212

Duplicate words across headline and body in org-mode

I typically use writegood in org-mode, and have encountered a situation like this:

* Title of a Section on Foo
Foo is good.

Here writegood sees "Foo" as a duplicate word. That in itself might not be a problem, but it messes with the color/face of the whole headline and makes it look like normal text.

I'm not sure if writegood could indicate the duplication in a way that won't mess up the appearance of org-mode headlines, but if not, I think it might be better for writegood to ignore duplication in such specific cases.

Adding writegood-mode to NonGNU ELPA

Would you be interested in having writegood-mode added to NonGNU ELPA, or even GNU ELPA? I would take care of everything, and the package would be updated automatically whenever you release a new version by bumping the version tag, so it wouldn't run into more effort on your end. The advantage is that people can install the package without having to configure third-party archives first.

How can we suggest alternative word usage?

I have added less than into writegood-weasel-words and want to advice using fewer than if less than is detected.

Is it possible to suggest alternative word usage in the mini-buffer?

Add support for multiple languages.

Thanks for creating this mode! I like it a lot and would try to add support for the German language. I'm not too firm with elisp, but from what I've seen I'd only have to supply writegood-passive-voice-irregulars and writegood-weasel-words to fully support another language.

If those two variables would exist in a hash-like data structure, I could supply a pull request that would add German.

Triple dot messes up Flesch–Kincaid's scores

I guess triple-dots end up being counted as multiple sentences.

How does one properly add "..." to writegood-sentence-punctuation? A naive attempt to simply add "..." here breaks writegood-grade-level.

Fails to do check when enabled via add-hook

I have added writegood-mode to a hook for LaTeX-mode:

(add-hook 'LaTeX-mode-hook 'writegood-mode))

When I open a latex file, writegood-mode is enabled; however, it doesn't highlight any of the trouble areas. If I execute writegood-mode, it disables writegood. If I execute again, writegood-mode is enabled and the highlighting works as normal.

Any idea why it wouldn't work when enabled via another mode-hook?

New release?

Would you mind tagging a new version of the package so that our distribution can easily pick up the update and make the newly added features available to our users?

Hook into flyspell?

How would I add a writegood-mode hook into FlySpell, such that when flyspell mode is enabled, writegood-mode also becomes enabled?

oxford commas

I know this might be controversial, as there are basically two opposing sides of that debate, but I would love it if writegood-mode could (optionally) outline oxford commas (as a) mistake. Depending on the config, this would be marked as an error:

foo, bar and baz

or this:

foo, bar, and baz

The former could be matched with this regex:

\([[:alpha:]]+,[[:space:]]+\)+[[:alpha:]]+[[:space:]]+\(and\|or\)[[:space:]][[:alpha:]]+

... according to this answer. The latter would be matched with:

\([[:alpha:]]+,[[:space:]]+\){2,}\(and\|or\)[[:space:]][[:alpha:]]+

Would you be open to such an extension, provided it's a toggle?

Writegood-mode capitalizes latex-pretty-symbols greek characters.

latex-pretty-symbols does the following:
If I type

$\xi$ is a greek letter

it will change it to

$ξ$ is a greek letter

If I then activate writegood-mode the string then becomes

$Ξ$ is a greek letter

and doesn't change back on deactivation.
The dollar signs just mark the inline math mode, the problem persists even if I try this without them.

Thanks in advance for any help.

Implement 'writegood-region'

I would like to combine flyspell-region with writegood-mode, but writegood-mode does not provide a function to check a region of text.

This is what I came up with to work around the limitation:

(defun writegood-region (beginning end)
  "Check style between BEGINNING and END."
  (interactive "r")
  (narrow-to-region beginning end)
  (writegood-mode)
  (widen))

(defun prose-check-region (beginning end)
  "Check spelling and style between BEGINNING and END."
  (interactive "r")
  (when (use-region-p)
    (writegood-region beginning end)
    (flyspell-region beginning end)
    (setq deactivate-mark t)))

The problem is that writegood-mode remains enabled after the function writegood-region returns.

Any ideas?

Cross-posted: https://emacs.stackexchange.com/questions/64981/combine-flyspell-region-withwritegood-mode

Regular expressions query

Can I add regex to Writegood Weasel Words? For example, say I want to find phrases like this:
Beth-Rehob.
Where we have a word followed by a hyphen followed by a capital word?
I tried "-[A-Z]+" and it brought up nothing.
If I type only "-" then it highlights the hyphen.

Meaning of the Reading Ease score ?

Dear,

Thank you for this nice mode.

The Reading Ease score is not straightforward to interpret. Why not add a short comment in the displayed mini-buffer message ? E.g., according to Wikipedia table ?

I propose something in this flavour:

(defun writegood-reading-ease-score->comment (score)
   "Rough meaning of the Flesch-Kincaid reading ease test.                                                                                                         
                                                                                                                                                                   
 From Wikipedia URL `https://en.wikipedia.org/wiki/Flesch–Kincaid_readability_tests'."
   (cond
    ((< score 0) "Ouch! (Proust litterature)")
    ((and (<= 0 score) (< score 30.0)) "Very difficult (college graduate)")
    ((and (<= 30.0 score) (< score 50.0)) "Difficult (almost college)")
    ((and (<= 50.0 score) (< score 60.0)) "Fairly difficult (10-12th grade)")
    ((and (<= 60.0 score) (< score 70.0)) "Plain English (8-9th grade)")
    ((and (<= 70.0 score) (< score 80.0)) "Fairly easy (7th grade)")
    ((and (<= 80.0 score) (< score 90.0)) "Easy (6th grade)")
    ((<= 90.0 score) "Very easy (5th grade)")
   ))
 
 ;;;###autoload                                                                                                                                                    
 (defun writegood-reading-ease (&optional start end)
   "Flesch-Kincaid reading ease test. Scores roughly between 0 and 100."
    (interactive)
    (let* ((params (writegood-fk-parameters start end))
           (sentences (nth 0 params))
           (words     (nth 1 params))
           (syllables (nth 2 params))
           (score  (- 206.835 (* 1.015 (/ words sentences)) (* 84.6 (/ syllables words)))))
      (message "Flesch-Kincaid reading ease score: %.2f. %s" score
               (writegood-reading-ease-score->comment score)))) 

All the best

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.