3

Suppose I have a sentence:

Two three four. 

Suppose I put the point on the "T" in "Two" and enter the text oneSPC. Auto-capitalize-mode will recognize that the point is at the beginning of a line or sentence, and will automatically capitalize the "O" in "One."

Current output:

One Two three four.  

But since "Two" is no longer the beginning of the sentence, can I get auto-capitalize-mode to automatically downcase the next word in the sentence if there is one?

Desired output:

One two three four.  

In other words, how can I instruct auto-capitalize-mode to downcase the next word whenever it auto-capitalizes a word if there is another word after the point before a line break or period?

2

In your specific example you can hit M-l to down-case the next word.

A general solution would involve some code: you'd want a custom function to run after auto-capitalize and call downcase-word. You also want to make sure the next word is part of the same sentence first. Something like:

(defun downcase-next-word-in-sentence ()
  (interactive)
  "Downcase the next word after point, unless at the end of a sentence or line."
  (unless (looking-at (sentence-end)) 
    (downcase-word 1)))

You can probably advise auto-capitalize to call this after it executes.

Update

Using 'after' advice does not seem to work here. In fact, once I add any advice to auto-capitalize it seems to stop working altogether. Not sure why that is -- perhaps someone else can comment.

The other limitation with this approach is that it is blindly downcasing the next word. After looking at the source of auto-capitalize I see it is doing smarter things like checking for words that are always supposed to be capitalized ("I"), etc.

  • Agreed that it's not ideal to blindly downcase the next word. At the very least it would be great to have an exception for the word "I." A more intelligent function could also make exceptions for any capitalized proper nouns listed in flyspell global dictionaries ("Paris") and user local dictionaries ("Daenerys"), but that would be way more complicated. So just an exception for "I" is probably the place to start. – incandescentman Jun 26 '15 at 17:21
  • Not sure if any code from this would help. emacs.stackexchange.com/questions/10632/… Obviously I don't want to globally search and replace trying to find sentences like they are doing. As you correctly noted, I want a function that will run only as an after advice to auto-capitalize. – incandescentman Jun 26 '15 at 17:26
  • what about this? (defadvice capitalize-word (after capitalize-word-advice activate) (unless (or (looking-at " I") (looking-at (sentence-end))) (downcase-word 1))) – incandescentman Jul 13 '15 at 6:17
  • Not quite: this will ignore any words starting with "I". You probably want something like (looking-at " I\\b") to only match I followed by a word boundary. Is this working for you with auto-capitalize? I don't have that installed anymore. – glucas Jul 13 '15 at 15:34
  • Here's my inept, non-programmer's attempt at an entire advice. Doesn't work as intended at the moment. (defadvice capitalize-word (after capitalize-word-advice activate) " (unless (or (looking-at " I\\b") (looking-at (sentence-end)) (looking at (line-end)); doesn't work (looking-at (user-full-name)) ) (downcase-word 1))) – incandescentman Jul 14 '15 at 0:18
1

Here's what I came up with, building on @glucas's idea to use defadvice. This code works, but I'm just starting to learn Lisp (and programming) so feel free to suggest improvements to my code.

(defadvice capitalize-word (after capitalize-word-advice activate)
"After capitalizing the new first word in a sentence, downcase the next word, since that next word is no longer the first word in the sentence." 
(unless 
  (or
   (looking-at " I\\b") ; never downcase the word "I" 
   (looking-at (sentence-end))
   (looking-at "[ ]*$") ; hopefully this means "zero or more whitespaces, then end of line"
   (looking-at (user-full-name))
   )
 (downcase-word 1))) 

I also created a companion function to re-capitalize the first word of the next already existing sentence if you wind up typing an entire sentence with a period at the end:

(defun smart-period ()
"When you type a period, capitalize the first word of the next sentence."
(interactive)
(insert ".") 
(save-excursion
(unless (looking-at "[ ]*$") ; zero or more whitespaces, then line break
(capitalize-unless-org-heading))
))

And since I didn't know how to concatenate looking-at regexps, I created an exception for org-mode headings in a separate function:

(defun capitalize-unless-org-heading ()
(interactive)
(unless (looking-at org-complex-heading-regexp)
(capitalize-word 1)
)) 

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.