For a while, I've been using sentence-end-double-space: nil. Now I want to get back into the habit of using two spaces to separate sentences. It is the convention for GNU documentation, and it actually makes sense: That way periods after abbreviations can semantically be differentiated from periods at the end of a sentence. Still, when typing, I forget to write the double space.

Is there a mode that helps me highlight my omissions?

Of course, it would also highlight a single space after an abbreviation, but that's fine.

Note that if sentence-end-double-space: nil has been set for the current buffer, then single spaces should not be highlighted.

  • 1
    flycheck-mode does that in elisp doc-strings. Otherwise you can use highlight-regexp with regular expression \. [^[:space:]]. You can even put (highlight-regexp "\\. [^[:space:]]") into the hook of the major mode you use for your documents. – Tobias Mar 17 at 14:36
  • 1
    An enhancement to add this to whitespace-style might be useful, but it would need to be limited to relevant modes, such as text-mode. Maybe a separate whitespace-mode option would be appropriate, to allow whitespace-style to continue to specify more general behavior. If you want to request such an enhancement, use M-x report-emacs-bug. – Drew Mar 17 at 17:02
  • @Tobias: Please consider posting your comment as an answer. – Drew Mar 17 at 17:02
  • @Drew I will do that eventually if nobody else comes up with a better answer. But I will wait for two or three days. Giving an answer that does not exactly fit what the OP wants is sometimes worse than giving no answer since the question does no longer draw as much attention as one without any answers. I put the question on my favorites and a remainder into my calendar (which is BTW an org-mode thing;-). – Tobias Mar 17 at 20:06
  • @Tobias: Yes, sounds good. Thx. – Drew Mar 17 at 20:17

In my comment I suggested to use highlight-regexp. But meanwhile I discovered that that method does not keep the highlighting correctly updated (it actually should).

So I wrote up a minor mode hlds-mode that does the job. I assume that with this minor mode the variable sentence-end-double-space becomes obsolete.

You just only hook the minor mode into those major modes where you want the highlighting and you can even switch on or off the minor mode with M-x hlds-mode if you decide late that you do like or not like the highlighting for that specific buffer.

(defface hlds
  '((((class color) (background dark))
     :background "grey" :foreground "darkgray")
    (((class color) (background light))
     :background "yellow"  :foreground "lightgray")
    (t :inverse-video t))
  "Face used to mark missing sentence separating double spaces."
  :group 'hlds)

(defvar hlds-re "\\.\\( \\)[^[:space:]]"
  "Regular expression for marking missing double spaces as sentence separators.")

(defun hlds-clear (start end)
  "Clear hlds fontification in region from START to END."
    (cl-loop for int being the intervals property 'face from start to end
         if (eq (get-text-property (car int) 'face) 'hlds)
         do (remove-text-properties (car int) (cdr int) '(face hdls)))))

(defun hlds-jitlock-handler (start end)
  "Mark double spaces in region from START to END."
     (hlds-clear start end)
     (goto-char (max (- start 2) 1))
     (when (< end (point-max))
       (cl-incf end))
     (while (re-search-forward hlds-re end t)
       (put-text-property (match-beginning 1) (match-end 1) 'face 'hlds)))))

(defvar-local hlds-font-lock-keywords nil
  "Additional `font-lock-keywors' entries for hdls-mode.")

(define-minor-mode hlds-mode
  "Highlight missing double-spaces that should separate sentences."
  " ds"
  (if hlds-mode
      (if font-lock-mode
         (setq hlds-font-lock-keywords `((,hlds-re 1 'hlds))))
    (unless jit-lock-mode (jit-lock-mode t))
    (jit-lock-register #'hlds-jitlock-handler)
    (jit-lock-fontify-now (point-min) (point-max)))
    (when font-lock-mode
      (font-lock-remove-keywords nil hlds-font-lock-keywords)
    (font-lock-flush (point-min) (point-max))))
    (when jit-lock-mode
    (hlds-clear (point-min) (point-max)))
      (jit-lock-unregister #'hlds-jitlock-handler))))

For obtaining the effect that the file-local variable sentence-end-double-space controls the activation of hlds-mode you can define a corresponding globalized mode. The TURN-ON function hlds-turn-on turns on hlds-mode if the automagically selected major mode for the file buffer is registered in sentence-end-double-space. If you annihilate the value of sentence-end-double-space file-locally hlds-mode is not switched on in the corresponding file buffer.

(defcustom hlds-major-mode-list '(text-mode fundamental-mode)
  "Major modes with `hlds-mode' turned on by default."
  :type '(repeat :tag "Major modes" symbol)
  :group 'hlds)

(defun hlds-turn-on ()
  "Turn on `hlds-mode' in the current buffer."
  (when (and (apply #'derived-mode-p hlds-major-mode-list)

(define-globalized-minor-mode global-hlds-mode hlds-mode hlds-turn-on)

(global-hlds-mode) ;; Just turn the global mode on.

Tested with emacs -Q with code in *scratch* buffer. One file with file-local setting sentence-end-double-space: nil and one without.

Emacs-Version: GNU Emacs 26.1 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.22.30) of 2018-05-29

  • Thanks. I'll look into that! Respect for sentence-end-double-space: nil is still however a requirement. I have thousands of text-mode files, some with, some without sentence-end-double-space: nil. – feklee Mar 20 at 14:23
  • @feklee Do you use sentence-end-double-space as a file-local variable? Okay then this is maybe a control flag for a globalized minor mode. – Tobias Mar 20 at 14:24
  • Yes, for example: Local Variables: mode: text fill-column: 80 sentence-end-double-space: nil coding: utf-8 End: Local IspellDict: american – feklee Mar 20 at 14:26
  • @feklee I added how you can define a globalized minor mode that is controlled by sentence-end-double-space: nil. – Tobias Mar 20 at 15:18
  • @feklee Okay I just got the meaning of sentence-end-double-space. I will correct that. – Tobias Mar 21 at 8:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.