Initiating interactive regexp search programmatically - emacs

I'd like to define a command that initiates an isearch-forward-regexp with a predefined regexp.
Say I want to find all occurrences of either "aaa" or "bbb". The regexp which I can enter interactively with isearch-forward-regexp is \\(aaa\\|bbb\\)
Is there any way to do this without entering the regexp interactively? I've tried things like this:
(defun my-search ()
(interactive)
(isearch-mode t t)
(isearch-yank-string "\\(aaa\\|bbb\\)"))
but this approach doesn't seem to work because there doesn't seem to be any way to define a string in emacs that evaluates to \\(aaa\\|bbb\\) when yanked into isearch.
For instance "\\(aaa" evaluates to (aaa, but "\\\\(aaa" evaluates to \\\\(aaa. There doesn't seem to be a way to evaluate to a single backslash.
Is there a way of doing what I want?

This command should do what I think you are asking for:
(defun foo (regexp)
(interactive (list (read-regexp "Regexp: ")))
(isearch-mode t t)
(let ((isearch-regexp nil))
(isearch-yank-string regexp)))
For example: M-x foo RET, then enter \(aaa\|bbb\) RET.
If you call it from Lisp instead of interactively then just provide the regexp you want as a string. For example:
(foo "\\(aaa\\|bbb\\)")
Note that isearch-yank-string does this:
(if isearch-regexp (setq string (regexp-quote string)))
That's why foo binds isearch-regexp to nil around the call to isearch-yank-string: to prevent quoting regexp special chars in the string.

Related

How to replace a word instead of a string in emacs like this?

For example, I have the codes below:
(defun toggle-light ()
"Toggle setting tab widths between 4 and 8"
(setq a
(if (boundp 'a) a nil))
(interactive)
(if a
(progn
(load-theme 'solarized-dark t)
(setq a nil))
(progn
(load-theme 'solarized-light t)
(setq a t) )))
And now I want to refactor this blocks by replacing the variable name a with is-lighted, but without changing other character a in other words (for example, in interactive or tab).
Is there a built-in function in emacs that can finsih that job?
C-uM-% a RET is-lighted RET
The prefix argument ("delimited") to the standard query-replace functions wraps the pattern with word-boundary markers.
While phils's answer is correct and idiomatic, you should also learn about \b word boundary regular expression. Thus, equivalent regexp replace would be M-%\ba\b. See Backslash in Regular Expressions # Emacs Manual and Regular Expression # EmacsWiki.

Passing Emacs variables to minibuffer shell commands

I can run a shell command quickly by hitting M-!. One thing I'd like to do is perform shell quick operations on the current file. An example would be checking the file out through perforce:
M-! p4 edit buffer-file-name RET
(Yes there are perforce integrations, but I'm more interested in the minishell/variable problem rather than a specific workflow)
Of course, the buffer-file-name variable is not evaluated before the command is sent to the shell.
Is there an easy on-the-fly way to do this? Or will I have to roll a custom elisp function?
It seems current Emacs has something built-in to achieve the desired result, after M-! (shell-command) press <down>, you will get the file name you are currently visiting on the prompt. Now you can edit it to add the command you want to run on it.
In dired-mode it will give you the file your cursor is currently on.
Indeed using C-u M-: is almost right. I'm not so sure about using shell-quote-argument in eval-to-shell-argument since it only works on strings making it impossible to use eval-to-shell-argument to insert a number or a symbol. You could try something like:
(defun sm-minibuffer-insert-val (exp)
(interactive
(list (let ((enable-recursive-minibuffers t))
(read-from-minibuffer "Insert: "
nil read-expression-map t
'read-expression-history))))
(let ((val (with-selected-window (minibuffer-selected-window)
(eval exp)))
(standard-output (current-buffer)))
(prin1 val)))
and then bind this function in your minibuffer with (define-key minibuffer-local-map [?\M-:] 'sm-minibuffer-insert-val).
Of course, if the only thing you ever want to insert is the buffer-file-name, then your execute-shell-command-on-buffer is simpler.
I did roll my own elisp function, and it looks like this:
(defun execute-shell-command-on-buffer (shell-command-text)
(interactive "MShell command:")
(shell-command (format shell-command-text (shell-quote-argument buffer-file-name)))
)
https://gist.github.com/2367513
I bound it to M-", so now my example can be completed with:
M-"p4 edit %sRET
I won't accept this as the answer, because I did ask for solutions that don't require a function.
You can use C-u M-: (eval-expression with a universal prefix argument) to evaluate any Lisp expression and insert its value at point in the current buffer (including minibuffers, as long as you have enable-recursive-minibuffers set to a non-nil value).
In your example: C-u M-: buffer-file-name RET.
Note that the result of the expression is printed in Lisp form: that is, quoted in such a way that a subsequent call to read would construct an equal Lisp value. For strings, this means enclosing in double quotes, which will probably be interpreted as you expect by the inferior shell. However, you may run into problems with strings that contain special characters, which need different escaping by Elisp and the shell.
The more correct way uses shell-quote-argument, as in phils' solution. Here's a quick defun that reads a Lisp expression and inserts its value at point as a properly quoted shell word:
(defun eval-to-shell-argument (form)
(interactive "XEval: ")
(insert (shell-quote-argument form)))
The read-and-evaluate step happens automatically by using an "X" as the argument to interactive.
Edited to add: As #tenpn notes, the above solution doesn't work for inserting buffer-local variables like buffer-file-name in a minibuffer like the one M-! pops up (more precisely, it inserts the buffer-local value of the minibuffer, which is unlikely to be useful). Here is a revised version which seems to work. If the minibuffer is active, it makes the buffer of the previously-selected window temporarily active while reading and evaluating an expression.
Final edit: From #Stefan's answer I see that I should have used (minibuffer-selected-window) to find the previously-selected window. I've also added a (format "%s" ..) to allow inserting non-string values, while still quoting special characters in strings. Here's the final version:
(defun eval-to-shell-argument ()
(interactive)
(let* ((buffer
(if (minibufferp)
(window-buffer (minibuffer-selected-window))
(current-buffer)))
(result
(with-current-buffer buffer
(eval-minibuffer "Eval: "))))
(insert (shell-quote-argument (format "%s" result)))))
You can't do that with M-!, but you can evaluate arbitrary elisp from the minibuffer, so writing a function isn't strictly necessary:
M-: (shell-command (format "p4 edit %s" (shell-quote-argument buffer-file-name))) RET
In this case however, I think eshell is what you want to use:
M-x eshell-command RET p4 edit (eval buffer-file-name) RET
Edit: Except unfortunately that doesn't work, as the *eshell cmd* buffer is selected when that is evaluated. One solution would be:
M-x eshell-command RET p4 edit (eval buffer-file-name (other-buffer nil t)) RET
(Not quite as elegant, sorry.)
Everyone seems to be rolling their own version, so here's mine -- it will substitue the current filename or marked dired-files or current dired file wherever a % is in the shell command. It follows the same conventions as M-! so I bind it to that.
(defun my-shell-command (command &optional output-buffer error-buffer)
"Run a shell command with the current file (or marked dired files).
In the shell command, the file(s) will be substituted wherever a '%' is."
(interactive (list (read-from-minibuffer "Shell command: "
nil nil nil 'shell-command-history)
current-prefix-arg
shell-command-default-error-buffer))
(cond ((buffer-file-name)
(setq command (replace-regexp-in-string "%" (buffer-file-name) command nil t)))
((and (equal major-mode 'dired-mode) (save-excursion (dired-move-to-filename)))
(setq command (replace-regexp-in-string "%" (mapconcat 'identity (dired-get-marked-files) " ") command nil t))))
(shell-command command output-buffer error-buffer))

In Emacs can you evaluate an Emacs Lisp expression and replace it with the result?

For example if I have the text:
Sum of items is (+ 1 2 3)
I want to move to the end of the line, evaluate the expression and replace it with the result, so that it reads:
Sum of items is 6
With the cursor at the end of the line, C-u C-x C-e will insert the value of the preceding parenthesized expression into the buffer. You could do that, then manually back up and delete the original expression. If that's too much work, here's a command that evaluates the preceding expression and replaces it with its value:
(defun replace-last-sexp ()
(interactive)
(let ((value (eval (preceding-sexp))))
(kill-sexp -1)
(insert (format "%S" value))))
Related to this, you might like Luke Gorrie's "lively.el", which provides live replacement of emacs lisp expressions within a text buffer. It's a neat hack.
I was having a go at a solution for this when I came across one in a Google search result.
(defun fc-eval-and-replace ()
"Replace the preceding sexp with its value."
(interactive)
(backward-kill-sexp)
(prin1 (eval (read (current-kill 0)))
(current-buffer)))
http://emacs.wordpress.com/2007/01/17/eval-and-replace-anywhere/
replace-regex functions can execute lisp to generate the replacements.
In the trivial instance where the sexp in question is on a single line, and is the only thing containing parenthesis, then you could match "(.+)" and replace with "\,(eval (read \&))".
If you are using emacs starter kit by technomancy there is "esk-eval-and-replace" function which evaluates the elisp sexp and replace them. Its bind to C-c e by default.
look to the function eval-print-last-sexp, you can build something using it
My emacs-fu isn't so strong, so I don't know if there's a single command to do this, but you can make yourself a (somewhat fragile) macro for it ... drop these lines in your .emacs:
(fset 'eval-sexp-in-place
[?\M-x ?e ?v ?a ?l ?- ?p ?r ?i ?n tab return ?\M-^ ?\M-^ ?\C-\M-b ?\C-\M-k ?\C-d])
(global-set-key [(control x) (control a)] 'eval-sexp-in-place)
This works fine, but there's one issue with it: you need to be at the end of the sexp (i.e. after the last right paren) to get it to work.
Also, I picked a random unbound key (C-x C-a) -- feel free to change that to something more to your liking.

Emacs rgrep customization

I have the following custom function in ~/.emacs:
(defun xi-rgrep (term)
(grep-compute-defaults)
(interactive "sSearch Term: ")
(rgrep term "*.[ch]*" "../"))
This function just runs rgrep for the term entered in the files/directories I'm interested in. However, I want to match the original rgrep functionality of having the default search term be the word at the point (I think that's the term?). How do I achieve this? I've tried several things, including running (grep-read-regexp) but haven't been successful.
You can use the 'thingatpt package like so:
(require 'thingatpt)
(defun xi-rgrep (term)
(interactive (list (completing-read "Search Term: " nil nil nil (thing-at-point 'word))))
(grep-compute-defaults)
(rgrep term "*.[ch]*" "../"))
Here is another way which does not require the 'thingatpt package and uses (grep-read-regexp):
(defun xi-rgrep ()
(interactive)
(grep-compute-defaults)
(rgrep (grep-read-regexp) "*.[ch]*" "../"))
I prefer this as 'thingatpt requires setting boundaries if you want to rgrep words with symbols, such as underscores, which is often the case for variables.

Emacs Elisp dynamic interactive prompt

I am trying to have a dynamic prompt from my elisp function. I want something like replace-regexp where it will show you the last regexp entered. I tried
(interactive
(concat "sab" "bab")))
that doesnt work!
I also tried message like format
(interactive "s %s" last-used-regexp)
and that doesn't work!
Anyone know how to do this?
Thank you!
M-x find-function is your friend. It will tell you how anything in emacs works by showing you the source code. Using it, I find that query-regexp-replace calls query-replace-read-args which calls query-replace-read-from which calls read-from-minibuffer using a prompt created from the last used regexp, which is saved in the dotted pair query-replace-defaults.
So:
(defun my-func ()
"Do stuff..."
(interactive)
(read-from-minibuffer "Regexp? " (first query-replace-defaults)))
is a command that throws up a prompt with the last entered regexp as the default.
Use a variable for input history, and interactive with a list:
(defvar my-func-history nil)
(defun my-func (str)
(interactive (list (read-from-minibuffer "Input string: " (car my-func-history) nil nil 'my-func-history)))
(insert str))
If you don't want the last value entered in there initially, change the (car my-func-history) to nil. You can of course up/down arrow to go through the history at the prompt.