Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calculate score on the fly #25

Open
ag91 opened this issue Sep 10, 2018 · 3 comments
Open

Calculate score on the fly #25

ag91 opened this issue Sep 10, 2018 · 3 comments

Comments

@ag91
Copy link

ag91 commented Sep 10, 2018

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)
@robstewart57
Copy link

This is great!

I am using this code, to good effect. A pull request would be useful for others. Thoughts @bnbeckwith ?

@bnbeckwith
Copy link
Owner

@ag91 @robstewart57 Feel free to make a pull request. We can review and add in the on-the-fly functionality.

@ag91
Copy link
Author

ag91 commented Dec 4, 2018 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants