Emacs, quick-jump and go-mode: point not updated during navigation - emacs

I want to combine the go-mode godef-jump with quick-jump, such that I drop a marker both before and after the jump.
(defun my-go-quick-jump-push-def-hook (pnt)
(interactive "d")
(message "%s %d" (buffer-name) pnt)
(quick-jump-push-marker)
(godef-jump pnt)
(quick-jump-push-marker)
(message "%s %d" (buffer-name) (point))
)
(defun my-go-mode-hook ()
(local-set-key (kbd "M-.") 'my-go-quick-jump-push-def-hook)
)
However, the message calls indicate that the buffer has not been updated after the call to godef-jump completes, and nor does (point) give a different value from pnt. But godef-jump does complete and does change the buffer where necessary. So something's up with the evaluation order that I can't figure out - it's almost like the actual navigation is going on lazily. Is this expected or is this something odd that go-mode is doing?
go-mode is at https://github.com/dominikh/go-mode.el/blob/master/go-mode.el,
quick-jump is at http://www.emacswiki.org/emacs/quick-jump.el
Many thanks.
Update: this problem seems to only happen when the jump is to a different buffer. I don't know enough about with-current-buffer (used in godef--find-file-line-column) to understand what's going wrong - my reading of the docs is that with-current-buffer shouldn't cause that buffer to be activated at all once the body completes, so I'm at a loss to understand why godef-jump works at all...

Answering my own question, basically, see the PR I made, and the discussion: https://github.com/dominikh/go-mode.el/pull/85
The problem was specific to go-mode, and has now been fixed there.

Related

Open Org Capture buffer in specific window?

I've been an Emacs user for about a year or so. I routinely have the same window set up each session (four windows).
I've set up capture templates and can capture what I want, but: instead of capture mode temporarily jerking me out of my window setup, I'd like the chosen capture template to open in a new (fifth) window, preserving my existing layout. I typically want the capture template open for a while, so it's disruptive.
This seems like it would be an obvious option, but I can't figure it out. Thanks in advance to all the Emacs heads out there.
I came up with a easier-to-use version of Dan's answer to the linked question:
(defun my-org-capture-place-template-dont-delete-windows (oldfun &rest args)
(cl-letf (((symbol-function 'delete-other-windows) 'ignore))
(apply oldfun args)))
(with-eval-after-load "org-capture"
(advice-add 'org-capture-place-template :around 'my-org-capture-place-template-dont-delete-windows))
That is, instead of having to modify Org-mode code and remove the call to delete-other-windows, this piece of code temporarily redefines delete-other-windows to ignore while org-capture-place-template is being called.
It doesn't do quite what you want: it picks one of the existing windows and puts the capture buffer there. At least it's better than the default behaviour of removing all previous windows but one.
There's probably a way to do what you want by customising the variable display-buffer-alist, but I couldn't figure it out...
You could also use https://github.com/raxod502/el-patch and patch org-capture after loading (look for the (el-patch-remove (delete-other-windows))):
(el-patch-feature org-capture)
(with-eval-after-load 'org-capture
(el-patch-defun org-capture-place-template (&optional inhibit-wconf-store)
"Insert the template at the target location, and display the buffer.
When `inhibit-wconf-store', don't store the window configuration, as it
may have been stored before."
(unless inhibit-wconf-store
(org-capture-put :return-to-wconf (current-window-configuration)))
(el-patch-remove (delete-other-windows))
(org-switch-to-buffer-other-window
(org-capture-get-indirect-buffer (org-capture-get :buffer) "CAPTURE"))
(widen)
(org-show-all)
(goto-char (org-capture-get :pos))
(setq-local outline-level 'org-outline-level)
(pcase (org-capture-get :type)
((or `nil `entry) (org-capture-place-entry))
(`table-line (org-capture-place-table-line))
(`plain (org-capture-place-plain-text))
(`item (org-capture-place-item))
(`checkitem (org-capture-place-item)))
(org-capture-mode 1)
(setq-local org-capture-current-plist org-capture-plist)) )
For some reason, the #legoscia approach fails for me in emacs 28.
So here is the el-patch snippet as suggested previously:
(el-patch-feature org-capture)
(with-eval-after-load 'org-capture
(el-patch-define-and-eval-template
(defun org-capture-place-template)
(el-patch-remove (delete-other-windows))))

emacs suggests to recover-file, but I missed it: how to make it prompt?

When emacs notices a crash, on next open of the file it "suggests" M-x recover file. But that only flashes up briefly, so I missed it this morning :( I went on editing, and lost last evening's work.
Is there a way to make that suggestion a prompt that must be responded to before it continues?
The warning message comes from the function after-find-file. I don't find an option to control this, but you can define a function to do something similar:
(defvar already-in-prompt-for-auto-save nil)
(defun prompt-for-auto-save-recovery ()
(if (and (not buffer-read-only)
(not already-in-prompt-for-auto-save)
(file-newer-than-file-p (or buffer-auto-save-file-name
(make-auto-save-file-name))
buffer-file-name)
(y-or-n-p (format "%s has auto save data: do you want to recover it? "
(file-name-nondirectory buffer-file-name))))
(let ((already-in-prompt-for-auto-save t))
(recover-this-file))))
and then install it as a hook.
(add-hook 'find-file-hook 'prompt-for-auto-save-recovery)
This is lightly tested code--I extracted what looked like the relevant parts of after-find-file--but maybe it will get you started in the right direction.

Emacs bibtex-mode unable to parse un-visited file

I'm not sure the best way to phrase this question, but hopefully my examples will make clear what's going on.
I have some code where I want to insert the contents of a bibtex file in a temporary buffer and move through the entries one at a time, grabbing the entry using bibtex-parse-entry for later use. However, whenever I run the code on a bibtex file that I haven't visited during this emacs session, bibtex-parse-entry returns a (wrong-type-argument stringp nil) error.
Once I visit the file, even if I then close the buffer, the code runs without any issues. And if I remove the bibtex-parse-entry call, bibtex-kill-entry has the same issue.
Here's the elisp code I'm using:
(with-temp-buffer
(insert-file-contents "~/test.bib")
(goto-char (point-min))
(bibtex-mode)
(while (not (eobp))
(let* ((entry (bibtex-parse-entry t)))
(message "i'm here"))
(bibtex-kill-entry)
(bibtex-beginning-of-entry)
)
)
and a dummy .bib file:
#Article{test,
author = {joe shmo},
title = {lorem ipsum},
journal = {something},
year = {1990},
}
With these you should be able to reproduce my error.
I have no idea what's going on, so I'd greatly appreciate any help!
I am not really an expert at this. I just debugged the situation a bit (try M-x toggle-debug-on-error in cases like this) and found a call to looking-at with a nil value. The stack-trace tells us that the problem is in the bibtex function bibtex-valid-entry. There, I found the variable bibtex-entry-maybe-empty-head which --according to its docstring-- is set by bibtex-set-dialect.
Thus, adding a call to bibtex-set-dialect to your function after calling bibtex-mode seems to fix the issue. As I do not really know, what you want to achieve in the end, I am not sure it actually fixes your problem. At least the function does raise an error anymore.
Hope, that makes sense and helps.
(with-temp-buffer
(insert-file-contents "~/test.bib")
(goto-char (point-min))
(bibtex-mode)
(bibtex-set-dialect) ;; <-- add this
(while (not (eobp))
(let* ((entry (bibtex-parse-entry t)))
(message "i'm here"))
(bibtex-kill-entry)
(bibtex-beginning-of-entry)))

Advice only applies in all cases after function calling advised function is re-evaluated

In my .emacs file, I have:
(defadvice narrow-to-region (around test activate)
(message "advice")
ad-do-it)
When I call narrow-to-region, the advice runs and prints 'advice' before narrowing.
When I call narrow-to-defun, it does not.
I found where narrow-to-defun is defined - in lisp.el, and re-evaluated the function. At this point, the advice started running.
What could cause this?
The problem is, apparently, due to byte-compilation and therefore the inability to advise the narrowing primitives (narrow-to-region is the primitive, narrow-to-defun calls narrow-to-region).
The following post on Null Program ("The Limits of Emacs Advice") goes into detail about this problem. Here's the shortish version from deep in the post:
It turns out narrow-to-region is so special -- probably because it's used very frequently -- that it gets its own bytecode. The primitive function call is being compiled away into a single instruction. This means my advice will not be considered in byte-compiled code. Darnit. The same is true for widen (code 126).
As to why the advice started working after you re-evaluated narrow-to-defun: I'm guessing it's because you ended up replacing the byte-compiled version when you re-evaluated.
#Dan described the problem well. Here is some info that might help you work around it.
What you can do is to advise (or to redefine) also narrow-to-defun (and perhaps narrow-to-page), so it acts similarly.
FWIW, I do something similar in library wide-n.el (see Multiple Narrowings).
I advise narrow-to-region. But I also redefine narrow-to-defun and narrow-to-page. In all 3 cases I make the same change, to record the details of each narrowing so you can return to them later. Here is the advice, for example:
(defadvice narrow-to-region (before push-wide-n-restrictions activate)
"Push the region limits to `wide-n-restrictions'.
You can use `C-x n x...' to widen to previous buffer restrictions."
(when (or (interactive-p) wide-n-push-anyway-p)
(wide-n-push (ad-get-arg 0) (ad-get-arg 1)))) ; Args START and END.
And here is the relevant part of the narrow-to-defun redefinition:
...
(goto-char end)
(re-search-backward "^\n" (- (point) 1) t)
(when (or (interactive-p) wide-n-push-anyway-p) (wide-n-push beg end)) ; <=====
(narrow-to-region beg end))))

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))