
;
; Author: Ken Duda
;
; This file contains a few commands intended to be used in keyboard macros.
;
; Use "m-x ++" to _increment_ the number at the point; that is, delete it, 
; add one, and reinsert.  
;
; Use the command "m-x input" while defining a keyboard macro.  It will
; insert a token "<user-input>" (which becomes the region) and leaves 
; the point at the end.  Then, when running the keyboard macro, it will
; instead _prompt_ you for input, which will get inserted at the point
; and become the region.
;
; Use the command "m-x goto-10" to end a keyboard macro.  In addition to
; ending the macro, it makes the macro loop back upon itself; when you
; execute the macro, it will execute over and over again, until you 
; hit C-g.  Warning: Once the keyboard macro loses its anonyminity, 
; this function will suddenly fail, since it works by invoking 
; call-last-kbd-macro (C-x e).
;
; Use m-x insert-counter to insert a numeral.  The numeral inserted is
; one higher each time the command is run. Use m-x reset-counter to set
; the counter back to the prefix arg (1 default).


(defun ++ ()
  "Increment the number (in base 10 representation) at point."
  (interactive)
  (if (looking-at "[-0-9]+")
      (progn
	(let ((num (car (read-from-string (buffer-substring (match-beginning 0) (match-end 0))))))
	  (delete-region (match-beginning 0) (match-end 0))
	  (insert (format "%d" (1+ num)))))))

(defvar kbd-mac-counter 1)

(defun insert-counter ()
"Insert a numeral.  The numeral inserted is
one higher each time the command is run. 
Use M-x reset-counter to set the counter back
to the prefix arg (1 default)."
  (interactive)
  (insert (format "%d" kbd-mac-counter))
  (setq kbd-mac-counter (1+ kbd-mac-counter)))

(defun reset-counter (arg)
"Set the counter used by reset-counter
to the prefix arg (1 default)."
  (interactive "p")
  (setq kbd-mac-counter arg))


(defun input (arg)
  "Get input from the user during a keyboard macro.
The input is read from the minibuffer and inserted
at the point.  The mark is set at the beginning of
the input, unless a (non-nil) prefix argument is passed.   
The point is left at the end of the input."
  (interactive "P")
  (or arg (push-mark (point)))
  (insert
   (if executing-kbd-macro 
       (let ((executing-kbd-macro nil))
	 (read-from-minibuffer "Keyboard-macro input: "))
     (if defining-kbd-macro
	 "<user-input>"
      (error "You're neither defining nor executing a keyboard macro!")))))

(defun goto-10 ()
  "End the current keyboard macro and make it loop back on itself
endlessly.  Note: this only works with the `last' keyboard macro;
it will fail after you name the keyboard macro."
  (interactive)
  (if defining-kbd-macro
      (progn
	(end-kbd-macro)
	(message "Repeating keyboard macro defined."))
    (if executing-kbd-macro
	(progn
	  (sit-for 0)			;Refresh, so the user can see how much has happened
	  (call-last-kbd-macro)
      (error "You're neither defining nor executing a keyboard macro!")))))

