writegood-mode
writegood-mode copied to clipboard
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)
This is great!
I am using this code, to good effect. A pull request would be useful for others. Thoughts @bnbeckwith ?
@ag91 @robstewart57 Feel free to make a pull request. We can review and add in the on-the-fly functionality.
Great to hear you like this feature :) I can open a pull request as is and then refine it with your feedback.
On Tue 04 Dec 2018 at 15:31, Benjamin Beckwith [email protected] wrote:
@ag91 @robstewart57 Feel free to make a pull request. We can review and add in the on-the-fly functionality.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.