bard@brigid.cs.cornell.edu (Bard Bloom) (07/13/90)
Last year, when I was trying to avoid finishing my thesis, I wrote a package called 1char.el, of commands which let you make changes to recently-typed words: "Delete the third-to-the-last occurrence of the letter `k'." Well, I finished my thesis anyways, but I have done some revisions and tweaks. The most useful one is that you don't have to count quite so much; if you realize that you missed a `k', you can type another command (`c-h <' or `c-h >') to make it the second or fourth `k'. (This is independent of the ordinary undo mechanism; you can move around after doing it.) Comments are welcome, as always. -- Bard ;; 1char.el -- commands to fix typos in the previous word with minimal typing. ;; Copyright (C) Bard Bloom, July 1989; revised July 1990. ;; This file is not yet part of GNU Emacs. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY. No author or distributor ;; accepts responsibility to anyone for the consequences of using it ;; or for whether it serves any particular purpose or works at all, ;; unless he says so in writing. Refer to the GNU Emacs General Public ;; License for full details. ;; Everyone is granted permission to copy, modify and redistribute ;; GNU Emacs, but only under the conditions described in the ;; GNU Emacs General Public License. A copy of this license is ;; supposed to have been given to you along with GNU Emacs so you ;; can know your rights and responsibilities. It should be in a ;; file named COPYING. Among other things, the copyright notice ;; and this notice must be preserved on all copies. ;; Changes since 7/89: ;; ;; Commands to undo the last 1char command, and redo it in a different place. ;; Case toggle 1char ;; Delete from point through 1char. ;; ;; Summary: ;; This is a bunch of commands to make minor changes in recently-typed ;; text. It's intended for fast but inaccurate typists, like me. ;; ;; There's nothing you couldn't do by moving back, typing a character ;; or three, and moving forward --- but it does save a bunch of keystrokes. ;; Might improve your typing speed by a word or two per day, even. ;; ;; I put the commands under c-h because they really want to be on ;; two-key commands you can type without moving your fingers from ;; the keyboard. ;; ;; Positions in the previous word are specified by a short sequence of ;; characters, called a 1char. ;; If it's a letter, then it refers to the last occurrance of that letter ;; in the word: pepper ;; ^ p means this p ;; ^ e means this e ;; ;; Most other characters behave the same way. The main exceptions are (now): ;; ;; ;; = and c-q: quotes the next character, so that it is taken literally (i.e., acts ;; like a letter). This is most useful for digits, -, and =. ;; -: negates the number you are about to type. Negative numbers go forwards rather ;; than backwards. 0 is treated as 1, unless 1char guesses that you really ;; wanted -1. ;; digits: Digits ask you for another character. `1 c' goes to the first ;; previous occurrance of c (just like c itself). `2 c' goes to the one ;; before that, and so on. ;; ;; pepper ;; ^ 1 p ;; ^ 2 p ;; ^ 3 p ;; ;; Lots of these commands take a prefix argument telling how many words back ;; to go. Furthermore, if the previous word isn't at least 18 (or whatever ;; value 1char-min-distance has) chars long, you get to work on the previous ;; 18 (or whatever) characters. ;; ;; Commands: ;; c-h c-t: transpose the 1char with the previous character (P) ;; c-h c-d: delete the 1char (P) ;; c-h c-i: insert a character before the 1char (P) ;; c-h c-a: insert a character after the 1char (P) ;; c-h c-c: change the 1char to another character (P) ;; c-h c-b: break the word before the 1char. "ofthe" and t --> "of the" ;; c-h c-m: put the cursor on the 1char. (P) ;; c-h c-u: undo (without moving point) ;; c-h c-l: recenter screen so that this paragraph is on top. ;; c-h c-j: join the previous two words. ;; c-h ~ : toggle the case of the 1char. (P) ;; c-h c-x: undo ;; ;; c-h c-k c-d: delete text from point to 1char (P) ;; c-h c-k c-k: delete forward from point to 1char (P) ;; (like c-h c-k c-d but the 1char is interpreted negatively) ;; It's easy to get the wrong occurrance of a letter. There are commands which undo ;; the last 1char command you typed and redo it one 1char to the left or right. ;; So, if the buffer had ;; ;; eggplant is extremely toxic ;; # ;; and you wanted to capitalize the e in `extremely' with c-h ~ 2 e, you'd get ;; ;; eggplant is extrEmely toxic ;; # ;; ;; which is wrong. You could fix it with c-h c-n, getting ;; ;; eggplant is Extremely toxic ;; # ;; The commands marked (P) take a prefix argument telling how many words ;; back to go. ;; ;; abbreviations: ;; if the variable 1char-expands-abbrevs is set to true ;; then all these commands try to expand the word(s) they ;; make as abbrevs. i have a bunch of abbrevs for my common ;; typos --- `fo' is an abbrev for `of' --- so ;; typing `fothe', c-h c-b t will result in `of the' which is ;; probably what i intended. ;; buggigestions to bard@cs.cornell.edu (require 'cl) (unless (fboundp 'point-after) (defmacro point-after (&rest commands) "returns the value of point after executing the commands. doesn't move point. (expands to (save-excursion commands (point)))." (` (save-excursion (,@ commands) point)))) (defun recenter-top-para () "put the top of this paragraph on the top of the screen. don't move point." (interactive) (save-excursion (backward-paragraph 1) (next-line 1) (recenter 0) )) (defvar 1char-expands-abbrevs t "if true, then the various 1char functions expand abbrevs everywhere appropriate.") (make-variable-buffer-local '1char-expands-abbrevs) (defun join-words (p) "join two previous words. expands them as an abbrev if 1char-expands-abbrevs is true. " (interactive "p") (save-excursion (backward-word (1- p)) (backward-word 1) (setq 1char-marker (point-marker)) (setq 1char-undoer (f:l () (goto-char 1char-marker) (insert " "))) (setq 1char-last-prefix-arg p) (setq 1char-last-called-function (f:l (p oc) (join-words p))) (delete-horizontal-space) (forward-word 1) (if 1char-expands-abbrevs (expand-abbrev)))) (defvar 1char-at-end-of-word-internal nil "don't change this. true inside the about-the-previous-word macro, intended to be false elsewhere.") (defmacro about-the-previous-word (prefix &rest code) (let ((p (gensym))) (` (let (((, p) (point-marker)) (1char-at-end-of-word-internal t) ) ;; i don't know why save-excursion screws up (save-restriction (let ((a (point))) (backward-word (prefix-numeric-value (, prefix))) ;; We do want the side effects in the following progns: (if (> (+ (point) 1char-min-distance) a) (narrow-to-region (max (point-min) (- a 1char-min-distance)) (progn (forward-word 1) (point))) (narrow-to-region (1- (point)) (progn (forward-word 1) (point)))) (goto-char (point-max)) (,@ code) cond (1char-expands-abbrevs (goto-char (point-max)) (expand-abbrev)) ) ) (goto-char (, p)))))) (defvar 1char-min-distance 80 "The `previous word' for 1chars extends at least this many characters back.") ;; a 1char is now: ;; EXTERNALLY: ;; - most chars: the first previous occurrance of that char. ;; - digit N: get another char, C; give the N'th previous occurrance of C. ;; - digit 0: read a number in the minibuffer ;; - c-a (for future work): give a little minibuffer window to pick ;; the place to work interactively. ;; INTERNALLY ;; '(prev c n) -- c=char, n=count. n<0 means go forward (defun 1char-to-char (oc) "Converts a 1char OC to a char c. So, `3N' would convert to `N'." (second oc)) (defun 1char-read (prompt) (message prompt) (let ((y "") (x (read-char))) (when (eq x ?-) (setq y "-") (setq x (read-char))) (while (memq x '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9)) (setq y (concat y (char-to-string x))) (message "%s -" y) (setq x (read-char)) ) (cond ((string= y "") (setq y 1)) ((string= y "-") (setq y -1)) (t (setq y (string-to-int y)))) (setq 1char-last-1char (case x (?\C-a 1char-last-1char) ((?\C-q ?=) (message "%s (c-q):") (list 'prev (read-char) y)) (otherwise (list 'prev x y)))) 1char-last-1char)) (defmacro 1char-excursion (p oc &rest code) (let ((v (gensym))) (` (save-excursion (1char-goto-internal p (, oc)) (,@ code) )))) (put '1char-excursion 'lisp-indent-hook 2) (defun 1char-goto-internal (p oc) "Go to the position given by the 1char OC. Takes a prefix arg to tell it how many words back to go." (backward-word (1- (prefix-numeric-value p))) (let ((n 1) (c nil) ) (cond ((eq (car oc) 'prev) (setq c (cadr oc) n (caddr oc)))) (when (= n 0) (setq n 1)) (cond ((null c) (error "Internal representation of 1char is screwed up.")) ((and (> n 0) (search-backward (char-to-string c) (point-min) 't n))) ((and (< n 0) (search-forward (char-to-string c) (point-max) 't (- n))) (goto-char (match-beginning 0)) ) (t (error "I can't find a %c." c))))) (defun 1char-goto (p oc) (interactive (list current-prefix-arg (1char-read "Goto (1char):"))) (when (featurep 'positions) (stack-save-current-pos)) (setq 1char-last-prefix-arg p 1char-goto-last-position (point-marker) 1char-last-1char oc 1char-undoer (f:l () ) 1char-last-called-function (f:l (p oc) (goto-char 1char-goto-last-position) (1char-goto p oc))) (1char-goto-internal p oc)) (defun 1char-break-word (p oc) "break the previous word just before a 1char-specified position. see the documentation of 1char-goto for details." (interactive (list current-prefix-arg (1char-read "Break before (1char):"))) (1char-excursion p oc (setq 1char-marker (point-marker)) (insert-before-markers " ") (backward-char 1) (if 1char-expands-abbrevs (expand-abbrev)) (1char-maybe-expand-abbrevs) ) (setq 1char-last-prefix-arg p 1char-last-1char oc 1char-undoer (f:l () (delete-region (1- 1char-marker) 1char-marker )) 1char-last-called-function (function 1char-break-word)) ) (defun 1char-maybe-expand-abbrevs () (when 1char-expands-abbrevs (unless (looking-at "\\>") (forward-word 1)) (expand-abbrev))) (defun 1char-transpose-chars (p oc) "transpose the character given by a 1char-specified position and the previous character." (interactive (list current-prefix-arg (1char-read "Twiddlebefore (1char):"))) (1char-excursion p oc (transpose-chars nil) (setq 1char-marker (point-marker)) (1char-maybe-expand-abbrevs) ) (setq 1char-last-prefix-arg p 1char-last-1char oc 1char-undoer (f:l () (goto-char (1- 1char-marker)) (transpose-chars nil)) 1char-last-called-function (function 1char-transpose-chars)) ) (defun 1char-change (p from to) "change the character given by a 1char to another character." (interactive (list current-prefix-arg (1char-read "Change (1char): ") (progn (message "To:") (read-char)))) (1char-excursion p from (setq 1char-marker (point-marker)) (delete-char 1) (insert to) (1char-maybe-expand-abbrevs)) (setq 1char-last-prefix-arg p 1char-change-to to 1char-last-1char from 1char-change-from (1char-to-char from) 1char-undoer (f:l () (save-excursion (goto-char (1+ 1char-marker)) (backward-delete-char-untabify 1) (insert 1char-change-from))) 1char-last-called-function (f:l (p oc) (1char-change p oc 1char-change-to))) ) (defun 1char-delete (p oc) "delete the character given by a 1char." (interactive (list current-prefix-arg (1char-read "Delete (1char):"))) (1char-excursion p oc (setq 1char-marker (point-marker)) (delete-char 1) (1char-maybe-expand-abbrevs)) (setq 1char-last-prefix-arg p 1char-last-1char oc 1char-deleted-char (1char-to-char oc) 1char-undoer (f:l () (save-excursion (goto-char 1char-marker) (insert 1char-deleted-char))) 1char-last-called-function (function 1char-delete)) ) (defun 1char-insert-before (p oc new) "insert a character just before the 1char c. new is the new character. expands abbrevs according to 1char-expands-abbrevs." (interactive (list current-prefix-arg (1char-read "Insert before (1char): ") (progn (message "Char:") (read-char)))) (1char-excursion p oc (setq 1char-marker (point-marker)) (insert new) (1char-maybe-expand-abbrevs)) (setq 1char-last-prefix-arg p 1char-insert-char new 1char-last-1char oc 1char-undoer (f:l () (delete-region 1char-marker (1+ 1char-marker))) 1char-last-called-function (f:l (p oc) (1char-insert-before p oc 1char-insert-char))) ) (defun 1char-insert-after (p oc new) "insert a character just after the 1char c. new is the new character. expands abbrevs according to 1char-expands-abbrevs." (interactive (list current-prefix-arg (1char-read "Insert after (1char): ") (progn (message "Char:") (read-char)))) (1char-excursion p oc (forward-char 1) (insert new) (setq 1char-marker (point-marker)) (1char-maybe-expand-abbrevs)) (setq 1char-last-prefix-arg p 1char-insert-char new 1char-last-1char oc 1char-undoer (f:l () (delete-region (1- 1char-marker) 1char-marker)) 1char-last-called-function (f:l (p oc) (1char-insert-after p oc 1char-insert-char)))) (defun 1char-one-further-out (n) (interactive "p") (1char-undo) (funcall 1char-last-called-function 1char-last-prefix-arg (1char-+ 1char-last-1char n)) ) (defun 1char-undo () (save-excursion (if 1char-undoer (funcall 1char-undoer) (error "Sorry, maarster, but I don't know how to fix that.") ))) (defun 1char-one-further-in (n) (interactive "p") (1char-one-further-out (- n))) (defun 1char-+ (oc n) "Return a 1char which is OC but N further out. If the thing comes out having 0 repitition, then make it (sgn N) -- on the ground that you're probably decrementing or incrementing and want it to go in some direction." (case (car oc) (prev (list 'prev (second oc) (let ((sum (+ n (third oc)))) (cond ((not (zerop sum)) sum) ((not (zerop (signum n))) (signum n)) (t 1)) ))) (t (error "Doom: illegal 1char %s" (2str oc))))) (defun 1char-negate (oc) "Returns a 1char which is OC negated. (forward <-> backward)" (case (car oc) (prev (list 'prev (second oc) (- (third oc)))) (t (error "Doom: illegal 1char %s" (2str oc))))) (defun undo-without-moving () "undo one thing without moving point." (interactive) (let ((p (point-marker))) (undo) (goto-char p))) (defun 1char-delete-through-1char-backwards (p oc) (interactive (list current-prefix-arg (1char-read "Delete backwards through (1char):"))) (kill-region (point) (point-after (1char-goto-internal p oc) ))) (defun 1char-delete-through-1char-forwards (p oc) (interactive (list current-prefix-arg (1char-read "Delete forwards through (1char):"))) (kill-region (point) (point-after (1char-goto-internal p (1char-negate oc))))) (defun 1char-case-twiddle (p oc) "Change the case of a character a ways back." (interactive (list current-prefix-arg (1char-read "Case twiddle (1char):"))) (1char-excursion p oc (let* ((c (string-to-char (buffer-substring (point) (1+ (point))))) (C (logxor 32 c)) ) (setq 1char-case-twiddle-char c 1char-marker (point-marker)) (when (or (and (<= c ?Z) (>= c ?A)) (and (<= c ?z) (>= c ?a))) (delete-char 1) (insert C)) (setq 1char-last-prefix-arg p 1char-last-1char oc 1char-undoer (f:l () (goto-char 1char-marker) (delete-char 1) (insert 1char-case-twiddle-char)) 1char-last-called-function (function 1char-case-twiddle))))) (global-set-key "\C-h\C-j" 'join-words) (global-set-key "\C-h\C-@" 'undo) (global-set-key "\C-h\C-u" 'undo-without-moving) (global-set-key "\C-h\C-l" 'recenter-top-para) (global-set-key "\C-h\C-t" '1char-transpose-chars) (global-set-key "\C-h\C-d" '1char-delete) (global-set-key "\C-h\C-a" '1char-insert-after) (global-set-key "\C-h\C-i" '1char-insert-before) (global-set-key "\C-h\C-c" '1char-change) (global-set-key "\C-h\C-b" '1char-break-word) (global-set-key "\C-h\C-m" '1char-goto) (global-set-key "\C-h<" '1char-one-further-out) (global-set-key "\C-h," '1char-one-further-out) (global-set-key "\C-h\C-n" '1char-one-further-out) (global-set-key "\C-h>" '1char-one-further-in) (global-set-key "\C-h." '1char-one-further-in) (global-set-key "\C-h\C-p" '1char-one-further-in) (global-set-key "\C-h\C-k\C-k" '1char-delete-through-1char-forwards) (global-set-key "\C-h\C-k\C-d" '1char-delete-through-1char-backwards) (global-set-key "\C-h~" '1char-case-twiddle)
bard@brigid.cs.cornell.edu (Bard Bloom) (07/13/90)
There was a bug (a reference to a function defined elsewhere) in the first version of this I posted. This one seems to run in an `emacs -q'. Tell me if there are any more problems with it. Apologies, Bard ;; 1char.el -- commands to fix typos in the previous word with minimal typing. ;; Copyright (C) Bard Bloom, July 1989; revised July 1990. ;; This file is not yet part of GNU Emacs. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY. No author or distributor ;; accepts responsibility to anyone for the consequences of using it ;; or for whether it serves any particular purpose or works at all, ;; unless he says so in writing. Refer to the GNU Emacs General Public ;; License for full details. ;; Everyone is granted permission to copy, modify and redistribute ;; GNU Emacs, but only under the conditions described in the ;; GNU Emacs General Public License. A copy of this license is ;; supposed to have been given to you along with GNU Emacs so you ;; can know your rights and responsibilities. It should be in a ;; file named COPYING. Among other things, the copyright notice ;; and this notice must be preserved on all copies. ;; Changes since 7/89: ;; ;; Commands to undo the last 1char command, and redo it in a different place. ;; Case toggle 1char ;; Delete from point through 1char. ;; ;; Summary: ;; This is a bunch of commands to make minor changes in recently-typed ;; text. It's intended for fast but inaccurate typists, like me. ;; ;; There's nothing you couldn't do by moving back, typing a character ;; or three, and moving forward --- but it does save a bunch of keystrokes. ;; Might improve your typing speed by a word or two per day, even. ;; ;; I put the commands under c-h because they really want to be on ;; two-key commands you can type without moving your fingers from ;; the keyboard. ;; ;; Positions in the previous word are specified by a short sequence of ;; characters, called a 1char. ;; If it's a letter, then it refers to the last occurrance of that letter ;; in the word: pepper ;; ^ p means this p ;; ^ e means this e ;; ;; Most other characters behave the same way. The main exceptions are (now): ;; ;; ;; = and c-q: quotes the next character, so that it is taken literally (i.e., acts ;; like a letter). This is most useful for digits, -, and =. ;; -: negates the number you are about to type. Negative numbers go forwards rather ;; than backwards. 0 is treated as 1, unless 1char guesses that you really ;; wanted -1. ;; digits: Digits ask you for another character. `1 c' goes to the first ;; previous occurrance of c (just like c itself). `2 c' goes to the one ;; before that, and so on. ;; ;; pepper ;; ^ 1 p ;; ^ 2 p ;; ^ 3 p ;; ;; Lots of these commands take a prefix argument telling how many words back ;; to go. Furthermore, if the previous word isn't at least 18 (or whatever ;; value 1char-min-distance has) chars long, you get to work on the previous ;; 18 (or whatever) characters. ;; ;; Commands: ;; c-h c-t: transpose the 1char with the previous character (P) ;; c-h c-d: delete the 1char (P) ;; c-h c-i: insert a character before the 1char (P) ;; c-h c-a: insert a character after the 1char (P) ;; c-h c-c: change the 1char to another character (P) ;; c-h c-b: break the word before the 1char. "ofthe" and t --> "of the" ;; c-h c-m: put the cursor on the 1char. (P) ;; c-h c-u: undo (without moving point) ;; c-h c-l: recenter screen so that this paragraph is on top. ;; c-h c-j: join the previous two words. ;; c-h ~ : toggle the case of the 1char. (P) ;; c-h c-x: undo ;; ;; c-h c-k c-d: delete text from point to 1char (P) ;; c-h c-k c-k: delete forward from point to 1char (P) ;; (like c-h c-k c-d but the 1char is interpreted negatively) ;; It's easy to get the wrong occurrance of a letter. There are commands which undo ;; the last 1char command you typed and redo it one 1char to the left or right. ;; So, if the buffer had ;; ;; eggplant is extremely toxic ;; # ;; and you wanted to capitalize the e in `extremely' with c-h ~ 2 e, you'd get ;; ;; eggplant is extrEmely toxic ;; # ;; ;; which is wrong. You could fix it with c-h c-n, getting ;; ;; eggplant is Extremely toxic ;; # ;; The commands marked (P) take a prefix argument telling how many words ;; back to go. ;; ;; abbreviations: ;; if the variable 1char-expands-abbrevs is set to true ;; then all these commands try to expand the word(s) they ;; make as abbrevs. i have a bunch of abbrevs for my common ;; typos --- `fo' is an abbrev for `of' --- so ;; typing `fothe', c-h c-b t will result in `of the' which is ;; probably what i intended. ;; buggigestions to bard@cs.cornell.edu (require 'cl) (unless (fboundp 'f:l) (defmacro f:l (x &rest y) "(function (lambda X) Y). Abbreviation taken from some obscure dialect of Lisp, but I remembered it seven years after I read the manual, so it can't be all that obscure, can it?" (list 'function (append (list 'lambda x ) y)))) (unless (fboundp 'point-after) (defmacro point-after (&rest commands) "returns the value of point after executing the commands. doesn't move point. (expands to (save-excursion commands (point)))." (` (save-excursion (,@ commands) point)))) (defun recenter-top-para () "put the top of this paragraph on the top of the screen. don't move point." (interactive) (save-excursion (backward-paragraph 1) (next-line 1) (recenter 0) )) (defvar 1char-expands-abbrevs t "if true, then the various 1char functions expand abbrevs everywhere appropriate.") (make-variable-buffer-local '1char-expands-abbrevs) (defun join-words (p) "join two previous words. expands them as an abbrev if 1char-expands-abbrevs is true. " (interactive "p") (save-excursion (backward-word (1- p)) (backward-word 1) (setq 1char-marker (point-marker)) (setq 1char-undoer (f:l () (goto-char 1char-marker) (insert " "))) (setq 1char-last-prefix-arg p) (setq 1char-last-called-function (f:l (p oc) (join-words p))) (delete-horizontal-space) (forward-word 1) (if 1char-expands-abbrevs (expand-abbrev)))) (defvar 1char-at-end-of-word-internal nil "don't change this. true inside the about-the-previous-word macro, intended to be false elsewhere.") (defmacro about-the-previous-word (prefix &rest code) (let ((p (gensym))) (` (let (((, p) (point-marker)) (1char-at-end-of-word-internal t) ) ;; i don't know why save-excursion screws up (save-restriction (let ((a (point))) (backward-word (prefix-numeric-value (, prefix))) ;; We do want the side effects in the following progns: (if (> (+ (point) 1char-min-distance) a) (narrow-to-region (max (point-min) (- a 1char-min-distance)) (progn (forward-word 1) (point))) (narrow-to-region (1- (point)) (progn (forward-word 1) (point)))) (goto-char (point-max)) (,@ code) cond (1char-expands-abbrevs (goto-char (point-max)) (expand-abbrev)) ) ) (goto-char (, p)))))) (defvar 1char-min-distance 80 "The `previous word' for 1chars extends at least this many characters back.") ;; a 1char is now: ;; EXTERNALLY: ;; - most chars: the first previous occurrance of that char. ;; - digit N: get another char, C; give the N'th previous occurrance of C. ;; - digit 0: read a number in the minibuffer ;; - c-a (for future work): give a little minibuffer window to pick ;; the place to work interactively. ;; INTERNALLY ;; '(prev c n) -- c=char, n=count. n<0 means go forward (defun 1char-to-char (oc) "Converts a 1char OC to a char c. So, `3N' would convert to `N'." (second oc)) (defun 1char-read (prompt) (message prompt) (let ((y "") (x (read-char))) (when (eq x ?-) (setq y "-") (setq x (read-char))) (while (memq x '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9)) (setq y (concat y (char-to-string x))) (message "%s -" y) (setq x (read-char)) ) (cond ((string= y "") (setq y 1)) ((string= y "-") (setq y -1)) (t (setq y (string-to-int y)))) (setq 1char-last-1char (case x (?\C-a 1char-last-1char) ((?\C-q ?=) (message "%s (c-q):") (list 'prev (read-char) y)) (otherwise (list 'prev x y)))) 1char-last-1char)) (defmacro 1char-excursion (p oc &rest code) (let ((v (gensym))) (` (save-excursion (1char-goto-internal p (, oc)) (,@ code) )))) (put '1char-excursion 'lisp-indent-hook 2) (defun 1char-goto-internal (p oc) "Go to the position given by the 1char OC. Takes a prefix arg to tell it how many words back to go." (backward-word (1- (prefix-numeric-value p))) (let ((n 1) (c nil) ) (cond ((eq (car oc) 'prev) (setq c (cadr oc) n (caddr oc)))) (when (= n 0) (setq n 1)) (cond ((null c) (error "Internal representation of 1char is screwed up.")) ((and (> n 0) (search-backward (char-to-string c) (point-min) 't n))) ((and (< n 0) (search-forward (char-to-string c) (point-max) 't (- n))) (goto-char (match-beginning 0)) ) (t (error "I can't find a %c." c))))) (defun 1char-goto (p oc) (interactive (list current-prefix-arg (1char-read "Goto (1char):"))) (when (featurep 'positions) (stack-save-current-pos)) (setq 1char-last-prefix-arg p 1char-goto-last-position (point-marker) 1char-last-1char oc 1char-undoer (f:l () ) 1char-last-called-function (f:l (p oc) (goto-char 1char-goto-last-position) (1char-goto p oc))) (1char-goto-internal p oc)) (defun 1char-break-word (p oc) "break the previous word just before a 1char-specified position. see the documentation of 1char-goto for details." (interactive (list current-prefix-arg (1char-read "Break before (1char):"))) (1char-excursion p oc (setq 1char-marker (point-marker)) (insert-before-markers " ") (backward-char 1) (if 1char-expands-abbrevs (expand-abbrev)) (1char-maybe-expand-abbrevs) ) (setq 1char-last-prefix-arg p 1char-last-1char oc 1char-undoer (f:l () (delete-region (1- 1char-marker) 1char-marker )) 1char-last-called-function (function 1char-break-word)) ) (defun 1char-maybe-expand-abbrevs () (when 1char-expands-abbrevs (unless (looking-at "\\>") (forward-word 1)) (expand-abbrev))) (defun 1char-transpose-chars (p oc) "transpose the character given by a 1char-specified position and the previous character." (interactive (list current-prefix-arg (1char-read "Twiddlebefore (1char):"))) (1char-excursion p oc (transpose-chars nil) (setq 1char-marker (point-marker)) (1char-maybe-expand-abbrevs) ) (setq 1char-last-prefix-arg p 1char-last-1char oc 1char-undoer (f:l () (goto-char (1- 1char-marker)) (transpose-chars nil)) 1char-last-called-function (function 1char-transpose-chars)) ) (defun 1char-change (p from to) "change the character given by a 1char to another character." (interactive (list current-prefix-arg (1char-read "Change (1char): ") (progn (message "To:") (read-char)))) (1char-excursion p from (setq 1char-marker (point-marker)) (delete-char 1) (insert to) (1char-maybe-expand-abbrevs)) (setq 1char-last-prefix-arg p 1char-change-to to 1char-last-1char from 1char-change-from (1char-to-char from) 1char-undoer (f:l () (save-excursion (goto-char (1+ 1char-marker)) (backward-delete-char-untabify 1) (insert 1char-change-from))) 1char-last-called-function (f:l (p oc) (1char-change p oc 1char-change-to))) ) (defun 1char-delete (p oc) "delete the character given by a 1char." (interactive (list current-prefix-arg (1char-read "Delete (1char):"))) (1char-excursion p oc (setq 1char-marker (point-marker)) (delete-char 1) (1char-maybe-expand-abbrevs)) (setq 1char-last-prefix-arg p 1char-last-1char oc 1char-deleted-char (1char-to-char oc) 1char-undoer (f:l () (save-excursion (goto-char 1char-marker) (insert 1char-deleted-char))) 1char-last-called-function (function 1char-delete)) ) (defun 1char-insert-before (p oc new) "insert a character just before the 1char c. new is the new character. expands abbrevs according to 1char-expands-abbrevs." (interactive (list current-prefix-arg (1char-read "Insert before (1char): ") (progn (message "Char:") (read-char)))) (1char-excursion p oc (setq 1char-marker (point-marker)) (insert new) (1char-maybe-expand-abbrevs)) (setq 1char-last-prefix-arg p 1char-insert-char new 1char-last-1char oc 1char-undoer (f:l () (delete-region 1char-marker (1+ 1char-marker))) 1char-last-called-function (f:l (p oc) (1char-insert-before p oc 1char-insert-char))) ) (defun 1char-insert-after (p oc new) "insert a character just after the 1char c. new is the new character. expands abbrevs according to 1char-expands-abbrevs." (interactive (list current-prefix-arg (1char-read "Insert after (1char): ") (progn (message "Char:") (read-char)))) (1char-excursion p oc (forward-char 1) (insert new) (setq 1char-marker (point-marker)) (1char-maybe-expand-abbrevs)) (setq 1char-last-prefix-arg p 1char-insert-char new 1char-last-1char oc 1char-undoer (f:l () (delete-region (1- 1char-marker) 1char-marker)) 1char-last-called-function (f:l (p oc) (1char-insert-after p oc 1char-insert-char)))) (defun 1char-one-further-out (n) (interactive "p") (1char-undo) (funcall 1char-last-called-function 1char-last-prefix-arg (1char-+ 1char-last-1char n)) ) (defun 1char-undo () (save-excursion (if 1char-undoer (funcall 1char-undoer) (error "Sorry, maarster, but I don't know how to fix that.") ))) (defun 1char-one-further-in (n) (interactive "p") (1char-one-further-out (- n))) (defun 1char-+ (oc n) "Return a 1char which is OC but N further out. If the thing comes out having 0 repitition, then make it (sgn N) -- on the ground that you're probably decrementing or incrementing and want it to go in some direction." (case (car oc) (prev (list 'prev (second oc) (let ((sum (+ n (third oc)))) (cond ((not (zerop sum)) sum) ((not (zerop (signum n))) (signum n)) (t 1)) ))) (t (error "Doom: illegal 1char %s" (2str oc))))) (defun 1char-negate (oc) "Returns a 1char which is OC negated. (forward <-> backward)" (case (car oc) (prev (list 'prev (second oc) (- (third oc)))) (t (error "Doom: illegal 1char %s" (2str oc))))) (defun undo-without-moving () "undo one thing without moving point." (interactive) (let ((p (point-marker))) (undo) (goto-char p))) (defun 1char-delete-through-1char-backwards (p oc) (interactive (list current-prefix-arg (1char-read "Delete backwards through (1char):"))) (kill-region (point) (point-after (1char-goto-internal p oc) ))) (defun 1char-delete-through-1char-forwards (p oc) (interactive (list current-prefix-arg (1char-read "Delete forwards through (1char):"))) (kill-region (point) (point-after (1char-goto-internal p (1char-negate oc))))) (defun 1char-case-twiddle (p oc) "Change the case of a character a ways back." (interactive (list current-prefix-arg (1char-read "Case twiddle (1char):"))) (1char-excursion p oc (let* ((c (string-to-char (buffer-substring (point) (1+ (point))))) (C (logxor 32 c)) ) (setq 1char-case-twiddle-char c 1char-marker (point-marker)) (when (or (and (<= c ?Z) (>= c ?A)) (and (<= c ?z) (>= c ?a))) (delete-char 1) (insert C)) (setq 1char-last-prefix-arg p 1char-last-1char oc 1char-undoer (f:l () (goto-char 1char-marker) (delete-char 1) (insert 1char-case-twiddle-char)) 1char-last-called-function (function 1char-case-twiddle))))) (global-set-key "\C-h\C-j" 'join-words) (global-set-key "\C-h\C-@" 'undo) (global-set-key "\C-h\C-u" 'undo-without-moving) (global-set-key "\C-h\C-l" 'recenter-top-para) (global-set-key "\C-h\C-t" '1char-transpose-chars) (global-set-key "\C-h\C-d" '1char-delete) (global-set-key "\C-h\C-a" '1char-insert-after) (global-set-key "\C-h\C-i" '1char-insert-before) (global-set-key "\C-h\C-c" '1char-change) (global-set-key "\C-h\C-b" '1char-break-word) (global-set-key "\C-h\C-m" '1char-goto) (global-set-key "\C-h<" '1char-one-further-out) (global-set-key "\C-h," '1char-one-further-out) (global-set-key "\C-h\C-n" '1char-one-further-out) (global-set-key "\C-h>" '1char-one-further-in) (global-set-key "\C-h." '1char-one-further-in) (global-set-key "\C-h\C-p" '1char-one-further-in) (global-set-key "\C-h\C-k\C-k" '1char-delete-through-1char-forwards) (global-set-key "\C-h\C-k\C-d" '1char-delete-through-1char-backwards) (global-set-key "\C-h~" '1char-case-twiddle)
jka@hpfcso.HP.COM (Jay Adams) (07/14/90)
Lemme guess, "f:l" means this: (defmacro f:l (args &rest body) (list 'function (cons 'lambda (cons args body)))) - Jay
bard@brigid.cs.cornell.edu (Bard Bloom) (07/14/90)
> Lemme guess, "f:l" means this: > > (defmacro f:l (args &rest body) > (list 'function (cons 'lambda (cons args body)))) > Yes indeed. It's a truly obscure mnemonic, but I remembered it from UCI Lisp a good many years after my two-month usage of UCI Lisp -- probably as a good example of a truly obscure mnemonic. I recently posted a version which defined it. -- Bard