flyspell correct the previous to previous mistake - emacs

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

Related

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

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.

Undo buffer-search in Emacs

After doing a (re-search-forward str) in the current buffer, it would be nice in some cases to have an easy method to return to the previous buffer position. The behavior should be like (undo) for buffer changes. So if I do two searches forward, first from position A to B, and then from B to C, I would like to press a key to go back one step (from C to B), and pressing the key again would leave me at A..
If you are using re-search-forward in Lisp code (and you probably should be, if you are using it at all, even though it is a command), then do not set the mark in order to be able to return to your starting point.
Instead, simply save the starting position ((point)) as, say, variable beg, and then use goto-char beg.
See this paragraph in (elisp) The Mark:
Novice Emacs Lisp programmers often try to use the mark for the
wrong purposes. The mark saves a location for the user's
convenience. An editing command should not alter the mark unless
altering the mark is part of the user-level functionality of the
command. (And, in that case, this effect should be documented.)
To remember a location for internal use in the Lisp program, store
it in a Lisp variable. For example:
(let ((beg (point)))
(forward-line 1)
(delete-region beg (point))).
With this
(global-set-key
(kbd "M-p")
(lambda()(interactive) (set-mark-command 4)))
I can jump backwards one by one through a few C-M-s.
Note that this works for isearch-forward-regexp, not for plain
re-search-forward (this one doesn't set the mark).
But with elisp it's no problem - just call push-mark before
re-search-forward.
To sum up, the following seems to work:
(defun my-search-fun (str)
(interactive)
(push-mark)
(beginning-of-buffer)
(re-search-forward str))
(defun my-undo-search ()
(interactive)
(pop-mark)
(goto-char (mark))

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 function to uncomment regardless of mode

Main goal: making a smart "uncomment" function suitable for any mode.
(defun uncomment-mode-specific ()
(interactive)
(if (region-active-p)
(comment-region (region-beginning) (region-end) -1) ; so far so good
(if (= ";" (line-beginning-position)) ; here is the problem
(message "successful")
(message "unsuccessful"))
))
In the if statement, I would like to check for the value of the first character of the line, and if it equals the variable comment-start (which would return ";" in emacs lisp), goto beginning-of-line and delete the character. Ideas?
EDIT: More clarification as requested in a comment below follows. I would like a function to do:
1) If a region is selected, remove the comments (here that uncomment-region or comment-dwim would work as pointed out by Patrick)
ELSE:
2) If the first character of the line at point is a comment character, remove the comment character.
ELSE:
3) Search current line for comment (excluding \% or \;, mode dependent), move up to comment and kill the line starting with the comment sign.
I could not see how you would want this to work differently. It could then be bound to one key to simply remove comments, depending on the mode, using comment-start to identify the comment character.
I'm posting this as an alternative answer, since what you are trying to do is partly done already with the comment-dwim command. From the docs (you can find it using C-h f comment-dwim)
comment-dwim is an interactive compiled Lisp function in
`newcomment.el'.
It is bound to M-;.
(comment-dwim ARG)
Call the comment command you want (Do What I Mean).
If the region is active and transient-mark-mode is on, call
comment-region (unless it only consists of comments, in which
case it calls uncomment-region).
Else, if the current line is empty, call comment-insert-comment-function
if it is defined, otherwise insert a comment and indent it.
Else if a prefix ARG is specified, call comment-kill.
Else, call comment-indent.
You can configure comment-style to change the way regions are commented.
So in order to use it, simply select a region with C-SPC (set-mark-command) and move the caret to the other point and run comment-dwim.

Elisp: Old variable values seem to stick

Beginner question for emacs lisp.
In my .emacs I have written the following:
(defun line-text-up-with-parentheses-above()
(interactive)
(line-text-up-with-char-above "("))
(defun line-text-up-with-char-above(charval)
(interactive)
(setq now-point (point))
(previous-line)
(setq above-point (point))
(forward-char)
(search-forward charval (line-end-position) nil)
(setq above-paren (point))
(goto-char now-point)
(insert (make-string (- above-paren above-point) ? )))
(global-set-key (kbd "\<C-S-iso-lefttab>") 'line-text-up-with-parentheses-above)
The function intends to line the text at the point up with the character after the "(" on the line above it.
Everything seem to work fine, unless the function is called twice in a row. In this case, the text before the point advances exactly the same amount as last time.
Seems like the variables aren't being set the second time around.
Does anyone know how to fix this?
Many thanks!
You calculate the intended indentation. However, you always insert it regardless of how many spaces the current line contains.
You could either simply delete the spaces on the current line before inserting the new spaces, or you could try to calculate the number of spaces needed and insert or delete, as needed.
Some hints:
By using setq you are using global variables, try to bind them using let.
Instead of recording where the point is before you move it around and restore it afterwards, you could use the special construct save-excursion.
I think the variables are being set correctly (although Lindydancer is correct to suggest let instead of setq). And your function works fine for me if I call it with point at the first non-whitespace character on the line you want to 'line up'. The only problem I see is that the function lines up with wherever point is when you call it, which is not correct if point is not at the first non-whitespace character.
You can fix this be adding (back-to-indentation) immediately after (interactive) in line-text-up-with-char-above. Actually, once you wrap everything in save-excursion you'll want to add back-to-indentation as the first function within the save-excursion form.
Protip: align and specifically align-regexp.