how to use a keyboard macro in a lisp function until it fails - emacs

right now I have a keyboard macro defined and named, and i want to make a lisp function which goes to the top of the buffer, and does:
i = 1
do{
run macro
if macro hit the end of the buffer, break out of the loop
insert i
i++
}while(true)
here's what's in my .emacs
(fset 'next-id
(lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ([19 73 68 61 34 13 67108896 19 34 13 2 23] 0 "%d")) arg)))
(global-set-key (kbd "C-x n") 'next-id)
how would I go about this?

Srsly. Here's how to do it: C-u 0 F4

This should do the trick:
(defun apply-macro-to-buffer (&optional macro)
"Apply last keyboard macro to the buffer"
(interactive "CEnter the name of the macro to apply: ")
(or macro
(progn
(if (null last-kbd-macro)
(error "No keyboard macro has been defined"))
(setq macro last-kbd-macro)))
(let ((end-marker (copy-marker (point-max)))
(i 1))
(save-excursion
(goto-char (point-min))
(while (and (< (point) end-marker))
(let ((mark-active nil))
(execute-kbd-macro macro))
(insert (format "%d\n" i))
(setq i (1+ i))))))
To do the same for a regular command, try this:
(defun apply-command-to-buffer (command)
"Apply a command to the buffer"
(interactive "CEnter the name of the command to apply: ")
(let ((end-marker (copy-marker (point-max)))
(i 1))
(save-excursion
(goto-char (point-min))
(while (and (< (point) end-marker))
(call-interactively command)
(insert (format "%d\n" i))
(setq i (1+ i))))))

Related

Moving lines internally in emacs 24.4

I have this snippet of code in my .emacs file that should move lines of code up or down. This works fine on 24.3.1 but not fully on 24.4.
moving lines down work, as the line would be swapped with the bottom line and the "cursor" would move as well.
Moving the line up however, it will swap but the cursor stay on the same line without moving up along with the line.
Is there a reason for that?
;; Moving a line up or down
(defun move-text-internal (arg)
(cond
((and mark-active transient-mark-mode)
(if (> (point) (mark))
(exchange-point-and-mark))
(let ((column (current-column))
(text (delete-and-extract-region (point) (mark))))
(forward-line arg)
(move-to-column column t)
(set-mark (point))
(insert text)
(exchange-point-and-mark)
(setq deactivate-mark nil)))
(t
(let ((column (current-column)))
(beginning-of-line)
(when (or (> arg 0) (not (bobp)))
(forward-line)
(when (or (< arg 0) (not (eobp)))
(transpose-lines arg))
(forward-line -1))
(move-to-column column t)))))
(defun move-text-down (arg)
"Move region (transient-mark-mode active) or current line
arg lines down."
(interactive "*p")
(move-text-internal arg))
;(global-set-key [M-S-down] 'move-text-down)
(global-set-key [A-M-down] 'move-text-down)
(defun move-text-up (arg)
"Move region (transient-mark-mode active) or current line
arg lines up."
(interactive "*p")
(move-text-internal (- arg)))
;(global-set-key [M-S-up] 'move-text-up)
(global-set-key [A-M-up] 'move-text-up)

Switch parts of adjacent lines

I have this code that switch lines up/down:
;; Moving a line up or down
(defun move-text-internal (arg)
(cond
((and mark-active transient-mark-mode)
(if (> (point) (mark))
(exchange-point-and-mark))
(let ((column (current-column))
(text (delete-and-extract-region (point) (mark))))
(forward-line arg)
(move-to-column column t)
(set-mark (point))
(insert text)
(exchange-point-and-mark)
(setq deactivate-mark nil)))
(t
(let ((column (current-column)))
(beginning-of-line)
(when (or (> arg 0) (not (bobp)))
(forward-line)
(when (or (< arg 0) (not (eobp)))
(transpose-lines arg))
(forward-line -1))
(move-to-column column t)))))
(defun move-text-down (arg)
"Move region (transient-mark-mode active) or current line
arg lines down."
(interactive "*p")
(move-text-internal arg))
(global-set-key [M-S-down] 'move-text-down)
(defun move-text-up (arg)
"Move region (transient-mark-mode active) or current line
arg lines up."
(interactive "*p")
(move-text-internal (- arg)))
(global-set-key [M-S-up] 'move-text-up)
I was wondering if it is possible to tweak the move-text-internal function so it is possible to move part of line "after cursor" up or down.
Here is an example:
Before:
A X B W
Q E O P
If cursor was after X on the first line, after M-S-down:
A X O P
Q E B W
UPDATE:
Thanks to Jordan Biondo for the the his code and function.
I tweaked it to keep line moving as long as you keep invoking the command.
(defun flip-text (&optional arg)
"Flip the text from point to the end of the current line with the text
in the next line from the same column to the end of the next line.
With a prefix arg, flip text with the line above the current."
(interactive "p")
(save-excursion
(let ((tt (delete-and-extract-region (point) (point-at-eol)))
(c (current-column)))
(forward-line arg)
(move-to-column c)
(insert tt)
(let ((ot (delete-and-extract-region (point) (point-at-eol))))
(forward-line (- arg))
(goto-char (point-at-eol))
(insert ot)
))
)
(previous-line (- arg))
)
(global-set-key (kbd "C-M-z") (lambda ()
(interactive)
(flip-text 1)))
(global-set-key (kbd "C-M-c") (lambda ()
(interactive)
(flip-text -1)))
This will do what you specified but does not do multiple lines.
(defun flip-text-to-eol (&optional up)
"Flip the text from point to the end of the current line with the text
in the next line from the same column to the end of the next line.
With a prefix arg, flip text with the line above the current."
(interactive "P")
(save-excursion
(let ((tt (delete-and-extract-region (point) (point-at-eol)))
(c (current-column)))
(forward-line (if up -1 1))
(move-to-column c)
(insert tt)
(let ((ot (delete-and-extract-region (point) (point-at-eol))))
(forward-line (if up 1 -1))
(goto-char (point-at-eol))
(insert ot)))))

How to bind keys to indent/unindent region in emacs?

I want to define two key-bindings to indent/unindent region by 4 spaces.
Before:
hello
world
foo
bar
Visually select world and foo.
Type >
After:
hello
world
foo
bar
I also want to bind < to unindent region.
I'm not familiar with emacs, please help.
There are already keyboard shortcuts for that:
Indent: C-u 4 C-x TAB
Unindent C-u - 4 C-x TAB
If you find that too long to type, you could put the following in your .emacs file:
(defun my-indent-region (N)
(interactive "p")
(if (use-region-p)
(progn (indent-rigidly (region-beginning) (region-end) (* N 4))
(setq deactivate-mark nil))
(self-insert-command N)))
(defun my-unindent-region (N)
(interactive "p")
(if (use-region-p)
(progn (indent-rigidly (region-beginning) (region-end) (* N -4))
(setq deactivate-mark nil))
(self-insert-command N)))
(global-set-key ">" 'my-indent-region)
(global-set-key "<" 'my-unindent-region)
With this code the greater than (>) and less than (<) keys will indent/unindent a marked region by 4 spaces each.
(defun keyboard-indent (&optional arg)
(interactive)
(let ((deactivate-mark nil)
(beg (or (and mark-active (region-beginning))
(line-beginning-position)))
(end (or (and mark-active (region-end)) (line-end-position))))
(indent-rigidly beg end (* (or arg 1) tab-width))))
(defun keyboard-unindent (&optional arg)
(interactive)
(keyboard-indent (* -1 (or arg 1))))
In addition to what #Thomas already wrote, you might not want to use the keys < and > for indenting or unindenting. Just image you need to write some HTML and can't enter those characters anymore. This is why I inserted the following in my init file, as key settings:
(global-set-key (kbd "C-<") 'my-indent-region)
(global-set-key (kbd "C->") 'my-unindent-region)
Note: It doesn't work without the (kbd ...). You will get an error:
global-set-key: Key sequence C - > starts with non-prefix key C
You can use replace 4 with tab-width as
(defun indent-region-shift-right-n (N)
(interactive "p")
(if (use-region-p)
(progn (indent-rigidly (region-beginning) (region-end) (* N tab-width))
(setq deactivate-mark nil))
(self-insert-command N)))
(defun unindent-region-shift-left-n (N)
(interactive "p")
(if (use-region-p)
(progn (indent-rigidly (region-beginning) (region-end) (* N (- tab-width)))
(setq deactivate-mark nil))
(self-insert-command N)))
(global-set-key ">" 'indent-region-shift-right-n)
(global-set-key "<" 'unindent-region-shift-left-n)

eval every line in the scratch buffer and append the result to the line

I've got this snippet of code:
(define-key lisp-interaction-mode-map (kbd "C-c C-e")
(lambda ()
(let ((result (eval (read (buffer-substring
(point-at-bol) (point-at-eol)))))
(goto-char (point-at-eol))))
(insert (format " ; => %s" result))))
but it doesn't work, as in
Wrong type argument: commandp, (lambda nil (let ((result (eval (read (buffer-substring (point-at-bol) (point-at-eol))))) (goto-char (point-at-eol)))) (insert (format " ; => %s" result)))
This command shouldn't function on a per-line basis. Move point by sexp instead.
Here is a library I made that does basically this, but works with mult-line
results, and is reentrant. So you can change some stuff, and re-run the
command to update results.
EDIT: correct link to package mentioned.
Solved.
(define-key lisp-interaction-mode-map (kbd "C-c C-e")
(lambda ()
(interactive)
(let ((result (eval (read (buffer-substring
(point-at-bol) (point-at-eol))))))
(goto-char (point-at-eol))
(insert (format " ; ⇒ %s" result)))))

Intelligent auto closing matching characters

In some of the modes I'm using, emacs helps me by auto closing some elements such as quotes, parenthesis.
However some times, out of habit I type the closing element my self and end up with ()) or """.
How can I set up emacs to ignore the extra key?
While it is fun to roll your own, autopair has emerged as the canonical solution to this problem. It does everything you ask, and a few things, you didn't know you wanted. Emacs wiki entry.
Emacs 24 (currently in pretest) will be prepackaged with an electric pairing package. Autopair is still much more sophisticated than the builtin one.
EDIT: I had had the following in my .emacs for a while, and it worked fine so I didn't think too much about it. As event_jr points out in his answer, the same features (and apparently a bit more) can be had with the autopairs.el package, linked from the same page that I got this code from.
I have the following code in my .emacs to do this, taken from the emacs wiki:
(setq skeleton-pair t)
(setq skeleton-pair-alist
'((?\( _ ?\))
(?[ _ ?])
(?{ _ ?})
(?\" _ ?\")))
(defun autopair-insert (arg)
(interactive "P")
(let (pair)
(cond
((assq last-command-char skeleton-pair-alist)
(autopair-open arg))
(t
(autopair-close arg)))))
(defun autopair-open (arg)
(interactive "P")
(let ((pair (assq last-command-char
skeleton-pair-alist)))
(cond
((and (not mark-active)
(eq (car pair) (car (last pair)))
(eq (car pair) (char-after)))
(autopair-close arg))
(t
(skeleton-pair-insert-maybe arg)))))
(defun autopair-close (arg)
(interactive "P")
(cond
(mark-active
(let (pair open)
(dolist (pair skeleton-pair-alist)
(when (eq last-command-char (car (last pair)))
(setq open (car pair))))
(setq last-command-char open)
(skeleton-pair-insert-maybe arg)))
((looking-at
(concat "[ \t\n]*"
(regexp-quote (string last-command-char))))
(replace-match (string last-command-char))
(indent-according-to-mode))
(t
(self-insert-command (prefix-numeric-value arg))
(indent-according-to-mode))))
(defun autopair-backspace (arg)
(interactive "p")
(if (eq (char-after)
(car (last (assq (char-before) skeleton-pair-alist))))
(and (char-after) (delete-char 1)))
(delete-backward-char arg))
(global-set-key [backspace] 'autopair-backspace)
(define-key isearch-mode-map [backspace] 'isearch-delete-char) ;; required to fix behaviour in isearch
(global-set-key "(" 'autopair-insert)
(global-set-key ")" 'autopair-insert)
(global-set-key "[" 'autopair-insert)
(global-set-key "]" 'autopair-insert)
(global-set-key "{" 'autopair-insert)
(global-set-key "}" 'autopair-insert)
(global-set-key "\"" 'autopair-insert)
I'm not sure if it's Emacs 24 feature only, but electric-pair-mode seems to do what you want.