2

I'm trying to get Emacs to insert a line break at the end of each sentence as I type. (Why? Makes for easier version control of tex files.)

Looking around I found a few places with some suggestions for how to do something similar.

  • This question's answers are mostly suggestions for how to take a document and insert line breaks after each sentence after the fact.
  • This question is asking for a slightly different feature, viz. having Emacs insert two spaces after each sentence.

In an answer to the second question, abo-abo suggests something like this:

(defun electric-space ()
  (interactive)
  (if (looking-back "\\w\\.")
      (insert " "))
  (self-insert-command 1))

(defvar electric-space-on-p nil)

(defun toggle-electric-space ()
  (interactive)
  (global-set-key
   " "
   (if (setq electric-space-on-p
             (not electric-space-on-p))
       'electric-space
     'self-insert-command)))

A small change to this almost allows me to do what I want: replace insert " " with insert "%\n". One downside of this is that the point always ends up on the second column of the following line. Thus, this is what results if I call toggle-electric-space:

Hello world. %
 This is another line.

Is there an obvious way around this?

Another problem with this approach is that there are cases where . does not come at the end of a sentence (though that's easy to fix by writing, e.g. p.~23 instead of p. 23, which is good practice anyway) as well as cases where a sentence ends with something other than a period (?, !, .), etc.).

Now, it seems to me that these problems should be easy to get around in Emacs, since we have something like forward-sentence around, which is smart enough as far as I can tell to recognize that (This sentence.) ends after the closing parenthesis. But I don't know how to make use of forward-sentence in combination with the definition of electric-space above.

This package manages to do something similar to what I want. The difference is that it makes . electric, so it requires explicitly listing all the possible exceptions, i.e. all cases where a period does not end a new line. And in order to allow for sentences that do not end with a period, the package makes ? and ! electric, but I see no easy way of allowing for .) and ?), etc., to be recognized as ending sentences.

I suppose adding a condition like if (looking-back ".") in making the closing parenthesis electric might work... I'll need to study that package more careful and see how I could modify it to suit my purposes. But being effectively a lisp illiterate, I'd appreciate any pointers you may have.

Update

The way to implement abo-abo's suggestion should instead be this:

(defun electric-space () ; Trying to get Emacs to do semantic linefeeds
  (interactive)
  (if (looking-back (sentence-end))
      (insert " %\n")
       (self-insert-command 1))
       )

(defvar electric-space-on-p nil)

(defun toggle-electric-space ()
  (interactive)
  (global-set-key
   " "
   (if (setq electric-space-on-p
             (not electric-space-on-p))
       'electric-space
     'self-insert-command)))

I don't know if there's a more elegant way to do this, but for now it seems to work.

6
  • Docstring of function sentence-end: The default value specifies that in order to be recognized as the end of a sentence, the ending period, question mark, or exclamation point must be followed by two spaces, with perhaps some closing delimiters in between. – JeanPierre Nov 15 '19 at 18:29
  • But this can be overridden, I believe, setting sentence-end-double-space to nil, no? – apc Nov 15 '19 at 18:30
  • It seems, yes. Something like (looking-back (sentence-end)) should tell if point it at end of sentence. However, it seems to return t as soon as last char is a .. – JeanPierre Nov 15 '19 at 18:44
  • Instead of electric, you could add to post-self-insert-hook a function that tests if point is at end of sentence and inserts a newline if so. – JeanPierre Nov 15 '19 at 18:50
  • It seems you have found a working solution, so post it as an answer and accept it ;) – Xerus Apr 8 at 7:15
1

(Posting the 'update' to my question here as an answer.)

The way to implement abo-abo's suggestion should instead be this:

(defun electric-space () ; Trying to get Emacs to do semantic linefeeds
  (interactive)
  (if (looking-back (sentence-end))
      (insert " %\n")
       (self-insert-command 1))
       )

(defvar electric-space-on-p nil)

(defun toggle-electric-space ()
  (interactive)
  (global-set-key
   " "
   (if (setq electric-space-on-p
             (not electric-space-on-p))
       'electric-space
     'self-insert-command)))

I don't know if there's a more elegant way to do this, but for now it seems to work.

That said, since asking this question, the package twauctex has changed and now uses and makes SPC electric rather than .. I've been happily using this package for a while now and highly recommend it to other auctex users.

2
  • 1
    that function should work in any mode though, right? On the other hand the plugin is only for auctex - so I could use the function in org mode as well. – Xerus Apr 9 at 9:30
  • I don't see why not! – apc Apr 9 at 19:12

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.