How to make describe-function "C-h f" case-insensitive by default - emacs

When searching for a function whose name I partly remember, I use C-h f to call describe-function, enter *part-of-function-name, and hit TAB. But I now realize that this search is not case-insensitive.
For example:
C-h f info TAB
lists all functions starting with info, but doesn't include those starting with Info, whereas
C-h f Info TAB
lists all functions starting with Info, but doesn't include those starting with info.
Another example:
C-h f *nfc TAB
gives me *nfc [No match], whereas
C-h f *NFC TAB
gives me ucs-normalize-HFS-NFC-region.
How can I make describe-function case-insensitive by default, using some configuration in my init.el file?

Add a binding of completion-ignore-case to t in the interactive spec of the command. This has the advantages that (a) it affects only describe-function (C-h f) and (b) you can easily toggle it on/off (as with any Emacs advice).
(defadvice describe-function (before ignore-case activate)
"Make it case-insensitive."
(interactive
(let ((completion-ignore-case t) ; <============= ADDED BINDING
(fn (function-called-at-point))
(enable-recursive-minibuffers t)
val)
(setq val (completing-read
(if fn
(format "Describe function (default %s): " fn)
"Describe function: ")
obarray 'fboundp t nil nil (and fn (symbol-name fn))))
(list (if (equal val "") fn (intern val))))))

(setq completion-ignore-case t) should do what you want, tho globally rather than only for C-h f.

Here's a custom function that I use in place of describe-function.
It uses ido completion.
(defvar functions-cache nil)
;;;###autoload
(defun refresh-functions-cache ()
(interactive)
(setq functions-cache nil)
(mapatoms (lambda (symbol)
(when (fboundp symbol)
(push (symbol-name symbol) functions-cache))))
(setq functions-cache (sort functions-cache #'string<)))
;;;###autoload
(defun describe-function-ex (function)
"Display the full documentation of FUNCTION (a symbol)."
(interactive
(let ((fn (function-called-at-point))
(enable-recursive-minibuffers t)
val)
(unless functions-cache
(refresh-functions-cache))
(setq val (ido-completing-read
(if fn
(format "Describe function (default %s): " fn)
"Describe function: ")
functions-cache
nil t nil nil
(and fn (symbol-name fn))))
(list (if (equal val "")
fn (intern val)))))
(if (null function)
(message "You didn't specify a function")
(help-setup-xref (list #'describe-function function)
(called-interactively-p 'interactive))
(save-excursion
(with-help-window (help-buffer)
(prin1 function)
(princ " is ")
(describe-function-1 function)
(with-current-buffer standard-output
;; Return the text we displayed.
(buffer-string))))))

Related

Emacs jump to next annotated words or phrases

When using Emacs, I notice that words or phrases in a buffer can be annotated or highlighted by many minor modes like hi-lock-mode, flyspell-mode, flycheck-mode...
Is there any uniform way to jump to the highlighted words or phrases created by all these minor modes? Specifically, is there any package or function support jumping to the next and previous highlighted phrases?
When using Eclipse, I can do it by pressing Ctrl-. and Ctrl-,. However, when switching to Emacs, so far, I haven't found an equivalent feature.
Developing a mode which aims to tackle that kind of tasks
https://github.com/andreas-roehler/werkstatt/tree/master/general-key
Facilitates the setting of a general command.
Than this command gets different bindings according to modes - which needs to be edited by hand once. Afterwards it allows to set/change a key at one place for all related/bound commands.
See for example inside
https://github.com/andreas-roehler/werkstatt/blob/master/general-key/general-key-python-mode.el
It's alpha still notably for the install process. Bug reports resp. feature requests welcome.
Not surprisingly, #Drew has answered something related to this.
You can programmatically use isearch with something like:
(defun foo (regexp)
(interactive (list (read-regexp "Regexp: ")))
(isearch-mode t t)
(let ((isearch-regexp nil))
(isearch-yank-string regexp)))
This will pull your previous regexp history, including those from hi-lock. I imagine it would be a fun exercise to modify this to use hi-lock-regexp-history.
If you use swiper, you can restrict the search candidates to lines with highlighted patterns by hi-lock-mode.
Here is a simple wrapper of swiper:
(require 'cl-lib)
(defun swiper-over-highlights-simple ()
(interactive)
(let ((original-swiper--candidates (symbol-function 'swiper--candidates)))
(cl-letf (((symbol-function 'swiper--candidates)
(lambda ()
(let ((pattern (mapconcat #'car hi-lock-interactive-patterns "\\|")))
(cl-remove-if-not (lambda (x) (string-match-p pattern x))
(funcall original-swiper--candidates))))))
(swiper))))
In addition, you can change ivy-read's preselect argument, which initializes the first matched line inside swiper.
The following fuction, modified from swiper, finds the closest next line with a highlighted pattern:
(defun swiper-over-highlights (&optional initial-input)
(interactive)
(let ((original-swiper--candidates (symbol-function 'swiper--candidates))
(pattern (mapconcat #'car hi-lock-interactive-patterns "\\|")))
(cl-letf (((symbol-function 'swiper--candidates)
(lambda ()
(cl-remove-if-not (lambda (x) (string-match-p pattern x))
(funcall original-swiper--candidates)))))
(let ((candidates (swiper--candidates)))
(swiper--init)
(setq swiper-invocation-face
(plist-get (text-properties-at (point)) 'face))
(let ((preselect
(save-excursion
(search-forward-regexp pattern nil t)
(let* ((current-line-value (current-line))
(candidate-line-numbers (mapcar (lambda (x) (cadr (text-properties-at 0 x)))
candidates))
(preselect-line-num (cl-find-if (lambda (x) (<= current-line-value x))
candidate-line-numbers)))
(- (length candidate-line-numbers)
(length (member preselect-line-num candidate-line-numbers))))))
(minibuffer-allow-text-properties t)
res)
(unwind-protect
(and
(setq res
(ivy-read
"Swiper: "
candidates
:initial-input initial-input
:keymap swiper-map
:preselect preselect
:require-match t
:action #'swiper--action
:re-builder #'swiper--re-builder
:history 'swiper-history
:extra-props (list :fname (buffer-file-name))
:caller 'swiper))
(point))
(unless (or res swiper-stay-on-quit)
(goto-char swiper--opoint))
(isearch-clean-overlays)
(unless (or res (string= ivy-text ""))
(cl-pushnew ivy-text swiper-history))
(setq swiper--current-window-start nil)
(when swiper--reveal-mode
(reveal-mode 1))))))))

Emacs metaprogramming, dynamically define methods

I am trying to define some helper functions to quickly jump to different projects from within emacs. I started by defining a macro as follows
(defmacro project-alias (name path)
`(defun ,name ()
(interactive)
(cd ,path)))
And this works great I can (project-alias foo "~/bar") no problem. The problem comes when I try and apply this macro over a list of tuples.
(setq projects '((foo . "~/foo")
(bar . "~/bar")))
(dolist (p projects)
(project-alias (car p) (cdr p)))
The above code errors with
Debugger entered--Lisp error: (wrong-type-argument symbolp (car p))
defalias((car p) (lambda nil (interactive) (cd (cdr p))))
I have tried passing the first argument in as a string and calling intern to get the symbol representation out with no joy, and I've also tried defining my macro to accept the string form and that doesn't work either
What am I doing wrong?
If your use of the macro involves evaluating sexps to produce the name and path, then it needs to evaluate the sexps:
(defmacro project-alias (name path)
`(defun ,(eval name) () (interactive) (cd ,(eval path))))
Alternatively, use a function:
(defun project-alias (name path)
(eval `(defun ,name () (interactive) (cd ,path))))
You could do either
(defun project-alias-f (name path)
(eval `(defun ,name ()
(interactive)
(cd ,path))))
(dolist (p projects)
(project-alias-f (car p) (cdr p)))
or
(dolist (p projects)
(eval `(project-alias ,(car p) ,(cdr p))))
Macro arguments are passed un-evaluated. (Macros could not otherwise do what they can do.)
So your arguments are literally the forms (car p) and (cdr p) (as opposed to, for instance, foo and "~/foo").
Here's another take on it, with no macros nor eval:
;; -*- lexical-binding:t -*-
(defun project-alias-f (name filename)
(defalias name (lambda () (interactive) (cd filename)))
(dolist (p projects)
(project-alias-f (car p) (cdr p)))
This is not an answer to your macro problem, but an alternative solution to your desire to jump between projects.
In my init.el file, I have (amongst other things)
(set-register ?A '(file . "~/.aliases"))
(set-register ?E '(file . "~/.emacs.d/init.el"))
(set-register ?H '(file . "~/.hgrc"))
(set-register ?T '(file . "~/.TODO.org"))
Then I can use jump-to-register (C-x r j) to jump to one of these files when I wish to edit the file (or do something with one of the unlisted projects). Because a file/folder is stored in the register (rather than a window config say), emacs will open the file or folder it finds in the register.

Emacs: swapping replace queries

Using query-replace, the minibuffer says this (having saved the previous arguments):
Query replace (default FROM -> TO)
is there a command to swap the args? To get this:
Query replace (default TO -> FROM)
AFAIK, nothing out of the box does that for you. But IMHO you don't need that.
All you need to do is use M-p. Use it once to get the last TO you used. Then repeat M-p a couple times to get the last FROM you used. Very quick.
After that, you can use C-x ESC ESC (or C-x M-: or C-x M-ESC), possibly followed by M-p, to repeat either combination (TO -> FROM or FROM -> TO).
(defun swap-query-replace-defaults ()
"Swap the initial expressions offered by `query-replace'. "
(interactive)
(let* ((erg query-replace-defaults)
(first (car erg))
(second (cdr erg)))
(setq query-replace-defaults (cons second first))
(when (interactive-p) (message "%s" query-replace-defaults))
query-replace-defaults))
Made a feature-request:
http://lists.gnu.org/archive/html/bug-gnu-emacs/2013-10/msg00102.html
There's a shortcut to swap the args: M-p RET M-p M-p RET
I use this:
;; Redefine `query-replace-read-from' to add a custom keymap when
;; replacing strings. Now, C-u ENTER does the reverse suggested
;; replacement.
(defvar query-replace-keymap
(let ((map (make-sparse-keymap)))
(set-keymap-parent map minibuffer-local-map)
(define-key map [remap exit-minibuffer]
(lambda ()
(interactive)
(if (and current-prefix-arg query-replace-defaults)
(setq query-replace-defaults
(cons
(cdr query-replace-defaults)
(car query-replace-defaults))))
(exit-minibuffer)))
map))
(defun query-replace-read-from (prompt regexp-flag)
"Query and return the `from' argument of a query-replace operation.
The return value can also be a pair (FROM . TO) indicating that the user
wants to replace FROM with TO."
(if query-replace-interactive
(car (if regexp-flag regexp-search-ring search-ring))
(let* ((history-add-new-input nil)
(query-replace-defaults query-replace-defaults)
(prompt
(if query-replace-defaults
(format "%s (default %s -> %s): " prompt
(query-replace-descr (car query-replace-defaults))
(query-replace-descr (cdr query-replace-defaults)))
(format "%s: " prompt)))
(from
;; The save-excursion here is in case the user marks and copies
;; a region in order to specify the minibuffer input.
;; That should not clobber the region for the query-replace itself.
(save-excursion
(if regexp-flag
(read-regexp prompt nil query-replace-from-history-variable)
(read-from-minibuffer
prompt nil query-replace-keymap nil query-replace-from-history-variable
(car (if regexp-flag regexp-search-ring search-ring)) t)))))
(if (and (zerop (length from)) query-replace-defaults)
(cons (car query-replace-defaults)
(query-replace-compile-replacement
(cdr query-replace-defaults) regexp-flag))
(add-to-history query-replace-from-history-variable from nil t)
;; Warn if user types \n or \t, but don't reject the input.
(and regexp-flag
(string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\(\\\\[nt]\\)" from)
(let ((match (match-string 3 from)))
(cond
((string= match "\\n")
(message "Note: `\\n' here doesn't match a newline; to do that, type C-q C-j instead"))
((string= match "\\t")
(message "Note: `\\t' here doesn't match a tab; to do that, just type TAB")))
(sit-for 2)))
from))))

Shortcut for inserting environments in `org-mode`

I'm using org-mode for organizing myself (very useful so far!). However, it is kind of annoying writting
#+begin_comment
...
#+end_comment
each time I'd like to insert an environment.
Question
Is there a shortcut to insert the #+begin_ and #+end_ for a given environment?
In the same way C-c C-o comment RET would insert
\begin{comment}
\end{comment}
in latex-mode.
Org has a facility called "Easy templates": http://orgmode.org/manual/Easy-Templates.html
A template for comment is missing but you can add it with:
(add-to-list 'org-structure-template-alist '("C" "#+begin_comment\n?\n#+end_comment"))
And use it by typing <C followed by TAB.
Alternatively, you could use yasnippet.
Now the corresponding template section is called Structure Template and the insertion sequence is invoked by C-c C-,. I didn't (require 'org-tempo) which is described to support insertion keys like <s TAB.
The comment environment is already defined in org-structure-template-alist. So the comment would be inserted by
C-c C-, C
It's still possible to add a user defined sequence by, for example,
C-c C-, [TAB|RET|SPC] src python :results output :session
delivering
#+begin_src python :results output :session
#+end_src
(emacs 25.2.2, org-mode 9.2)
You could have a look at "org-auctex-keys.el", a minor mode which I created to offer AUCTeX key bindings within Org documents.
In this case, you'd use C-c C-e to insert an environment (prompt to enter the environment name), as what AUCTeX does.
If you're interested, check it out at https://github.com/fniessen/org-auctex-key-bindings.
Not as elegant as the answer of Michael Markert but maybe more expandable.
1) You can select a region and put the block around it or you can just put the block at point.
2) Keyword expansion and history.
3) Keystrokes: C-c b
The command could be further expanded. E.g., for the src block the various switches like -n -r and export to files could be supported.
(defun list-major-modes ()
"Returns list of potential major mode names (without the final -mode).
Note, that this is guess work."
(interactive)
(let (l)
(mapatoms #'(lambda (f) (and
(commandp f)
(string-match "-mode$" (symbol-name f))
;; auto-loaded
(or (and (autoloadp (symbol-function f))
(let ((doc (documentation f)))
(when doc
(and
(let ((docSplit (help-split-fundoc doc f)))
(and docSplit ;; car is argument list
(null (cdr (read (car docSplit)))))) ;; major mode starters have no arguments
(if (string-match "[mM]inor" doc) ;; If the doc contains "minor"...
(string-match "[mM]ajor" doc) ;; it should also contain "major".
t) ;; else we cannot decide therefrom
))))
(null (help-function-arglist f)))
(setq l (cons (substring (symbol-name f) 0 -5) l)))))
(when (called-interactively-p 'any)
(with-current-buffer (get-buffer-create "*Major Modes*")
(clear-buffer-delete)
(let ((standard-output (current-buffer)))
(display-completion-list l)
(display-buffer (current-buffer)))))
l))
(defvar org-insert-block-hist nil
"History for command `org-insert-block'")
(defvar org-insert-block-hist/src:major nil
"History for major mode in org src blocks.")
(defvar org-insert-block-list (append org-protecting-blocks
'("comment" ""))
"List of block types offered as completion for command `org-insert-block'")
;; block_src switches: -n () -r (references) -l "((%s))" (label format) -k (keep labels)
(defvar org-insert-block-list-specials
"Assoc list of Commands for reading additional specification of org-blocks.")
(setq org-insert-block-list-specials
'(("src" . (concat " " (completing-read "Major mode:"
(list-major-modes)
nil nil
(car org-insert-block-hist/src:major)
'(org-insert-block-hist/src:major . 1)
)))))
(defun org-insert-block (bl &optional b e attributes)
"Put region between b and e into org-block of kind bl.
If b or e is nil then put org-block limiters around point.
The string attributes is inserted behind the string #+begin_... "
(interactive
(let ((usereg (use-region-p))
(blKind (completing-read "Input block kind (tab: completion, uparrow: history):"
org-insert-block-list nil nil (car org-insert-block-hist) '(org-insert-block-hist . 1))))
(list
blKind
(when usereg (region-beginning))
(when usereg (region-end))
(let ((spec (assoc blKind org-insert-block-list-specials)))
(when spec (eval (cdr spec)))
))))
(let ((begBlock (concat "\n#+begin_" bl attributes "\n"))
(endBlock (concat "\n#+end_" bl "\n")))
(if (and b e)
(save-restriction
(narrow-to-region b e)
(goto-char (point-min))
(insert begBlock)
(goto-char (point-max))
(insert endBlock)
(indent-region (point-min) (point-max)))
(let ((p (point)))
(insert endBlock)
(goto-char p)
(insert begBlock))
)))
(add-hook 'org-mode-hook '(lambda ()
(local-set-key (kbd "C-c b") 'org-insert-block)))

flet works, but with obsolete message; cl-flet does not work

I'm trying to temporarily turn off the yes-or-no-p within a function that is defined elsewhere and then restore things to the way they were. Using flet works, but creates a *compile-log* buffer telling me that it is obsolete and to use cl-flet instead. However, cl-flet doesn't seem to work with this attempt at defadvice -- i.e., nothing happens and the yes-or-no-p remains active. Any ideas on how to avoid the error message and make this work also?
(defun function-without-confirmation ()
(defadvice elmo-dop-queue-flush (around stfu activate)
(flet ((yes-or-no-p (&rest args) t)
(y-or-n-p (&rest args) t))
ad-do-it))
. . . .
(ad-unadvise 'elmo-dop-queue-flush)
)
I cannot take credit for the answer, because that was solved by wvxvw, so I'll put the relevant fix underneath the original question. The new macro is called lawlist-flet instad of flet, and the obsolete line has been commented out:
(defmacro lawlist-flet (bindings &rest body)
"Make temporary overriding function definitions.
This is an analogue of a dynamically scoped `let' that operates on the function
cell of FUNCs rather than their value cell.
If you want the Common-Lisp style of `flet', you should use `cl-flet'.
The FORMs are evaluated with the specified function definitions in place,
then the definitions are undone (the FUNCs go back to their previous
definitions, or lack thereof).
\(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
(declare (indent 1) (debug cl-flet)
;; (obsolete "use either `cl-flet' or `cl-letf'." "24.3")
)
`(letf ,(mapcar
(lambda (x)
(if (or (and (fboundp (car x))
(eq (car-safe (symbol-function (car x))) 'macro))
(cdr (assq (car x) macroexpand-all-environment)))
(error "Use `labels', not `flet', to rebind macro names"))
(let ((func `(cl-function
(lambda ,(cadr x)
(cl-block ,(car x) ,#(cddr x))))))
(when (cl--compiling-file)
;; Bug#411. It would be nice to fix this.
(and (get (car x) 'byte-compile)
(error "Byte-compiling a redefinition of `%s' \
will not work - use `labels' instead" (symbol-name (car x))))
;; FIXME This affects the rest of the file, when it
;; should be restricted to the flet body.
(and (boundp 'byte-compile-function-environment)
(push (cons (car x) (eval func))
byte-compile-function-environment)))
(list `(symbol-function ',(car x)) func)))
bindings)
,#body))
And, here is the modified function that eliminates the error message relating to flet being obsolete.
(defun function-without-confirmation ()
(defadvice elmo-dop-queue-flush (around stfu activate)
(lawlist-flet ((yes-or-no-p (&rest args) t)
(y-or-n-p (&rest args) t))
ad-do-it))
. . . .
(ad-unadvise 'elmo-dop-queue-flush)
Here's how I'd recommend you do it:
(defvar stfu-inhibit-yonp nil)
(defadvice yes-or-no-p (around stfu activate)
(if stfu-inhibit-yonp (setq ad-return t) ad-do-it))
(defadvice y-or-n-p (around stfu activate)
(if stfu-inhibit-yonp (setq ad-return t) ad-do-it))
(defadvice elmo-dop-queue-flush (around stfu activate)
(let ((stfu-inhibit-yonp t))
ad-do-it))
Contrary to CL's flet this will make it clear (e.g. in C-h f yes-or-no-p) that something's going on with yes-or-no-p.