]> git.bundesbrandschatzamt.de Git - emacsconfig.git/commitdiff
added art bollocks mode for better writing.
authorAndreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
Sun, 28 Sep 2014 20:54:30 +0000 (22:54 +0200)
committerAndreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
Sun, 28 Sep 2014 20:54:30 +0000 (22:54 +0200)
Signed-off-by: Andreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
artbollocks-mode.el [new file with mode: 0644]
bba.org

diff --git a/artbollocks-mode.el b/artbollocks-mode.el
new file mode 100644 (file)
index 0000000..0f0943b
--- /dev/null
@@ -0,0 +1,356 @@
+;;; artbollocks-mode.el --- A minor mode to guide art writers.
+;;
+;; Copyright (c) 2011,2012 Rob Myers <robNOSPAMrobmyers.org>
+;; Minor changes (c) 2012 Sacha Chua <sachaNOSPAMsachachua.com>
+;;
+;; Based on fic-mode.el
+;; Copyright (C) 2010, Trey Jackson <bigfaceworm(at)gmail(dot)com>
+;;
+;; Non-artbollocks words from: http://matt.might.net/articles/
+;;
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU Affero General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+;;
+;; 2012-06-16: Renamed functions and variables to avoid collisions.
+;; Incompatible changes, so please review your configuration. - Sacha
+;; Chua
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Extra words thanks to:
+;; Brian van den Broek (contextuality, dialetic, problematize)
+;; Isabel Brison (alterity, mise en abyme)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Commentary:
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Usage
+;;
+;; To use, save artbollocks-mode.el to a directory in your load-path.
+;;
+;; (require 'artbollocks-mode)
+;; (add-hook 'text-mode-hook 'artbollocks-mode)
+;;
+;; or
+;;
+;; M-x artbollocks-mode
+;;
+;; NOTE: If you manually turn on artbollocks-mode,
+;; you you might need to force re-fontification initially:
+;;
+;;   M-x font-lock-fontify-buffer
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Code:
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Customization
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Enable features individually
+
+(defcustom artbollocks-lexical-illusions t
+  "Whether to check for lexical illusions"
+  :type '(boolean)
+  :group 'artbollocks-mode)
+
+(defcustom artbollocks-passive-voice t
+  "Whether to check for passive voice"
+  :type '(boolean)
+  :group 'artbollocks-mode)
+
+(defcustom artbollocks-weasel-words t
+  "Whether to check for weasel words"
+  :type '(boolean)
+  :group 'artbollocks-mode)
+
+(defcustom artbollocks-jargon t
+  "Whether to check for artbollocks jargon"
+  :type '(boolean)
+  :group 'artbollocks-mode)
+
+;; Lexical illusion face
+
+(defcustom artbollocks-lexical-illusions-foreground-color "black"
+  "Lexical illusions face foreground colour"
+  :group 'artbollocks-mode)
+
+(defcustom artbollocks-lexical-illusions-background-color "magenta"
+  "Lexical illusions face background color"
+  :group 'artbollocks-mode)
+
+(defcustom artbollocks-font-lock-lexical-illusions-face 'font-lock-lexical-illusions-face
+  "The face for lexical illusions in artbollocks mode"
+  :group 'artbollocks-mode)
+
+(make-face 'artbollocks-font-lock-lexical-illusions-face)
+(modify-face 'artbollocks-font-lock-lexical-illusions-face
+            artbollocks-lexical-illusions-foreground-color
+             artbollocks-lexical-illusions-background-color
+            nil t nil t nil nil)
+
+;; Passive voice face
+
+(defcustom artbollocks-passive-voice-foreground-color "Gray"
+  "Passive voice face foreground colour"
+  :group 'artbollocks-mode)
+
+(defcustom artbollocks-passive-voice-background-color "White"
+  "Passive voice face background color"
+  :group 'artbollocks-mode)
+
+(defcustom artbollocks-font-lock-passive-voice-face 'font-lock-passive-voice-face
+  "The face for passive voice words in artbollocks mode"
+  :group 'artbollocks-mode)
+
+(make-face 'artbollocks-font-lock-passive-voice-face)
+(modify-face 'artbollocks-font-lock-passive-voice-face
+             artbollocks-passive-voice-foreground-color
+             artbollocks-passive-voice-background-color nil t nil t nil nil)
+
+;; Weasel words face
+
+(defcustom artbollocks-weasel-words-foreground-color "Brown"
+  "Weasel words face foreground colour"
+  :group 'artbollocks-mode)
+
+(defcustom artbollocks-weasel-words-background-color "White"
+  "Weasel words face background color"
+  :group 'artbollocks-mode)
+
+(defcustom artbollocks-font-lock-weasel-words-face 'artbollocks-font-lock-weasel-words-face
+  "The face for weasel-words words in artbollocks mode"
+  :group 'artbollocks-mode)
+
+(make-face 'artbollocks-font-lock-weasel-words-face)
+(modify-face 'artbollocks-font-lock-weasel-words-face
+             artbollocks-weasel-words-foreground-color
+             artbollocks-weasel-words-background-color nil t nil t nil nil)
+
+;; Artbollocks face
+
+(defcustom artbollocks-foreground-color "Purple"
+  "Font foreground colour"
+  :group 'artbollocks-mode)
+
+(defcustom artbollocks-background-color "White"
+  "Font background color"
+  :group 'artbollocks-mode)
+
+(defcustom artbollocks-font-lock-artbollocks-face 'font-lock-artbollocks-face
+  "The face for artbollocks words in artbollocks mode"
+  :group 'artbollocks-mode)
+
+(make-face 'artbollocks-font-lock-artbollocks-face)
+(modify-face 'artbollocks-font-lock-artbollocks-face artbollocks-foreground-color
+             artbollocks-background-color nil t nil t nil nil)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Lexical illusions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defconst artbollocks-lexical-illusions-regex "\\b\\(\\w+\\)\\W+\\(\\1\\)\\b")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Passive voice
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defconst artbollocks-passive-voice-regex "\\b\\(am\\|are\\|were\\|being\\|is\\|been\\|was\\|be\\)\\s-+\\(\\w+ed\\|awoken\\|been\\|born\\|beat\\|become\\|begun\\|bent\\|beset\\|bet\\|bid\\|bidden\\|bound\\|bitten\\|bled\\|blown\\|broken\\|bred\\|brought\\|broadcast\\|built\\|burnt\\|bu|swollen\\|swum\\|swung\\|taken\\|taught\\|torn\\|told\\|thought\\|thrived\\|thrown\\|thrust\\|trodden\\|understood\\|upheld\\|upset\\|woken\\|worn\\|woven\\|wed\\|wept\\|wound\\|won\\|withheld\\|withstood\\|wrung\\|written\\)\\b")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Weasel words
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defconst artbollocks-weasel-words-regex "\\b\\(many\\|various\\|very\\|fairly\\|several\\|extremely\\|exceedingly\\|quite\\|remarkably\\|few\\|surprisingly\\|mostly\\|largely\\|huge\\|tiny\\|\\(\\(are\\|is\\) a number\\)\\|excellent\\|interestingly\\|significantly\\|substantially\\|clearly\\|vast\\|relatively\\|completely\\)\\b")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Artbollocks
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defconst artbollocks-jargon-regex "\\b\\(a priori\\|ad hoc\\|affirmation\\|affirm\\|affirms\\|alterity\\|altermodern\\|aporia\\|aporetic\\|appropriates\\|appropriation\\|archetypal\\|archetypical\\|archetype\\|archetypes\\|autonomous\\|autonomy\\|baudrillardian\\|baudrillarian\\|commodification\\|committed\\|commitment\\|commonalities\\|contemporaneity\\|context\\|contexts\\|contextual\\|contextualise\\|contextualises\\|contextualisation\\|contextialize\\|contextializes\\|contextualization\\|contextuality\\|convention\\|conventional\\|conventions\\|coterminous\\|critique\\|cunning\\|cunningly\\|death of the author\\|debunk\\|debunked\\|debunking\\|debunks\\|deconstruct\\|deconks\\|wry\\|wryly\\|zizekian\\|zižekian\\)\\b")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Highlighting
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun artbollocks-search-for-keyword (regex limit)
+  "Match REGEX in buffer until LIMIT."
+  (let (match-data-to-set
+       found)
+    (save-match-data
+      (while (and (null match-data-to-set)
+                 (re-search-forward regex limit t))
+           (setq match-data-to-set (match-data))))
+    (when match-data-to-set
+      (set-match-data match-data-to-set)
+      (goto-char (match-end 0))
+      t)))
+
+(defun artbollocks-lexical-illusions-search-for-keyword (limit)
+  (artbollocks-search-for-keyword artbollocks-lexical-illusions-regex limit))
+
+(defun artbollocks-passive-voice-search-for-keyword (limit)
+  (artbollocks-search-for-keyword artbollocks-passive-voice-regex limit))
+
+(defun artbollocks-weasel-words-search-for-keyword (limit)
+  (artbollocks-search-for-keyword artbollocks-weasel-words-regex limit))
+
+(defun artbollocks-search-for-jargon (limit)
+  (artbollocks-search-for-keyword artbollocks-jargon-regex limit))
+
+(defconst artbollocks-lexicalkwlist
+  '((artbollocks-lexical-illusions-search-for-keyword
+     (2 'artbollocks-font-lock-lexical-illusions-face t))))
+
+(defconst artbollocks-passivekwlist
+  '((artbollocks-passive-voice-search-for-keyword
+     (0 'artbollocks-font-lock-passive-voice-face t))))
+
+(defconst artbollocks-weaselkwlist
+  '((artbollocks-weasel-words-search-for-keyword
+     (0 'artbollocks-font-lock-weasel-words-face t))))
+
+(defconst artbollocks-kwlist
+  '((artbollocks-search-for-jargon
+     (0 'artbollocks-font-lock-artbollocks-face t))))
+
+(defun artbollocks-add-keywords ()
+  (when artbollocks-lexical-illusions
+    (font-lock-add-keywords nil artbollocks-lexicalkwlist))
+  (when artbollocks-passive-voice
+    (font-lock-add-keywords nil artbollocks-passivekwlist))
+  (when artbollocks-weasel-words
+    (font-lock-add-keywords nil artbollocks-weaselkwlist))
+  (when artbollocks-jargon
+    (font-lock-add-keywords nil artbollocks-kwlist)))
+
+(defun artbollocks-remove-keywords ()
+  (font-lock-remove-keywords nil artbollocks-lexicalkwlist)
+  (font-lock-remove-keywords nil artbollocks-passivekwlist)
+  (font-lock-remove-keywords nil artbollocks-weaselkwlist)
+  (font-lock-remove-keywords nil artbollocks-kwlist))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Utility macros
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defmacro interactive-optional-region ()
+  "Flexible variation of (interactive \"r\").
+Bind START and END parameters to either a selected region or the
+entire buffer, subject to narrowing."
+  `(interactive
+    (if (use-region-p)
+        (list (region-beginning) (region-end))
+      (list (point-min) (point-max)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Text metrics
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun artbollocks-count-letters (&optional start end)
+  (how-many "\\w" (or start (point-min)) (or end (point-max))))
+
+(defun artbollocks-count-syllables (&optional start end)
+  ;; Naively count vowel runs as syllable markers
+  (how-many "[aeiouy]+" (or start (point-min)) (or end (point-max))))
+
+(defun artbollocks-count-words (&optional start end)
+  "Count the number of words between START and END."
+  (interactive-optional-region)
+  (let* ((s (or start (point-min)))
+         (e (or end (point-max)))
+         (result
+          (if (fboundp 'count-words)
+              (count-words s e)
+            (how-many "\\w+" s e))))
+    (if (called-interactively-p 'any)
+        (message "Word count: %s" result))
+    result))
+
+(defun artbollocks-count-sentences (&optional start end)
+  "Count the number of words between START and END."
+  (interactive-optional-region)
+  (let* ((s (or start (point-min)))
+         (e (or end (point-max)))
+         (result
+          (how-many "\\w[!?.]" s e)))
+    (if (called-interactively-p 'any)
+        (message "Sentence count: %s" result))
+    result))
+
+;; FIXME: Avoid divide by zero where document is empty or small
+
+(defun artbollocks-automated-readability-index (&optional start end)
+  (let ((words (float (artbollocks-count-words start end))))
+    (- (+ (* 4.71 (/ (artbollocks-count-letters start end) words))
+         (* 0.5 (/ words (artbollocks-count-sentences start end))))
+       21.43)))
+
+(defun artbollocks-flesch-reading-ease (&optional start end)
+  (let ((words (float (artbollocks-count-words start end))))
+    (- 206.834
+       (* 1.015 (/ words (artbollocks-count-sentences start end)))
+       (* 84.6 (/ (artbollocks-count-syllables start end) words)))))
+
+(defun artbollocks-flesch-kinkaid-grade-level (&optional start end)
+  (let ((words (float (artbollocks-count-words start end))))
+    (- (+ (* 11.8 (/ (artbollocks-count-syllables start end) words))
+         (* 0.39 (/ words (artbollocks-count-sentences start end))))
+       15.59)))
+
+(defalias 'artbollocks-word-count 'artbollocks-count-words)
+(defalias 'artbollocks-sentence-count 'artbollocks-count-sentences)
+
+(defun artbollocks-readability-index (&optional start end)
+  "Determine the automated readability index between START and END."
+  (interactive-optional-region)
+  (message "Readability index: %s" (artbollocks-automated-readability-index start end)))
+
+(defun artbollocks-reading-ease (&optional start end)
+  "Determine the Flesch reading ease between START and END."
+  (interactive-optional-region)
+  (message "Reading ease: %s" (artbollocks-flesch-reading-ease start end)))
+
+(defun artbollocks-grade-level (&optional start end)
+  "Determine the Flesch-Kinkaid grade level between START and END."
+  (interactive-optional-region)
+  (message "Grade level: %s" (artbollocks-flesch-kinkaid-grade-level start end)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; The mode
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defconst artbollocks-mode-keymap (make-keymap))
+
+(define-key artbollocks-mode-keymap (kbd "C-c [") 'artbollocks-word-count)
+(define-key artbollocks-mode-keymap (kbd "C-c ]") 'artbollocks-sentence-count)
+(define-key artbollocks-mode-keymap (kbd "C-c \\") 'artbollocks-readability-index)
+(define-key artbollocks-mode-keymap (kbd "C-c /") 'artbollocks-reading-ease)
+(define-key artbollocks-mode-keymap (kbd "C-c =") 'artbollocks-grade-level)
+
+;;;###autoload
+(define-minor-mode artbollocks-mode "Highlight passive voice, weasel words and artbollocks jargon in text, and provide useful text metrics"
+  :lighter " AB"
+  :keymap artbollocks-mode-keymap
+  :group 'artbollocks-mode
+  (if artbollocks-mode
+      (artbollocks-add-keywords)
+    (artbollocks-remove-keywords)))
+
+(provide 'artbollocks-mode)
+
+;; TODO
+;; Toggle adding word/sentence count to status bar
+;; Pluralization
+;; Incorporate diction commands if available (and advise on installation if not)
+;; Split general writing back out
diff --git a/bba.org b/bba.org
index 8e417463a5d8b75a2bf74a23d21674ca91a2d9d8..d2609441a732632b435446e0abfae0e1dfdf64b8 100644 (file)
--- a/bba.org
+++ b/bba.org
@@ -823,6 +823,49 @@ from environment variable http_proxy
 
 #+END_SRC
 
+*** Art Bollocks Mode
+    [2014-09-28 Sun 22:33]
+
+Keeps track of your writing.
+Includes [[http://en.wikipedia.org/wiki/Flesch%E2%80%93Kincaid_readability_tests#Flesch_Reading_Ease][Flesch Reading Ease]] and [[http://en.wikipedia.org/wiki/Flesch–Kincaid_readability_test#Flesch.E2.80.93Kincaid_Grade_Level][Flesch Grade Level]].
+With modifications by [[http://sachachua.com/blog/2011/12/emacs-artbollocks-mode-el-and-writing-more-clearly/][Sacha Chua]].
+
+#+BEGIN_SRC emacs-lisp
+(require 'artbollocks-mode)
+;; Avoid these phrases
+(setq weasel-words-regex
+      (concat "\\b" (regexp-opt
+                     '("one of the"
+                       "should"
+                       "just"
+                       "sort of"
+                       "a lot"
+                       "probably"
+                       "maybe"
+                       "perhaps"
+                       "I think"
+                       "really"
+                       "pretty"
+                       "maybe"
+                       "nice"
+                       "action"
+                       "utilize"
+                       "leverage") t) "\\b"))
+;; Fix a bug in the regular expression to catch repeated words
+(setq lexical-illusions-regex "\\b\\(\\w+\\)\\W+\\(\\1\\)\\b")
+;; Don't show the art critic words, or at least until I figure
+;; out my own jargon
+(setq artbollocks nil)
+;; Make sure keywords are case-insensitive
+(defadvice search-for-keyword (around sacha activate)
+  "Match in a case-insensitive way."
+  (let ((case-fold-search t))
+    ad-do-it))
+
+(add-hook 'text-mode-hook 'artbollocks-mode)
+(add-hook 'org-mode-hook  'artbollocks-mode)
+#+END_SRC
+
 *** window management
     [2014-09-24 Wed 13:03]