Is there a apply-function-to-region-lines in emacs? - function

A lot of my work involves searching and deleting unnecessary lines of code. So I create a macro, and then select all lines (C-x h) and then run the command (apply-macro-to-region-lines). I managed to save that command and placed it in my .emacs file; I called it cut_it_now. But now my function is not a macro anymore, so I can't use the (apply-macro-to-region-lines) function anymore.
Do you know if there is (apply-function-to-region-lines) implemented somewhere?
Many thanks,
D

The following function should do what you want:
(defun apply-function-to-region-lines (fn)
(interactive "aFunction to apply to lines in region: ")
(save-excursion
(goto-char (region-end))
(let ((end-marker (copy-marker (point-marker)))
next-line-marker)
(goto-char (region-beginning))
(if (not (bolp))
(forward-line 1))
(setq next-line-marker (point-marker))
(while (< next-line-marker end-marker)
(let ((start nil)
(end nil))
(goto-char next-line-marker)
(save-excursion
(setq start (point))
(forward-line 1)
(set-marker next-line-marker (point))
(setq end (point)))
(save-excursion
(let ((mark-active nil))
(narrow-to-region start end)
(funcall fn)
(widen)))))
(set-marker end-marker nil)
(set-marker next-line-marker nil))))
So, if you have the following function that you want to apply against lines in a buffer:
(defun test()
(insert "> "))
And, if your buffer contains the following contents:
Line 1: blah, blah
Line 2: blah, blah
Line 3: blah, blah
Line 4: blah, blah
If you select a region enclosing just lines 2 & 3, enter "M-x apply-function-to-region-lines", and enter "test" as the function name when prompted, you will get the following result in your buffer:
Line 1: blah, blah
> Line 2: blah, blah
> Line 3: blah, blah
Line 4: blah, blah

