Automatically jump to tag in Emacs - emacs

I'd like to have find-tag automatically accept the default option (i.e. the word at point) and jump to the tag postion without prompting.
Is this possible?
I'm also using the advised version of find-tag from Emacswiki, that in case of match re-runs ctags. So I'd like something like this:
is current word a known tag?
-> yes: jump to it without further confirmation
-> no: rerun ctags
is it known now?
-> yes: jump to it without further confirmation
-> no: prompt user for input
Thank you!

This is one of the top hits on Google for "find tags emacs no prompt." For the simple version of that - without the ctag-regeneration logic the poster mentioned - it seems the key is:
(find-tag (find-tag-default))
So, for me, this works:
(defun find-tag-no-prompt ()
"Jump to the tag at point without prompting"
(interactive)
(find-tag (find-tag-default)))
;; don't prompt when finding a tag
(global-set-key (kbd "M-.") 'find-tag-no-prompt)

Here is my settings for ctags, works awesome for me. I borrow it from here.
(require 'eproject)
(require 'etags-select)
(defun build-ctags ()
(interactive)
(message "building project tags")
(let ((root (eproject-root)))
(shell-command
(concat "ctags-exuberant -e -R --extra=+fq --exclude=db --exclude=test --exclude=.git --exclude=public -f " root "TAGS " root)))
(visit-project-tags)
(message "tags built successfully"))
(defun visit-project-tags ()
(interactive)
(let ((tags-file (concat (eproject-root) "TAGS")))
(visit-tags-table tags-file)
(message (concat "Loaded " tags-file))))
(defun hbin-find-tag ()
"Borrow from http://mattbriggs.net/blog/2012/03/18/awesome-emacs-plugins-ctags/"
(interactive)
(if (file-exists-p (concat (eproject-root) "TAGS"))
(visit-project-tags)
(build-ctags))
(etags-select-find-tag-at-point))
(global-set-key (kbd "M-.") 'hbin-find-tag)
PS: you may be need these:
git://github.com/jrockway/eproject.git
git://github.com/emacsmirror/etags-select.git

Well, I found a hack-y solution:
;; auto jump
(global-set-key (kbd "C-x C-M->") 'find-tag) ; bind to some unused placeholder
(global-set-key (kbd "M-.") (kbd "C-x C-M-> <return>"))
First bind find-tag to some dummy binding that you'll never use anyway (this step is necessary to avoid infinite loops). Then bind M-. to this new binding + <return>.
Ugly, but works... I'll leave the question open if somebody has a better answer (including handling of failed search as described in the original question).

here's a slightly modified version that loads dependent gems (useful in ruby on rails)
(defun build-ctags ()
(interactive)
(message "building project tags")
(let ((default-directory (eproject-root)))
(shell-command (concat "exctags -e -R --extra=+fq --exclude=db --exclude=test --exclude=.git --exclude=public -f TAGS * " (trim-string (shell-command-to-string "rvm gemdir")) "/gems/*"))
(visit-project-tags)
(message "tags built successfully")))

Emacs 25 does this by default. M-. (xref-find-definitions) jumps to the definition and M-, (xref-pop-marker-stack) pops back.

Related

How to turn a (non-interactive) function into a command (interactive function) in Emacs-LISP?

I want to call the function markdown-back-to-heading, which is native in Markdown mode in Emacs. I understand that interactive turns non-interactive functions interactive, or formally functions into commands:
Special Form: interactive arg-descriptor
This special form declares that a function is a command, and that it may therefore be called interactively (via M-x or by entering a key sequence bound to it).
I tried:
(define-key markdown-mode-map (kbd "C-c C-h") 'markdown-back-to-heading)
This throws an error: Wrong type argument: commandp, markdown-back-to-heading.
So I wrapped it with an interactive function, and it works:
(defun my-markdown-back-to-heading ()
"Wrap function to be called interactively."
(interactive)
(markdown-back-to-heading))
(define-key markdown-mode-map (kbd "C-c C-h") 'my-markdown-back-to-heading)
Is there a better way to turn the native function into an interactive command?
You can alternatively use the interactive-form symbol property.
For details see C-hig (elisp)Using Interactive
Here's a simple example:
;; Enable M-x kill-process (to kill the current buffer's process).
;; (This is not normally a command, but it is useful as one.)
(put 'kill-process 'interactive-form '(interactive))
The more complex version that I actually use is:
(put 'kill-process 'interactive-form
'(interactive
(let ((proc (get-buffer-process (current-buffer))))
(if (process-live-p proc)
(unless (yes-or-no-p (format "Kill %S? " proc))
(error "Process not killed"))
(error (format "Buffer %s has no process" (buffer-name))))
(list proc))))
If want to make markdown-back-to-heading interactive, you have a few different good options:
file a bug report to get upstream to make it so. Including a patch along with the bug-report can help speed up the process.
use an advice such as:
(advice-add 'markdown-back-to-heading :before
(lambda () (interactive "^") nil))
If instead you want to improve the interactivity of a function, e.g. if you want to support shift-selection, you can add the interactive code ^ with (interactive "^") instead of (interactive) so that Emacs knows this is a navigation command (and hence if you use it with a shifted-binding it will select the corresponding text). Here is a manual page with the list of interactive codes, and other options for interactivity at the manual page you mentioned.
Following #Stefan's suggestion, I filed a Github issue and submitted a patch, which adds the line (interactive "P") in the source code:
(defun markdown-back-to-heading (&optional invisible-ok)
"Move to previous heading line, or beg of this line if it's a heading.
Only visible heading lines are considered, unless INVISIBLE-OK is non-nil."
(interactive "P")
(markdown-move-heading-common #'outline-back-to-heading invisible-ok))
and now I can keybind it with
(define-key markdown-mode-map (kbd "C-c C-h") 'markdown-back-to-heading)
I had installed markdown-mode from MELPA, so this change required uninstalling the package, then these steps from the repo README. I forked the repo and cloned the repo locally:
git clone git#github.com:miguelmorin/markdown-mode
and added these lines to Emacs initialization:
(add-to-list 'load-path (expand-file-name "~/code/markdown-mode"))
(autoload 'markdown-mode "markdown-mode"
"Major mode for editing Markdown files" t)
(add-to-list 'auto-mode-alist '("\\.markdown\\'" . markdown-mode))
(add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))
(autoload 'gfm-mode "markdown-mode"
"Major mode for editing GitHub Flavored Markdown files" t)
(add-to-list 'auto-mode-alist '("README\\.md\\'" . gfm-mode))
(require 'markdown-mode)

Using 2 consecutive control key in Emacs [duplicate]

Let's say I bind the key to a certain function as follows:
(global-set-key (kbd "C-c =") 'function-foo)
Now, I want the key binding to work as:
After I press C-c = for the first time, if I want to repeat the function-foo, I don't need to press C-c again, but simply repeat pressing =. Then, after I call the function-foo for enough times, I can just press keys other than = (or explicitly press C-g) to quit.
How to do this?
This may be the thing you are looking for:
(defun function-foo ()
(interactive)
(do-your-thing)
(set-temporary-overlay-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "=") 'function-foo)
map)))
There's a smartrep.el package that does exactly what you need. The documentation is a bit scarce but you can get a grip of how it's supposed to be used by looking into numerous emacs configs found on github. For example (taken from here):
(require 'smartrep)
(smartrep-define-key
global-map "C-q" '(("n" . (scroll-other-window 1))
("p" . (scroll-other-window -1))
("N" . 'scroll-other-window)
("P" . (scroll-other-window '-))
("a" . (beginning-of-buffer-other-window 0))
("e" . (end-of-buffer-other-window 0))))
This is what I use. I like it because you don't have to specify the repeating key.
(require 'repeat)
(defun make-repeatable-command (cmd)
"Returns a new command that is a repeatable version of CMD.
The new command is named CMD-repeat. CMD should be a quoted
command.
This allows you to bind the command to a compound keystroke and
repeat it with just the final key. For example:
(global-set-key (kbd \"C-c a\") (make-repeatable-command 'foo))
will create a new command called foo-repeat. Typing C-c a will
just invoke foo. Typing C-c a a a will invoke foo three times,
and so on."
(fset (intern (concat (symbol-name cmd) "-repeat"))
`(lambda ,(help-function-arglist cmd) ;; arg list
,(format "A repeatable version of `%s'." (symbol-name cmd)) ;; doc string
,(interactive-form cmd) ;; interactive form
;; see also repeat-message-function
(setq last-repeatable-command ',cmd)
(repeat nil)))
(intern (concat (symbol-name cmd) "-repeat")))
You want your function-foo to use set-temporary-overlay-map.
In addition to what #juanleon suggested, which uses set-temporary-overlay-map, here is an alternative that I use quite a bit. It uses standard library repeat.el.
;; This function builds a repeatable version of its argument COMMAND.
(defun repeat-command (command)
"Repeat COMMAND."
(interactive)
(let ((repeat-previous-repeated-command command)
(last-repeatable-command 'repeat))
(repeat nil)))
Use that to define different repeatable commands. E.g.,
(defun backward-char-repeat ()
"Like `backward-char', but repeatable even on a prefix key."
(interactive)
(repeat-command 'backward-char))
Then bind such a command to a key with a repeatable suffix, e.g., C-c = (for C-c = = = =...)
See this SO post for more information.

dired: M-x find-dired: disable history?

I set (setq find-args "-iname ") so that M-x find-dired gives me ... "Run find (with args): -iname " as default. However, it seems to remember its history. Is there a way to disable the history and always start with the default argument "-iname"? I tried to modify find-args-history without success.
You have to use the function marius/find-dired each time instead of find-dired, as it is showed in answer. E.g. setup something like this (global-set-key (kbd "C-x g") 'marius/find-dired). It calls (setq find-args "-iname ...") each time before calling find-grep.
EDIT: without renaming:
(setq find-args '("-iname '**'" . 10))
(defadvice find-dired (after eab-find-dired activate)
(setq find-args '("-iname '**'" . 10)))
for deactivate:
(ad-remove-advice 'find-dired 'after 'eab-find-dired)
(ad-deactivate 'find-dired)
EDIT2: We use after-advice here, see comments.

How do I bind latexmk to one key in Emacs and have it show errors if there are any

I'm using AUCTeX and I would like to bind a key, e.g. C-0, that does the following:
Saves the active file without prompting me.
Runs latexmk on the active file without prompting me.
Shows me errors if latexmk encounters any by .
My problem is not how to bind a key (for which Tyler posted a link in a comment below) but how to come up with a function that accomplishes item 1–3.
I call Latexmk by
(add-hook 'LaTeX-mode-hook (lambda ()
(push
'("Latexmk" "latexmk %s" TeX-run-TeX nil t
:help "Run Latexmk on file")
TeX-command-list)))
This is my .latexmkrc
$pdf_mode = 1;
$recorder = 1;
$latex = 'latex -recorder -halt-on-error -interaction=nonstopmode -shell-escape';
$pdflatex = 'pdflatex -recorder -halt-on-error -interaction=nonstopmode -shell-escape';
I'm using Emacs 23.3 and AUCTeX 11.86.
Something like this?
(require 'tex-buf)
(defun run-latexmk ()
(interactive)
(let ((TeX-save-query nil)
(TeX-process-asynchronous nil)
(master-file (TeX-master-file)))
(TeX-save-document "")
(TeX-run-TeX "latexmk" "latexmk" master-file)
(if (plist-get TeX-error-report-switches (intern master-file))
(TeX-next-error t)
(minibuffer-message "latexmk done"))))
(add-hook 'LaTeX-mode-hook
(lambda () (local-set-key (kbd "C-0") #'run-latexmk)))
Edit:
TeX-save-document saves your master file and any sub-files (if you just have one file, it's your master file), and when TeX-save-query is nil, it doesn't ask you for confirmation. Then TeX-run-TeX runs latexmk using the mechanism usually used for running TeX, which includes error message parsing, but because it usually starts an asynchronous process, we set TeX-process-asynchronous to nil to wait for it to end. The odd-looking plist-get form is the documented way to check for errors from TeX-run-TeX (see comments in tex-buf.el), and if there are errors, we jump to the first one; if there are no errors, we show a message in the minibuffer just for fun.
Finally, the local-set-key is one way to bind a key to the function.
Does this do what you want?
(defun my-tex ()
"Saves the current buffer and runs LaTeX, all with no prompts or further interaction."
(interactive)
(save-buffer)
(TeX-command "LaTeX" 'TeX-master-file -1))
I don't use latexmk, but to make that work all you need to do is switch the string "LaTeX" for the name string you use for latexmk in TeX-command-list (which is probably just "latexmk" or "Latexmk").
I'm glad you asked, as this will be useful for me now!
Assuming you've already used the answer in How to call latexmk in emacs, and jump to next-error to add latexmk to the command list for AUCTeX, you can use the following function:
(defun run-latexmk ()
(interactive)
(save-buffer)
(TeX-command "Latexmk" 'TeX-master-file 0)
(if (plist-get TeX-error-report-switches (intern (TeX-master-file)))
(next-error))) ;; 0 -> suppress confirmation
And use any of the key-binding techniques to bind it to C-0; here's one that's local to the TeX mode:
(define-key TeX-mode-map (kbd "C-0") 'run-latexmk)
The run-latexmk function is based on digging through TeX-command-master, and simplifying it to your needs. Note that the call to (next-error) may not always happen, because LaTeX may get confused by your error and pause waiting for input

In Emacs, can we make one keystroke to do different command?

I want to make one keystroke, say C-F12, to do delete-other-windows or winner-undo. I think it's easy if I already learning Emacs Lisp programming, and set a boolean flag. That is, if previously it run delete-other-window, now it'll run winner-undo.
How do you do that in Emacs Lisp?
Thanks
Try something like this
(setq c-f12-winner-undo t)
(define-key (current-global-map) [C-f12]
(lambda()
(interactive)
(if c-f12-winner-undo
(winner-undo)
(delete-other-windows))
(setq c-f12-winner-undo (not c-f12-winner-undo))))
(defun swdev-toggle-sole-window ()
(interactive)
(if (cdr (window-list))
(delete-other-windows)
(winner-undo)))
(global-set-key (kbd "<C-f12>") 'swdev-toggle-sole-window)
The first line starts the declaration of a function called swdev-toggle-sole-window, taking no argument.
This function is declared as interactive, i.e. it can be called with M-x or through a key binding.
If the window list contains more than one element, i.e. if there is more than one window, …
… then delete other windows …
… else undo the window deletion.
Bind the function to the key C-f12.
Here's a solution using the approach taken by Emacs' recenter-top-bottom function:
(defun delete-other-window-or-winner-undo ()
"call delete-other-window on first invocation and winner-undo on subsequent invocations"
(interactive)
(if (eq this-command last-command)
(winner-undo)
(delete-other-windows)))
(global-set-key (kbd "<C-f12>") 'delete-other-window-or-winner-undo)