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