Elisp: is this an expected behavior of save-excursion? - emacs

The starting condition is this text in *scratch*:
(
form
30
)
(
baz
41
)
The whitespace is the only important thing here.
Now, with point on o in form, evaluating with M-:(eval-expression)
this code:
(save-excursion
(up-list)
(backward-list)
(indent-sexp))
Gives
(
form
30
)
with point on o. Same (expected) behavior repeats for point on r,m,0,a,z,1.
However for starting point on f, 3, b, 4, the resulting point is one character before
the expected position.
Is this the expected behavior or a bug?
If it's expected, I'd like to know more about rules and edge cases.
UPD: Add intuitive save-excursion variant
Just in case someone will want it,
here's the behavior that's more intuitive to me (i.e. saves point on f, 3 etc.):
(defmacro save-excursion-ex (&rest body)
"More intuitive (`save-excursion' BODY)."
`(let ((ext (save-match-data
(looking-back "^\\s-*")))
(out (save-excursion
,#body)))
(if ext
(if (or (bolp)
(= (point)
(save-excursion
(back-to-indentation)
(point))))
(back-to-indentation)
(error "Unexpected")))
out))

In Emacs, the point is considered to be "before" (point).
So, when indent-sexp inserts whitespace, it inserts it after the point.
E.g., when you say that the point is on f, it is actually at the beginning of line right before f and indent-sexp inserts spaces after it and before f.
The general rule is that if the point is between the beginning of line and the first non-blank character in the line, it will end up at the beginning of the line, otherwise it will preserve its position relative the surrounding text.
Think of it this way: we indent the code by
delete all leading blanks
insert leading blanks as necessary
So, the answer is: this is the expected behavior.
More to the implied gist of your question, there is no reason to rely on the specific position of the point after indentation if the point was adjacent to whitespace which was normalized.
If you need to get your code working, add a (goto-char (line-beginning-position)) (or equivalent) after the indentation call and then skip to the position you want to operate on.

Related

End function on successful function call, or evaluate for function

I apologize for the title.
I have a control flow issue. I would like to call just one of two functions. I put calls to both inside another function. If I could evaluate for either's value, then I could call or not call the next based on that value; if there were a return value associated with each call based on whether or not they actually did something it could be used in a conditional branch. Alternatively, if I knew a value for the character preceding the carat, that could act as an argument for the function.
I don't know how to do find these values.
My actual code is nearly simplest case. It is as follows:
(defun rad-delete-backward-char-indent ()
"Delete one character or up to indent's worth of white space"
(interactive)
(delete-horizontal-space 4)
(delete-backward-char))
(global-set-key "\d" 'rad-delete-backward-char-indent)
I would like to delete either one character, or all preceding white-space up to four spaces worth. Currently, I am deleting up to four white-spaces and a character. i.e.
"foo___^" << "fo^"
As opposed to:
"foo___" << "foo^"
Drew answered the essential question. The solution I used was to evaluate for the preceding character to the pointer using preceding-char generic function.
(defun rad-delete-backward-char-indent ()
"Delete one character or up to one tab worth of white space"
(interactive)
(setq first_char (string (preceding-char)))
(setq i 0)
(while (not (= i 4))
(if (string= " " (string (preceding-char)))
(delete-backward-char 1))
(setq i (1+ i)))
(unless (string= " " first_char)
(delete-backward-char 1)))
(global-set-key "\d" 'rad-delete-backward-char-indent)
(defun rad-delete-backward-char-indent ()
"Delete one character or up to indent's worth of white space"
(interactive)
(if <SOMETHING>
(delete-horizontal-space 4)
(delete-backward-char))
But it's not clear what the <SOMETHING> is that you want to test.
You say "If I could evaluate for either's value, then I could call or not call the next based on that value." I don't understand that sentence. Could you say it another way? Just what do you want to test, to know which code to evaluate?
What do you mean by evaluate for either's value?
While I think Drew's answer is your better choice, another solution, maybe closer to what you thought you wanted, is to check whether the first function changed something:
(defun rad-delete-backward-char-indent ()
"Delete one character or up to indent's worth of white space"
(interactive)
(let ((start (buffer-chars-modified-tick)))
(delete-horizontal-space 4)
(when (eq (buffer-chars-modified-tick) start)
(delete-backward-char))))
By the way, I don't think the 4 above does what you want. It does the same as any other non-nil value: it tells delete-horizontal-space to only delete backwards, but it doesn't bound the number of spaces it will remove.

How to show the whole line in the window?

I'm using Emacs 24.2 with a line-wrapping activated.
When I read log files of various simulations which contain messages like: "Error: ...some message...", I perform an incremental search: C-s error RET, C-s, C-s...
I find it very annoying that the highlighted result of the search (the word Error) is displayed at the bottom of the screen, and all the additional wrapped lines can't be seen:
I'd like to add modifications which ensure that the whole line of text will be displayed in the buffer, like this:
I found this question concerning re-centering of the search results. It seems that I could use the same defadvice statements for the search functions, but rather than re-centering the line I need just scroll the screen down by the number of wrapped parts.
How to do this?
You can use the solution on the question you reference, but changing recenter-top-bottom by this highly untested function:
(defun scroll-if-truncated()
(scroll-up
(/ (- (save-excursion
(end-of-line) (point))
(save-excursion
(beginning-of-line) (point)))
(window-body-width))))
After playing a bit with the code according to #juanleon's advice, I ended up with this:
;; Execute after each update in isearch-mode
(setq isearch-update-post-hook 'show-whole-line)
(defun show-whole-line ()
"Scroll such that the whole line (which contains the point) will be visible."
;; If it is the top part which is truncated
(if (not (pos-visible-in-window-p (line-beginning-position)))
(let
((amount
;; the required number of lines to scroll
(ceiling (/
(- (window-start)
(line-beginning-position))
(float (window-body-width))))))
;; don't scroll at all if the search result will be scrolled out
(if (< amount (/
(- (window-end)
(point) )
(float (window-body-width))))
(scroll-down amount)))
;; Else
(if (not (pos-visible-in-window-p (line-end-position)))
(let
((amount
(min
;; the required number of lines to scroll
(ceiling (/
(-
(line-end-position)
(window-end (selected-window) t))
(float (window-body-width))) )
;; however not to scroll out the first line
(/ (- (line-beginning-position) (window-start)) (window-body-width)))))
(scroll-up amount)))))
Few explanations:
Setting defadvice for isearch-forward is not enough - this function is not called again when you add chars to the search string. After a quick review of isearch.el.gz package I decided to advice to isearch-update function. This also eliminates the need of adding a separate advice for isearch-repeat-forward and etc. Later I noticed that there is a predefined hook in isearch-update, therefore no need for defadvice here.
show-whole-line function checks whether the beginning of the current line is visible. If not, it scrolls-down to show the beginning of the line, unless this scrolling will result in hiding the search match itself.
If the beginning of the line is visible, show-whole-line checks whether the end of the line is also visible. If not, it scrolls-up to show the end of the line, unless this scrolling will result in hiding the beginning of the line. I prefer to be able to see the beginning of the line.
This function and a hook work pretty well, but there is one annoying thing about it: the function is called when you initially press C-s (before you typed in any search string). This means that if the point is at a line which has its beginning or end out of the window, a simple invocation of C-s will result in scrolling in some manner.
While not critical at all, I'll be glad to hear suggestions how to remove the above side effect.
You should be able to get the behavior you want using variables scroll-conservatively and scroll-margin, in particular the latter.

Emacs: line numbers that respect line-wrapping

Modes: I'm using linum for line numbers, the package linum-relative for relative line numbers. If it matters, I am also using visual-line-mode. These are flexible.
Currently, a single line (i.e. text without a newline) is numbered as only one line, regardless of how many times it is wrapped. I am wondering if there is a way to change the numbering to respect these wraps. So, for example,
263 This is all in
a single line
without newlines
might become:
263 This is all in
264 a single line
265 without newlines
and, in relative mode:
0 This is all in
a single line
without newlines
might become:
-1 This is all in
0 a single line
1 without newlines
I really only want the change in relative mode, but would not mind if it spills over into absolute mode.
A toggled change that works on both would be most useful - that way, the user can specifically select when, or with which modes, to turn it off or on.
If the goal is navigation, I suggest a similar solution via the popular ace-jump-mode.
If the goal is just persistent line numbering, you might consider longlines-mode instead of visual-line-mode (but I would avoid this, personally).
ace-jump # GitHub
https://github.com/winterTTr/ace-jump-mode
Demo:
http://dl.dropboxusercontent.com/u/3254819/AceJumpModeDemo/AceJumpDemo.htm
With it, you can jump to any line with as little as two keypresses.
In addition to lines, you can jump to the start of any word; there's also individual character-level jump precision. If desired, it can be configured to restrict jumps to the current window/buffer, or across all windows in the current frame, and even multi-frames.
It doesn't, however, recognize wrapped lines as jump-able locations. Again, you might consider longlines-mode as a fix for this if it is really important to you, but as I understand, it's considered hack'ish and deprecated in favor of visual-line-mode. Though, with longlines-mode, the lines are renumbered exactly as you want in your first example.
I'm assuming the goal is navigation, and as such, I think you'll find with just a little practice that word-based jumping or even jumping via incremental search to be a superior solution.
Update
Here's a simple solution to trick ace-jump to scan within N lines using emacs narrowing features; perhaps others can improve upon it. You could also do something similar for word and line modes.
(defun brian-ace-jump-to-char-within-N-lines (&optional n)
(interactive "p")
(let* ((N (or n 0))
(query-char (read-char "Query Char:"))
(start (save-excursion
(forward-line (- N))
(point)))
(stop (save-excursion
(forward-line (1+ N))
(point))))
(unwind-protect
(condition-case err
(progn
(narrow-to-region start stop)
(ace-jump-char-mode query-char))
(error
(message (error-message-string err))))
(widen))))

flyspell correct the previous to previous mistake

suppose I have buffer contents as follows
teh msot |
curser is at |. generally I can correct msot to most with single C-; press (flyspell-auto-correct-previous-word). What I want is to correct teh to the, i.e previous to previous mistake. (or in general nth spell)
It seems flyspell-auto-correct-previous-word is taking numerical argument but not yielding intended result.
what am I missing.?
UPDATE:
Why I need this., when I write research notes, flyspell mistakenly marks some scientific words wrong. So need to skip the one or two false marks.
C-h f flyspell-auto-correct-previous-word tells me that the numerical argument is called "position". That does not look like what you are looking for. Position is likely to refer to a position in the buffer. Looking at the flyspell sourcecode reveals that the parameter is not used in the intendet way (cant tell what an overlay is thoug...)
;*---------------------------------------------------------------------*/
;* flyspell-auto-correct-previous-word ... */
;*---------------------------------------------------------------------*/
(defun flyspell-auto-correct-previous-word (position)
"*Auto correct the first mispelled word that occurs before point."
(interactive "d")
(add-hook 'pre-command-hook
(function flyspell-auto-correct-previous-hook) t t)
(save-excursion
(unless flyspell-auto-correct-previous-pos
;; only reset if a new overlay exists
(setq flyspell-auto-correct-previous-pos nil)
(let ((overlay-list (overlays-in (point-min) position))
(new-overlay 'dummy-value))
[SNIP]
also the (interactive "d") shows that the current position of point is assigned to position in case of an interactive call.
matthias

(re)number numbered lists in emacs (muse)

suppose I have a text list in emacs like this:
a
b
c
...
d
Is there a way to assign numbers to those items in Emacs, by selecting the region? End results should look like:
1. a
2. b
3. c
j. ...
n. d
Thanks.
The way I do this, which may not be optimal, is to use regex search and replace. This, of course, requires that you be able to define a regex to match the start of the lines you want numbers on. Taking your example, I'd use a search regex like this:
\([a-z]\)
note the capturing brackets, we'll need that first letter soon. And a replace regex like this:
\#. \1
where:
\# is a special form which is replaced, by Emacs, by the right number (though see the warning below);
. writes a stop; and
\1 writes a space and the captured group.
WARNING: Emacs will number your items 0, 1, 2, .... Until someone posts to tell us how to start at 1, I always insert a dummy 0th element before the edit, then delete it.
You can use the Emacs Keyboard Macro Counter.
Put the cursor one line ABOVE your list.
Start a macro: F3
Insert the counter value: C-x C-k C-i. A 0 will appear
Insert the DOT and a space: .
Move the cursor to the next line
Stop the macro: F4
Select your list
M-x apply-macro-to-region-lines
You can delete the 0 you added on the top and enjoy :)
NOTE: This will create a numbered list. It will not use letters.
A much simpler way is to use the CUA library's advanced rectangle editing commands. CUA is included in Emacs (at least 23.1, I think it's in earlier versions as well), so there isn't any new code to get.
You can use cua-set-rectangle-mark (bound to C-Return by default) to start a rectangle, and then use cua-sequence-rectangle to insert increasing values. It also gives you control over the format and starting value, so there is a lot of flexibility.
As an aside, CUA is primarily designed to make Emacs operate more like standard text editors (with C-c for copy, C-v for paste, etc), but it also includes some unrelated niceties, like rectangle editing. Don't ask me why :). If you want to use the rectangle editing without enabling the CUA keybindings (which is what I do), set cua-enable-cua-keys to nil, which can be done via customize.
(defun number-region (start end)
(interactive "r")
(let* ((count 1)
(indent-region-function (lambda (start end)
(save-excursion
(setq end (copy-marker end))
(goto-char start)
(while (< (point) end)
(or (and (bolp) (eolp))
(insert (format "%d. " count))
(setq count (1+ count)))
(forward-line 1))
(move-marker end nil)))))
(indent-region start end)))
Here's some elisp code to do it; would be easy to customize if you like tinkering.
This will number the current region (unless it is already numbered), and also the last line binds to the M-n keys. You could use a function key "[F6]" as needed.
Modified to take a format string to use. The default is 1. but you could do something like %d) to get a bracket instead of a . and so on.
(defun number-region(fmt)
(interactive "sFormat : ")
(if (or (null fmt) (= 0 (length fmt)))
(setf fmt "%d. "))
(save-excursion
(save-restriction
(narrow-to-region (point) (mark))
(goto-char (point-min))
(let ((num 1))
(while (> (point-max) (point))
(if (null (number-at-point))
(insert (format fmt num)))
(incf num)
(forward-line))))))
(global-set-key "\M-n" 'number-region)
Not a direct answer to your question, but if you find yourself manipulating numbered lists frequently, you may want to look into org-mode. In particular, the section on plain lists.