How to use vimpulse together with autopair.el - emacs

It seems that when vimpulse is running, autopair only works partially in the sense that pressing backspace in empty bracket pairs will no longer remove the closing bracket but only the opening one (which means backspace functions as normal backspace now). An example:
(When Vimpulse and autopair are both active, and current mode is INSERT mode, "|" denotes the cursor)
begin: (|)
Now press "backspace"
expected result: | (both opening and closing brackets are removed)
actual result: |) (only the opening bracket is removed)
I know this has to do with the fact that vimpulse (or rather viper-mode) remapped [backspace] from delete-backward-char to something else (viper-delete-backward-char I think). But I could not find a fix to it.
Could anybody find a solution to this? (so that backspace key will remove both opening and closing bracket when the bracket is empty and cursor is in between).
Thanks!

i think something like this in your init file would work:
(add-hook 'autopair-mode-hook
'(lambda ()
(define-key autopair-emulation-alist [remap viper-delete-backward-char] 'autopair-backspace)))

I will answer this question myself.
I could not figure out an "orthodoxy" way to solve the problem and I came up with a hack.
The function that is bound to in viper insert mode (viper-del-backward-char-in-insert) is adviced to check whether cursor is currently in a matched pair, if so, the character after the cursor is deleted before the actual function is called. This also takes into account possible problem caused by prefix character (backslash).
Just copy the code below into your .emacs file after viper-mode or vimpulse is loaded.
(defun not-escaped (escape-char)
"Character immediately before cursor is not prefixed by escape-char"
(let ((count 0))
(save-excursion
(if (char-before)
(backward-char))
(while (and (char-before)
(= (char-before) escape-char))
(setq count (+ count 1))
(backward-char))
(if (= 0
(% count 2))
t
nil))))
(defun in-matched-empty-pair (pair-list)
"tell if cursor is in an empty pair in pair-list"
(let ((next-char (char-after))
(prev-char (char-before))
(matched nil)
(pair)
(pair-left)
(pair-right))
(if (and next-char
prev-char)
(while (and (setq pair
(pop pair-list))
(not matched))
(setq pair-left (pop pair)
pair-right (pop pair))
(if (= next-char pair-right)
(if (and
(= prev-char pair-left)
(not-escaped ?\\))
(setq matched t)))))
(if matched
t
nil)))
(defvar viper-workaround-pairs
'(
(?\" ?\")
(?\' ?\')
(?\` ?\`)
(?\( ?\))
(?\[ ?\])
(?\{ ?\})
))
;; Workaround for integration problem with autopair
(defadvice viper-del-backward-char-in-insert (before viper-auto-delete-pair-backward())
(if (in-matched-empty-pair viper-workaround-pairs)
(delete-char 1)))
;; Activate advice
(ad-activate 'viper-del-backward-char-in-insert)
This is a hack but it is probably the best I could do now.

Here is my updated solution. Put the following in your .emacs file after the code that loads autopair and vimpulse:
(add-to-ordered-list 'emulation-mode-map-alists (car (last emulation-mode-map-alists)) 400)
It moves autopair's keymap in front of viper's one, giving it higher priority.
Maybe you have to adept the order number (here 400), depending on whether you are using additional emulation-modes.
The result can be checked with C-x v emulation-mode-map-alists. In my case:
(viper--intercept-key-maps cua--keymap-alist autopair-emulation-alist viper--key-maps)
Now, autopair-emulation-alist should be listed before viper--key-maps.

baumichel found the trick. I just add a quick snippet to help :
First, as autopair-mode simply appends autopair-emulation-alist, evaluate:
(defadvice viper-change-state-to-insert (after autopair nil activate)
(add-to-ordered-list 'emulation-mode-map-alists 'autopair-emulation-alist 300))
Then, remember that vimpulse-normalize-minor-mode-map-alist removes all viper keymaps in front of the alist, so execute:
(defadvice vimpulse-normalize-minor-mode-map-alist (after order-viper--key-maps nil activate)
(add-to-ordered-list 'emulation-mode-map-alists 'viper--key-maps 500))
That works for me! I evaluate these snippets in an embedded eval-after-load for both vimpulse and autopair.
My idea is that Emacs dev should rethink the emulation-mode-map-alists and use a property list indexing priority order like this: ((:name viper--key-maps :after (cua--keymap-alist autopair-emulation-alist)) (:name viper--intercept-key-maps :before (cua--keymap-alist autopair-emulation-alist))). Old packages like viper, CUA and so on should be better maintained because our setup becomes ugly after years with Emacs.

Related

Emacs: Assign a function to a keybinding, and with repeated presses, undo the last press and redo at a wider setting

Here's the bigger picture of what I'm trying to do:
With a keypress, it will insert an opening and closing parenthesis right after/before the innermost closing/opening delimiter (bracket, brace, parenthesis, whatever).
But if it is pressed immediately after, it will undo the last insertions, seek out the next closing delimiter, and put it after that, and so on.
I have a working version of the first part, but am looking for "best practices" for the second part (where it undoes and moves outwards)
As a motivator and concrete example, this is a typical scenario when coding in Python. I work with list comprehensions a lot, and often I construct the list, and then decide I want to sum all elements, etc. So I would first type:
[x*x for x in some_lst if is_prime(x)]
and then I'll want to encapsulate this list with a "sum" command:
sum([x*x for x in some_lst if is_prime(x)])
I don't want to have to keep moving the cursor to both the beginning and the end just to insert the parentheses. I'd rather have the point in the list, press a keystroke, have it figure out the delimiters, and place the mark just before the opening inserted parenthesis so that I can type "sum". My function below seems to work (piggybacking on the "expand-region" package):
(defun add-paren ()
(interactive)
(er/mark-outside-pairs)
(exchange-point-and-mark)
(insert-string ")")
(exchange-point-and-mark)
(insert-string "(")
(left-char 1)
)
What's the best practice for the 2nd step?
(Any suggestions/improvements to the above would also be appreciated. This is my first "real" function in Elisp.)
Thanks.
Update: Thanks everyone for the tips. I'll probably use some of them in my final solution. My original question still stands: Is there a standard pattern of "undoing and redoing at a larger scale", or will each problem have its own custom solution? Suppose I use smartparens as suggested to do it all in one keystroke, but I want it to occur on the 3rd level out. What I want is to press the keystroke 3 times and have it place the parentheses there.
So after the first keystroke, it places the parentheses at the innermost level. Pressing it again should remove the inserted parentheses, and place them in the next level up, and so on...
(BTW, not trying to reinvent the wheel. I suspect some of the packages listed may have exactly what I need - I just want practice coding in Elisp).
Update 2:
I guess there is no best practice for this? Anyway, I solved the problem using both expand-region and smartparens:
(defun add-paren ()
(interactive)
(if (eq last-command 'add-paren)
;; (message "AAAA")
(delete-paren)
)
(setq currpoint (point))
(er/mark-outside-pairs)
(if (eq currpoint (point))
(er/mark-outside-pairs)
)
(sp-wrap-with-pair "(")
(left-char 1)
)
(global-set-key (kbd "<f5>") 'add-paren)
(defun delete-paren ()
(interactive)
(setq currloc (point))
(sp-unwrap-sexp)
(goto-char currloc)
(left-char 1)
)
You're already using expand-region. Why not combine that with one of the many "surround region with..." modes?
I personally like smartparens (available via Marmalade or MELPA), but there are many other similar tools.
Use er/expand-region until you've got an appropriate selection, then
( to wrap in parentheses.
When programming, there are several hundred slightly different edit-tasks of this kind. Therefor created a toolkit for it.
In example given, the form might be described as delimited, more precisely bracketed.
ar-bracketed-atpt would mark it.
It's set here like this:
(global-set-key [(super \])] 'ar-bracketed-atpt)
Then comes in another class of commands which do several things on active region. In this case:
M-x ar-parentize-or-copy-atpt RET
It is bound to C-c )
A tarball for all this stuff is available here:
https://launchpad.net/s-x-emacs-werkstatt/
FWIW, I'd do it as follows:
go before the open bracket.
type sum C-M-SPC (
The C-M-SPC selects the parenthesized (well, "bracketized") expression, and the subsequent ( wraps it in parens (because of electric-pair-mode).
I guess there is no best practice for this? Anyway, I solved the problem using both expand-region and smartparens:
(defun add-paren ()
(interactive)
(if (eq last-command 'add-paren)
;; (message "AAAA")
(delete-paren)
)
(setq currpoint (point))
(er/mark-outside-pairs)
(if (eq currpoint (point))
(er/mark-outside-pairs)
)
(sp-wrap-with-pair "(")
(left-char 1)
)
(global-set-key (kbd "<f5>") 'add-paren)
(defun delete-paren ()
(interactive)
(setq currloc (point))
(sp-unwrap-sexp)
(goto-char currloc)
(left-char 1)
)

Scala mode indentation in Emacs

When writing Scala code in Emacs, I notice the following indentation issue:
List(1,2,3).foreach{ x =>
Then press enter.
Then close the bracket, and this is what ends up happening:
List(1,2,3).foreach{ x =>
}
Although this is one particular example, this issue appears in a variety of ways when auto-indenting in Emacs.
An answer to either of these two questions would be appreciated:
How can this issue be fixed so that the brace gets put in the proper place and anything within the braces is indented one level to the right?
Is it possible to disable this type of auto-indentation (i.e. like 'set noautoindent' in vi). I tried solutions like the ones suggested here: Disable auto indent globally in Emacs without success.
Thanks in advance!
I've coded up a simple piece of code - it makes emacs keep indent level for most time, and indents two spaces to the right when the previous non-empty line ends with "{", "(", ">", "=".
Add file besi.el to your load path.
(provide 'besi)
(defun besi-indent-line ()
"Indent current line"
(interactive)
(scala-indent-line-to (besi-indent)))
(defun besi-indent ()
(save-excursion
(forward-comment -100000)
(backward-char 1)
(if (or (looking-at "{") (looking-at "=") (looking-at ">") (looking-at "("))
(+ (current-indentation) 2)
(current-indentation))))
(defun besi-newline ()
(interactive)
(newline-and-indent))
Edit line in scala-mode.el
indent-line-function 'besi-indent-line
and line in scala-mode-ui.el
("\r" 'besi-newline)
Also add a line (require 'besi) to the start of scala-mode.el.
Uploaded it to github for easy reference - besi
I tried to solve this by editing scala-mode-indent.el file. It breaks indent in some of the other situations, but at least you will not have all those indents half-screen forward.
Comment out this line:
;; (scala-indentation-from-following)
And modify scala-indentation-from-preceding:
(defun scala-indentation-from-preceding ()
;; Return suggested indentation based on the preceding part of the
;; current expression. Return nil if indentation cannot be guessed.
(save-excursion
(scala-backward-spaces)
(and
(not (bobp))
(if (eq (char-syntax (char-before)) ?\()
(scala-block-indentation)
(progn
(when (eq (char-before) ?\))
(backward-sexp)
(scala-backward-spaces))
t
;;(scala-looking-at-backward scala-expr-start-re)
))
(if (scala-looking-at-backward scala-expr-start-re)
(+ (current-indentation) scala-mode-indent:step)
(current-indentation)
))))
As I said, it still remains broken after that. I plan to write a better support shortly, maybe in a week or two.
EDIT:
If you want to disable scala indentation completely, comment out the line in scala-mode.el
;; indent-line-function 'scala-indent-line

Copy Character Down in Emacs

I wrote an interactive function which inserts the "character above the point" in to the current line. For instance, given a line containing "12345" followed by a line "abcdef" and the point sitting at the letter "c", copy-down would make the second line become "ab3cdef". copy-down again would make the second line become "ab34cdef".
My function fails (using GNU Emacs 23.3.1 under windows 7) the second time I invoke it by inserting the text from the first invocation and not advancing properly. If I put any emacs "manipulations" in-between invocations, it works fine. (For instance if I do a copy-down, "left arrow", "right arrow", copy-down it works fine for both invocations.)
Here's my function:
(defun copy-down ()
"Grab the character in the line above and insert at the current location."
(interactive)
(let ((beg (progn (previous-line 1) (point)))
(end (progn (forward-char) (point))))
(backward-char)
(next-line 1)
(insert-buffer-substring (current-buffer) beg end)))
If it matters, I usually tie my function to a key: (global-set-key [f5] 'copy-down)
PS. I got used to using this capability in the editor I used before switching to emacs many years ago and I miss it in GNU Emacs. :-(
What you have works just fine for me. That said, previous-line has interaction with other settings (specifically goal-column) and generally shouldn't be used when writing elisp. Instead you should use (forward-line -1). But, of course, your code relies on the goal-column... You can test this by running Emacs without your other configurations, ala emacs -q.
Here's a slightly different version of your code that doesn't rely on goal-column:
(defun copy-down ()
"Grab the character in the line above and insert at the current location."
(interactive)
(let* ((col (current-column))
(to-insert (save-excursion
(forward-line -1)
(move-to-column col)
(buffer-substring-no-properties (point) (1+ (point))))))
(insert to-insert)))
If the problem isn't with using previous-line, then I don't imagine my code would make much of a difference.
Another option you have is to try running it in the debugger to see where your code breaks down. Move the point inside the defun for copy-down and type M-x edebug-defun, and the next time you run it you'll be able to step through the code. Docs for edebug can be found here.
You need to use let* instead of let. The former allows you to use earlier values in later forms in the same statement.
BTW, that's an unconventional way to write elisp, you might want to look at some other code samples.
EDIT:
Hey, someone completely rearranged your function! It might work now.
Try
(defun copy-down (arg)
(interactive "p")
(let ((p (+ (current-column) (point-at-bol 0))))
(insert-buffer-substring (current-buffer) p (+ p arg))))
which has the additional functionality of taking a prefix argument to copy n (default to 1) characters down.

How to move forward and backward in Emacs' mark ring

In Emacs, C-u C-SPC will "jump to the mark, and set the mark from
position popped off the local mark ring". Is there a way to go the opposite way around the mark ring? Say you have typed C-u C-SPC several times and want to go back to a mark you have seen without going all the way around the ring.
Unlike previous answers, this one does only exactly what was asked: the reverse of C-u C-SPC. I find it the most useful.
(defun unpop-to-mark-command ()
"Unpop off mark ring. Does nothing if mark ring is empty."
(interactive)
(when mark-ring
(setq mark-ring (cons (copy-marker (mark-marker)) mark-ring))
(set-marker (mark-marker) (car (last mark-ring)) (current-buffer))
(when (null (mark t)) (ding))
(setq mark-ring (nbutlast mark-ring))
(goto-char (marker-position (car (last mark-ring))))))
Comparing to the answer by scottfrazer, this command has a subtle difference of how it moves the cursor and mark, which more accurately mirrors C-u C-spc, and it does not require that the previous command was a unpop/pop-to-mark-command.
Here's a solution I just finished spending way too much time on. The difference between this and the other solutions is it works across buffers, ie it works on the 'global-mark-ring'. My goal was to emulate history browsing similar to Eclipse or IntelliJ. I bind it to M-left and M-right, obviously you can choose different keys for this.
(defun marker-is-point-p (marker)
"test if marker is current point"
(and (eq (marker-buffer marker) (current-buffer))
(= (marker-position marker) (point))))
(defun push-mark-maybe ()
"push mark onto `global-mark-ring' if mark head or tail is not current location"
(if (not global-mark-ring) (error "global-mark-ring empty")
(unless (or (marker-is-point-p (car global-mark-ring))
(marker-is-point-p (car (reverse global-mark-ring))))
(push-mark))))
(defun backward-global-mark ()
"use `pop-global-mark', pushing current point if not on ring."
(interactive)
(push-mark-maybe)
(when (marker-is-point-p (car global-mark-ring))
(call-interactively 'pop-global-mark))
(call-interactively 'pop-global-mark))
(defun forward-global-mark ()
"hack `pop-global-mark' to go in reverse, pushing current point if not on ring."
(interactive)
(push-mark-maybe)
(setq global-mark-ring (nreverse global-mark-ring))
(when (marker-is-point-p (car global-mark-ring))
(call-interactively 'pop-global-mark))
(call-interactively 'pop-global-mark)
(setq global-mark-ring (nreverse global-mark-ring)))
(global-set-key [M-left] (quote backward-global-mark))
(global-set-key [M-right] (quote forward-global-mark))
Following up my comment to scottfrazer's very handy solution, here's some advice which works in conjunction with that to make it easy to reverse directions around the mark ring at will, without the need to use a different key-binding for each direction.
I use cua-selection-mode, so for me C-SPC is bound to cua-set-mark, but I've written this as a macro so as to advise whichever function is bound to C-SPC, and verified that it works with the default set-mark-command.
To unpop, simply supply a negative prefix argument. e.g. C-- C-SPC
One of the nice things about cua-set-mark is that after an initial C-u C-SPC, you can continue to pop successive marks with just C-SPC, and I've included that behaviour here: After an initial C-- C-SPC you can continue un-popping with just C-SPC. To reverse the direction again and call pop-to-mark, simply supply a positive argument once more with C-u C-SPC.
(defmacro my-unpop-to-mark-advice ()
"Enable reversing direction with un/pop-to-mark."
`(defadvice ,(key-binding (kbd "C-SPC")) (around my-unpop-to-mark activate)
"Unpop-to-mark with negative arg"
(let* ((arg (ad-get-arg 0))
(num (prefix-numeric-value arg)))
(cond
;; Enabled repeated un-pops with C-SPC
((eq last-command 'unpop-to-mark-command)
(if (and arg (> num 0) (<= num 4))
ad-do-it ;; C-u C-SPC reverses back to normal direction
;; Otherwise continue to un-pop
(setq this-command 'unpop-to-mark-command)
(unpop-to-mark-command)))
;; Negative argument un-pops: C-- C-SPC
((< num 0)
(setq this-command 'unpop-to-mark-command)
(unpop-to-mark-command))
(t
ad-do-it)))))
(my-unpop-to-mark-advice)
Here's a function to do it:
(defun unpop-to-mark-command ()
"Unpop off mark ring into the buffer's actual mark.
Does not set point. Does nothing if mark ring is empty."
(interactive)
(let ((num-times (if (equal last-command 'pop-to-mark-command) 2
(if (equal last-command 'unpop-to-mark-command) 1
(error "Previous command was not a (un)pop-to-mark-command")))))
(dotimes (x num-times)
(when mark-ring
(setq mark-ring (cons (copy-marker (mark-marker)) mark-ring))
(set-marker (mark-marker) (+ 0 (car (last mark-ring))) (current-buffer))
(when (null (mark t)) (ding))
(setq mark-ring (nbutlast mark-ring))
(goto-char (mark t)))
(deactivate-mark))))
There are two rings of markers: one local to the current buffer and one global among all buffers.
By default, in Icicles (in Icicle global minor mode):
C-- C-SPC lets you trip among the local markers
C-- C-x C-SPC lets you trip among the global markers
IOW, with a negative prefix arg, C-SPC and C-x C-SPC navigate. Without it they just do what they normally do (set-mark-command and pop-global-mark, respectively).
Navigating works as follows:
Locations are available as completion candidates: the text is that of the marker's line.
Completion: you can use substring, regexp, prefix, fuzzy (various kinds).
You can cycle among any of the completion candidates, or go to any of them directly.
Keys available during completion include:
up, down -- cycle among candidates in *Completions*, without navigating to their locations
C-up, C-down -- cycle, navigating to each location in turn
C-RET, C-mouse-2 -- go directly to the current/clicked candidate (e.g. in *Completions*)
RET, mouse-2 -- same as previous (go to candidate), but end the command (done)
S-TAB -- apropos-complete (substring/regexp)
TAB -- prefix or fuzzy complete
It doesn't do exactly what you're asking for, but it might be worth looking for a package called marker-visit.el which lets you navigate the marks in the current buffer in 'buffer position order'. From that file:
;;; Commentary:
;; This file provides a simple way to navigate among marks in a
;; buffer. C-u C-SPC is similar, but takes you haphazardly around the
;; buffer. Setting bookmarks is a lot of extra work if you just want
;; to jump around your buffer quickly; plus, you have to come up with
;; a name for every bookmark.
;; All the marks you've left while editing a buffer serve as bread
;; crumb trails of areas in the buffer you've edited. It is
;; convenient to navigate back and forth among these marks in order.
;; This file provides two methods to do just that, marker-visit-prev
;; and marker-visit-next. These two functions will take you, from
;; point, to the nearest mark in either direction. The function
;; marker-visit-truncate-mark-ring will truncate the mark ring.
;; The marks you can visit in a buffer consist of: "the mark" plus the
;; contents of the mark-ring.
I bind [S-up] and [S-down] to marker-visit-prev and marker-visit-next respectively.
If you really want/need to navigate in the order your mark-ring has currently, then you might get somewhere by looking at the functions pop-to-mark-command and pop-mark and implementing your own versions to rotate the mark ring in the opposite direction.
The manual says this:
The variable mark-ring-max
specifies the maximum number of
entries to keep in the mark ring. If
that many entries exist and another
one is pushed, the earliest one in the
list is discarded. Repeating `C-u
C-' cycles through the positions
currently in the ring.
I suggest you use that to contain the size of the mark ring (to 3 or 4, mine is currently 16). Then you can move around it much faster using prefixes.
Also:
If you want to move back to the
same place over and over, the mark
ring may not be convenient enough. If
so, you can record the position in a
register for later retrieval (*note
Saving Positions in Registers:
RegPos.).
Not directly answer for this question for emacs keybindings.
For evil users
I found better-jumper for evil users. If you are interested with evil-mode honestly offering to use.
By using How it's offer in it's main repository
(with-eval-after-load 'evil-maps
(define-key evil-motion-state-map (kbd "C-o") 'better-jumper-jump-backward)
(define-key evil-motion-state-map (kbd "<C-i>") 'better-jumper-jump-forward))
It's really easy to go back and forward to old positions of the cursor.
Additional you can create new scenarios by using it's hook function like if I change the buffer mark the old point etc.
For emacs key binding fans
Only advice which I can give for default-keybinding style is helm-all-mark-rings. It gives best visibility about mark-rings.

How do I get Emacs to fill sentences, but not paragraphs?

I've seen at least two recommendations on StackOverflow to insert newlines between sentences when editing LaTeX documents. The reason being that the practice facilitates source control, diffing, and collaborative editing.
I'm basically convinced, but I'm lazy, and I don't want to have to think about it.
So I'm searching for some emacs incantation to handle it for me. Could be a minor mode, could be a set of variables that need to be set.
I think what I don't want is
Soft wrapping of text (say using the longlines and (set long-lines-auto-wrap 't)). This is because I don't want to impose requirements on my collaborators' editors, and I sometimes use other unix tools to examine these files.
I think what I do want is
For fill-paragraph to fill between newlines that look like they mark the end of a sentence.
A solution that works with auto-fill-mode would be a bonus.
That is:
chat chat chat.
A new sentence
with goofed up wrapping that needs to be fixed.
Mumble mumble
Transformed to:
chat chat chat.
A new sentence with goofed up wrapping that needs to be fixed.
Mumble mumble
Your comments and suggestions are appreciated.
Edit: The suggestion by Jouni K. Seppänen pointed me at LaTeX-fill-break-at-separators, which suggests that emacs almost knows how to do this already. Anyway, I'm off to read some code, and will report back. Thanks again.
More general version of the same question: Editor showdown: Maintain newlines at the ends of sentences. Thanks, dreeves.
Here's what I use, which was mostly cribbed from Luca de Alfaro:
(defun fill-sentence ()
(interactive)
(save-excursion
(or (eq (point) (point-max)) (forward-char))
(forward-sentence -1)
(indent-relative t)
(let ((beg (point))
(ix (string-match "LaTeX" mode-name)))
(forward-sentence)
(if (and ix (equal "LaTeX" (substring mode-name ix)))
(LaTeX-fill-region-as-paragraph beg (point))
(fill-region-as-paragraph beg (point))))))
I bind this to M-j with
(global-set-key (kbd "M-j") 'fill-sentence)
The references to "LaTeX" are for AUCTeX support. If you don't use AUCTeX, the let can be simplified to
(let (beg (point))
(forward-sentence)
(fill-region-as-paragraph beg (point)))
I have been meaning to do this forever and I recently found this blog post which worked fairly well for me. So here is (a slightly modified version of) what I have been using for a few days.
(defun auto-fill-by-sentences ()
(if (looking-back (sentence-end))
;; Break at a sentence
(progn
(LaTeX-newline)
t)
;; Fall back to the default
(do-auto-fill)))
(add-hook 'LaTeX-mode-hook (lambda () (setq auto-fill-function 'auto-fill-by-sentences)))
;; Modified from http://pleasefindattached.blogspot.com/2011/12/emacsauctex-sentence-fill-greatly.html
(defadvice LaTeX-fill-region-as-paragraph (around LaTeX-sentence-filling)
"Start each sentence on a new line."
(let ((from (ad-get-arg 0))
(to-marker (set-marker (make-marker) (ad-get-arg 1)))
tmp-end)
(while (< from (marker-position to-marker))
(forward-sentence)
;; might have gone beyond to-marker---use whichever is smaller:
(ad-set-arg 1 (setq tmp-end (min (point) (marker-position to-marker))))
ad-do-it
(ad-set-arg 0 (setq from (point)))
(unless (or (looking-back "^\\s *")
(looking-at "\\s *$"))
(LaTeX-newline)))
(set-marker to-marker nil)))
(ad-activate 'LaTeX-fill-region-as-paragraph)
If you put a comment marker at the end of each sentence, Emacs knows not to move the next line inside the comment:
chat chat chat.%
A new sentence
with goofed up wrapping that needs to be fixed.%
Mumble mumble%
Then M-q fills each sentence separately, at least in AUCTeX 11.85. (If you test this in Emacs, there seems to be a bug where if this is the first paragraph in the buffer and you type M-q, you get an error message. Just put a newline before the text to work around it.)
If you don't want to type the comment characters, you could take LaTeX-fill-paragraph and modify it so that sentence-ending punctuation at end of line works similarly to comments.
(defun wrap-at-sentences ()
"Fills the current paragraph, but starts each sentence on a new line."
(interactive)
(save-excursion
;; Select the entire paragraph.
(mark-paragraph)
;; Move to the start of the paragraph.
(goto-char (region-beginning))
;; Record the location of the end of the paragraph.
(setq end-of-paragraph (region-end))
;; Wrap lines with 'hard' newlines (i.e., real line breaks).
(let ((use-hard-newlines 't))
;; Loop over each sentence in the paragraph.
(while (< (point) end-of-paragraph)
;; Determine the region spanned by the sentence.
(setq start-of-sentence (point))
(forward-sentence)
;; Wrap the sentence with hard newlines.
(fill-region start-of-sentence (point))
;; Delete the whitespace following the period, if any.
(while (char-equal (char-syntax (preceding-char)) ?\s)
(delete-char -1))
;; Insert a newline before the next sentence.
(insert "\n")))))
(global-set-key (kbd "M-q") 'wrap-at-sentences)
May not work in all circumstances, but:
(defun my-fill-sentence ()
"Fill sentence separated by punctuation or blank lines."
(interactive)
(let (start end)
(save-excursion
(re-search-backward "\\(^\\s-*$\\|[.?!]\\)" nil t)
(skip-syntax-forward "^w")
(setq start (point-at-bol)))
(save-excursion
(re-search-forward "\\(^\\s-*$\\|[.?!]\\)" nil t)
(setq end (point-at-eol)))
(save-restriction
(narrow-to-region start end)
(fill-paragraph nil))))
To make it work with auto-fill-mode, add (setq normal-auto-fill-function 'my-fill-sentence) to your LaTeX mode hook (I think).
I am assuming you know elisp.
There are a few approaches you can take:
Hook into auto-fill-mode. There are a lot of hard-coded
conditionals there, so it might not work for you. You can
potentially play with auto-fill-function and see if you have
the hook you need there.
Make a character (probably .) "electric" so that when you press
it, it inserts itself and then calls a function to determine how
to fill the line you're on.
Set an after-change-hook to call a function that determines how
to fill the sentence. This function will be called after every
change to the buffer, so do it efficiently. (This mechanism is
used by font-lock, so don't worry about it too much. It sounds
slow, but really isn't -- people type slowly.)
Once you have hooked in at the right place, you just have to implement
the filling logic. The source for sentence-at-point (from thingatpt) may be
instructive.
Anyway, I've never heard of anyone doing this... but it is definitely possible. Like most things in Emacs, it's just a Simple Matter Of Programming.
If the other answers are too automatic, here's a semiautomatic approach.
It's basically what you would do repeatedly if you were going to manually reformat, but condensed so you can hit a single key repeatedly instead.
;; - go to the end of the line,
;; - do ^d to suck the previous line onto this one,
;; - make sure there's only one space between the now-concatenated
;; lines, and then
;; - jump to the end and hit space so that (with auto-fill-mode)
;; the line nicely rewraps itself:
;; (turn on auto-fill-mode with M-x auto-fill-mode)
(defalias 'fill-sentence
(read-kbd-macro "C-e C-d SPC M-x just- one- space RET C-e SPC <backspace>"))
(define-key global-map [f4] 'fill-sentence) ; or whatever key you like
I like Chris Conway's macro a lot but it only works after you manually line-break each sentence. I'm a lazy guy so I want emacs to do it for me. This morning I finally sat down and looked into the problem. The solution I have now is to hack the built-in macro fill-region-as-paragraph.
After applying the following hack, a new option newline-after-sentence will be set to true. The standard M-q (fill-paragraph) will automatically fill and create line-breaks between sentences. Note that tests are only done with GNU Emacs 23.3.1 — use it at your own risk.
The full macro is long so I won't post it here. The idea is to add the following loops in fill-region-as-paragraph
...
;; Insert a line break after each sentence
(while (< (point) to)
(forward-sentence)
(if (< (point) to) (fill-newline)))
;; This is the actual filling loop.
(goto-char from)
(let (sentbeg sentend)
(while (< (point) to)
(setq sentbeg (point))
(end-of-line)
(setq sentend (point))
(fill-one-line sentbeg sentend justify) ;; original filling loop
(forward-line)))))
...
You can find the full macro in my git repository. Some details are also written in my blog. In case you don't want to read my poor English, you can simply use
$ curl http://fermi.mycloudnas.com/cgit.cgi/fill/plain/hack.el >> ~/.emacs
to append the hack to your ~/.emacs and give it a try. Comments and bug reports are all welcome.
An alternative approach would be to leave your .tex file as is, and use a tool like latexdiff
(described in this StackExchange post) instead of Unix diff. This produces a .tex file with Word-style track changes marks, and handles whitespace correctly so you don't have to worry about where your sentences end.
I wrote the following which loops over a region and inserts newlines. Instead of using forward-sentence which didn't work for me, I use re-search-forward "[.?!][]\"')}]*\\( \\)", which finds all sentences followed only by two spaces (the regexp is a modified sentence-end). The newline is made using newline-and-indent.
(defun fill-sentences-in-paragraph ()
"Put a newline at the end of each sentence in paragraph."
(interactive)
(save-excursion
(mark-paragraph)
(call-interactively 'fill-sentences-in-region)))
(defun fill-sentences-in-region (start end)
"Put a newline at the end of each sentence in region."
(interactive "*r")
(call-interactively 'unfill-region)
(save-excursion
(goto-char start)
(while (re-search-forward "[.?!][]\"')}]*\\( \\)" end t)
(newline-and-indent))))
To be able to fix improperly formatted text such as the example "chat chat chat...", fill-sentences-in-region first calls unfill-region which gets rid of sentence-breaking whitespace:
(defun unfill-region (beg end)
"Unfill the region, joining text paragraphs into a
single logical line. This is useful, e.g., for use
with 'visual-line-mode'."
(interactive "*r")
(let ((fill-column (point-max)))
(fill-region beg end)))
I use visual-line-mode and replace my default paragraph fill M-q to fill-sentences-in-paragraph with (global-set-key "\M-q" 'fill-sentences-in-paragraph).