Note that you can still use apply-macro-to-region-lines with a macro generated from code, provided the macro is defined as a vector or string. With a custom apply-named-macro-to-region-lines[2], you can select the macro to use interactively.
Emacs has two ways of generating code from a keyboard macro, depending upon the method used to name it.
If you use kmacro-name-last-macro (bound to C-xC-kn), then Emacs generates a function from the macro, which is not directly useful for this particular purpose [1].
If you use name-last-kbd-macro to name your macro, it will be generated as a vector or string.
In either case, you then use insert-kbd-macro to obtain the code.
In fact the vector/string format is the default, so you could bypass the naming step and immediately ask for the code (typing RET at the name prompt to indicate the most recently-defined macro), and then manually edit the default name of the inserted code.
[1]: The vector form does appear to simply be embedded in the function definition, so you should be able to extract that from the code to manually re-define a macro function in vector format.
[2]: When I originally wrote this reply, I'd forgotten that this was a custom function. Sorry about that.
(defun apply-named-macro-to-region-lines (top bottom)
"Apply named keyboard macro to all lines in the region."
(interactive "r")
(let ((macro (intern
(completing-read "kbd macro (name): "
obarray
(lambda (elt)
(and (fboundp elt)
(or (stringp (symbol-function elt))
(vectorp (symbol-function elt))
(get elt 'kmacro))))
t))))
(apply-macro-to-region-lines top bottom macro)))

A simple solution is to define a macro that calls your function then use the good ol' apply-macro-to-region-lines.
Apart from that, I think that you could write a loop in a few lines of elisp that does exactly what you ask for. If you would like to be fancy, you can even prompt the user for the name of the function. I think this is a good exercise for elisp, I can help you with some pointers if you feel like you would like to try it yourself.

I agree with #Lindydancer's answer, and I'd also add that there might be an easier way to accomplish your goal. e.g. the built-in function delete-matching-lines. :-)

You could always copy the source to apply-macro-to-region-lines and tweak it to call a passed in function, and thus make your own version.

Related

ELISP interactive function with both prefix argument and user input as optional arguments

In ELISP, the documentation for interactive codes mentions:
P -- Prefix arg in raw form. Does not do I/O.
...
s -- Arbitrary text, read in the minibuffer and returned as a string ... Prompt.
I presumed that I could write a function with an optional prefix argument, as in:
(defun some-function (&optional prefix)
(interactive "P")
...
)
or a function with user input, as in:
(defun some-function (user-argument)
(interactive "sProvide an argument: ")
...
)
but not both. Then I found the Org-mode function org-match-sparse-tree, which I can call with C-u C-c \, where the prefix argument restricts the match to open org-mode headings and I am still prompted for a match. The source code is below and I cannot find how the variable match is assigned:
(defun org-match-sparse-tree (&optional todo-only match)
"..."
(interactive "P")
(org-agenda-prepare-buffers (list (current-buffer)))
(let ((org--matcher-tags-todo-only todo-only))
(org-scan-tags 'sparse-tree (cdr (org-make-tags-matcher match))
org--matcher-tags-todo-only)))
How does this function take both prefix argument and user input?
How does this function [interactively] take both prefix argument and user input?
It doesn't -- the match argument is not obtained, and is therefore nil. What you're seeing is the effect of the subsequent call to (org-make-tags-matcher match) with that nil value as the argument:
(defun org-make-tags-matcher (match)
"..."
(unless match
;; Get a new match request, with completion against the global
;; tags table and the local tags in current buffer.
(let ((org-last-tags-completion-table
(org-tag-add-to-alist
(org-get-buffer-tags)
(org-global-tags-completion-table))))
(setq match
(completing-read
"Match: "
'org-tags-completion-function nil nil nil 'org-tags-history))))
...)
Functions can take multiple interactive arguments, though.
See C-hf interactive
To pass several arguments to the command, concatenate the individual strings, separating them by newline characters.
The very first example in that help demonstrates this:
(defun foo (arg buf) "Doc string" (interactive "P\nbbuffer: ") .... )
This is elaborated upon at (elisp)Using Interactive -- up one level in the documentation you'd linked to:
It may be a string; its contents are a sequence of elements
separated by newlines, one for each argument(1). Each element
consists of a code character (*note Interactive Codes::) optionally
followed by a prompt (which some code characters use and some
ignore). Here is an example:
(interactive "P\nbFrobnicate buffer: ")
The code letter ‘P’ sets the command’s first argument to the raw
command prefix (*note Prefix Command Arguments::). ‘bFrobnicate
buffer: ’ prompts the user with ‘Frobnicate buffer: ’ to enter the
name of an existing buffer, which becomes the second and final
argument.
You should read that documentation fully, though -- there are more sophisticated things you can do, including writing arbitrary elisp to produce the interactive arguments (which may or may not involve prompting the user).

How to execute a normal mode command in a vim function?

I am writing a vim function to insert some text in a c++ file, please see the following function:
function! InsertDebugInfo()
let i = line('.')
call append(i+1, '#ifdef DEBUG')
call append(i+2, 'std::cout << "" << std::endl;')
call append(i+3, '#endif')
call append(i+4, '')
call cursor(i+3, 0)
endfunction
In normal mode, I use == to re-indent one code line. My question is
how to call == in the above function. Furthermore, how to execute the
command such as 2f" which move the cursor to the second ".
To indent, you can just use
normal ==
To find also you can use
normal 2f"
or even shorter
norm <whatever you do in normal mode>
Now you might be getting what I'm trying to say.
If not, read documentation :h normal.
Try this in your function:
execute 'normal 2f"'

How to bind F1-F12 key as keyboard macro in Emacs?

I want to bind F1-F12 key as keyboard macro. Starting kbd-macro with Shift-[F1-F12] and execute it with [F1-F12]. Each key can have different macro. Is there any way to do this?
Try this bit of code:
(mapc (lambda(x) (global-set-key x 'auto-name-macro))
'([f5] [f6] [f7] [f8]))
(defun auto-name-macro (arg)
(interactive "p")
(if defining-kbd-macro
(progn
(kmacro-end-or-call-macro arg)
(fset
(intern (format "mcr-%s" last-command-event))
last-kbd-macro))
(execute-kbd-macro
(intern
(format "mcr-%s" last-command-event)))))
You start macro definitions with f3 as before, but now
f5, f6, f7 and f8 function in the same
way as f4, except each remembers their own macro.
You finish definition with the key and then call it again with the same key. Exactly like f4.
Macros also get names, e.g. mcr-f5, mcr-f6, ..., so you can call them with M-x instead.
UPD: macros can reference each-other and be bound to any key
There's more than a few lines of code so I've put it at https://github.com/abo-abo/centimacro.
The setup is just
(require 'centimacro)
f5 will call centi-assign.
It prompts you where you'd like your next binding to be, so you press f6,
for instance.
The macro is now recording, and pressing f6 will stop it and assign
the new macro to f6.
Now you can use what you defined in f6 for other macro, say f7, but it could be C-e, it's not restricted to functional keys.
Here's an example:
<f5><f6>foo<f6> ;; Now <f6> inserts "foo".
<f5><f7><f6>bar<f7> ;; Now <f7> inserts "foobar".
<f5><f8><f6>-<f7>-<f6><f8> ;; Now <f8> inserts "foo-foobar-foo".
<f5><f6>omg<f6> ;; Now <f6> inserts "omg",
;; <f7> - "omgbar",
;; <f8> - "omgbar-omg-omg".
Well assigning a macro to a key is trivial. Just record it as usual, then type:
C-xC-kb
I'd also suggest that you don't want to waste 12 useful bindings on "record a macro" when one (pre-existing) binding will do, so you may prefer to adapt to this approach rather than pursuing the original request.
Lastly, note that F5-F9 are all reserved for the end user, but other function keys are not, and already have useful bindings (including keys for recording keyboard macros, funnily enough), so I would focus on those. (If you're running out, you can always make one or more of them a prefix binding.)
I don't think that you can do this exctly as you specified, because any function you write to help with this has to have (start-kbd-macro) as the last call in it - that's the way that start-kbd-macro works. This prevents it from naming the keyboard macro after the user finishes recording it.
The only way I can see to make something similar would be to have shift-F1 be the key that you use after you finish recording the macro that is to be stored in F1.
The user would have to start recording a kbd macro the usual way, but hit shift F1 after he completes it. You could then easily put a function on shift-F1 that renames the macro to the function that you have bound to F1.
The code would be something like this:
(defun assign-macro-to-f1 () (interactive)
(name-last-kbd-macro 'f1-kbd-macro)
(global-set-key[(f1)] (execute-kbd-macro `f1-kbd-macro))
)
(global-set-key [(shift f1)] `assign-macro-to-f1)
(note - I tried also ending the kbd macro in the shift-f1 function, but it seems like messing around with kbd macros in functions is problematic ... better to let them record the macro the normal way, and save it with this function)
Here is a solution I have used:
After recording the macro, name it using C-xC-kn.
Then you can use M-xinsert-kbd-macro and give it the name of the macro you just defined. That will insert some lisp code which defines the macro. You can then put the generated lisp code in your init.el file, followed by a global-set-key to set the macro to whatever key you want.
Here's a sample of the generated lisp and keybinding (the macro just enters the word "test"):
(fset 'test-macro
(lambda (&optional arg) "Keyboard macro." (interactive "p")
(kmacro-exec-ring-item (quote ([116 101 115 116 41 backspace] 0 "%d")) arg)))
(global-set-key '[(f5)] 'test-macro)

Emacs function automaticly accepting prompt

I am trying to find a way to automatically accept the first proposal from the minibuffer.
(defun find-file-at-point-without-prompt ()
(interactive )
(find-file-at-point)
)
Calling results in the prompt: "Find file or URL: ......". I just want an automatic "yes".
Passing arguments does not work. It might be interesting for other cases as well. I used a macro before that would just call find-file-at-point followed by a RET.
It seems there is no variable to automatically accept the prompt.
You can redefine a function ffap-read-file-or-url by removing a part which is doing the prompt. It remains something like this
(defun ffap-read-file-or-url (prompt guess)
"Read file or URL from minibuffer, with PROMPT and initial GUESS."
(or guess (setq guess default-directory))
(let (dir)
;; Tricky: guess may have or be a local directory, like "w3/w3.elc"
;; or "w3/" or "../el/ffap.el" or "../../../"
(or (ffap-url-p guess)
(progn
(or (ffap-file-remote-p guess)
(setq guess
(abbreviate-file-name (expand-file-name guess))
))
(setq dir (file-name-directory guess))))
;; Do file substitution like (interactive "F"), suggested by MCOOK.
(or (ffap-url-p guess) (setq guess (substitute-in-file-name guess)))
;; Should not do it on url's, where $ is a common (VMS?) character.
;; Note: upcoming url.el package ought to handle this automatically.
guess))

Using an argument of a function in normal mode in Vim?

I have a Vimscript function defined like this:
function Cs(a, b)
normal a:a|"cylr a:b|x"cP
endfunction
However, the intended action (do some crazy stuff with the arguments a and b in normal mode) doesn't work, instead it takes the first "a" as "append" and writes the rest of the line to the file.
How can I use arguments on a "normal" statement in Vimscript? I found no way to do this.
You need to build up a string with the parameters in and execute it with the :exec statement.
e.g. something like this:
function Cs(a, b)
exec "normal " a ":" a "|\"cylr " a ":" b "|x\"cP"
endfunction