home *** CD-ROM | disk | FTP | other *** search
- ;From utkcs2!emory!samsung!usc!ucsd!rutgers!rochester!cornell!Bard Mon Jun 11 10:06:25 EDT 1990
- ;Article 4413 of comp.emacs:
- ;Path: utkcs2!emory!samsung!usc!ucsd!rutgers!rochester!cornell!Bard
- ;>From: Bard the Emacs Gargoyle
- ;Newsgroups: comp.emacs
- ;Subject: Patterned-insert.
- ;Message-ID: <41976@cornell.UUCP>
- ;Date: 10 Jun 90 21:49:02 GMT
- ;Sender: nobody@cornell.UUCP
- ;Reply-To: bard@cs.cornell.edu (Bard Bloom)
- ;Distribution: comp
- ;Organization: Cornell Univ. CS Dept, Ithaca NY
- ;Lines: 260
-
-
- ;; Repetitititive insertion functions.
- ;; Copyright (C) 1990 Bard Bloom
-
- ;; A gizmo for quickly generating text with a pattern, and in particular
- ;; arithmetic progressions. For example, you might want to
- ;; create text looking like:
- ;; `a' --> 97 and the square of that is 9409
- ;; `b' --> 98 and the square of that is 9604
- ;; `c' --> 99 and the square of that is 9801
- ;; `d' --> 100 and the square of that is 10000
- ;; `e' --> 101 and the square of that is 10201
-
- ;; This was generated by the command
- ;; m-x insert-patterned
- ;; with arguments ";; `%c' --> %d and the square of that is %(* i i)",
- ;; ?a,
- ;; and ?e
- ;;
-
-
-
- ;; This file is is intended for use with GNU Emacs, and may be added to it
- ;; if the Free Software Foundation so wishes.
-
- ;; 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.
-
-
- (require 'cl)
-
- (defmacro for-var-low-high (var low high &rest body)
- "For VAR from LOW to HIGH do BODY. LOW and HIGH are evaluated
- once each. No error checking -- barfs if either isn't a number.
- VAR is let-bound."
- (let ((high-save (gensym)))
- (`
- (let (( (, var) (, low))
- ( (, high-save) (, high))
- )
- (while (<= (, var) (, high-save))
- (,@ body)
- (incf (, var))
- )))))
-
- (defun insert-patterned (pattern low high &optional no-line-breaks)
- "
- Insert lines with a similar structure but some variation into the file.
- It repeatedly inserts PATTERN in the file, varying the global variable i
- from LOW to HIGH. PATTERN is used somewhat as a format. If the following
- constructs occur within the PATTERN, they are replaced by appropriate
- string:
- %d,%i -- index as number
- %c -- index as char
- %(X) -- eval the expression (X), insert its value (made into a string)
- %% -- a %-sign
- %[X] -- the value of the expression X, made into a string.
- %[X c] -- the value of the expression X, printed with format c.
-
- For example, with
- PATTERN = \" a[%i] := %(* 2 i); \"
- LOW = 0
- HIGH = 3
- this command would insert
- a[0] := 0;
- a[1] := 2;
- a[2] := 4;
- a[3] := 6;
-
- Interactively, LOW and HIGH are evaluated expressions:
- PATTERN = \" ascii_%c := %i; \"
- LOW = ?a
- HIGH = ?d
- would insert
- ascii_a := 97;
- ascii_b := 98;
- ascii_c := 99;
- ascii_d := 100;
-
- A simple hex ASCII table could be generated with
- PATTERN = \" %c - %[i 2x]\".
- The pattern %[i 2x] prints the value of the expression i according to the format
- string `%2x', which is two-place hexadecimal. See `format' for more details.
-
- There is a good deal of overlap between the %(...) and %[... ...] patterns.
- %(X) and %[(X)] are identical. The %[...] can be used for inserting the values
- of variables --- %[x] inserts the value of x, while %(x) tries to call the function
- x --- and the second argument in the %[...] construct can specify a format.
-
- If the prefix argument NO-LINE-BREAKS is true, then the insertions
- are not separated by anything; otherwise, they are separated by line-breaks.
-
- "
- (interactive "sPattern: \nXFrom: \nXTo: \nP")
- (let* ((format+args (insert-pattern-internal pattern 1))
- (fmt (first format+args))
- (args (second format+args)))
- (for-var-low-high i low high
- (insert
- (apply (function format) fmt (mapcar (function eval) args))
- (if no-line-breaks "" "\n"))
- ))
- )
-
-
- (defun insert-patterned-2 (pattern lowi highi lowj highj &optional no-line-breaks)
- "
- Very much like insert-patterned, except that it has two variables i and j.
- i varies more slowly than j. Patterns are the same as insert-pattern (q.v.)
- except that we also allow:
- %j -- second index as number.
- If you want to insert j as a character, use %[j c].
- "
- (interactive "sPattern: \nX i from: \nXi to: \nX j from: \nX j to:\nP")
- (let* ((format+args (insert-pattern-internal pattern 2))
- (fmt (first format+args))
- (args (second format+args)))
- (for-var-low-high i lowi highi
- (for-var-low-high j lowj highj
- (insert
- (apply (function format) fmt (mapcar (function eval) args))
- (if no-line-breaks "" "\n"))
- ))))
-
- (defun insert-patterned-3 (pattern lowi highi lowj highj lowk highk &optional no-line-breaks)
- "
- Very much like insert-patterned, except that it has three variables: i,j,k.
- i varies more slowly than j, which is in turn slower than k.
- Patterns are the same as insert-pattern (q.v.)
- except that we also allow:
- %j -- second index as number.
- %k -- third index as number
- If you want to insert j as a character, use %[j c].
- "
- (interactive "sPattern: \nX i from: \nXi to: \nX j from: \nX j to:\nX k from: \nX k to:\nP")
- (let* ((format+args (insert-pattern-internal pattern 3))
- (fmt (first format+args))
- (args (second format+args)))
- (for-var-low-high i lowi highi
- (for-var-low-high j lowj highj
- (for-var-low-high k lowk highk
- (insert
- (apply (function format) fmt (mapcar (function eval) args))
- (if no-line-breaks "" "\n"))
- )))))
-
- (defun insert-patterned-4 (pattern lowi highi lowj highj lowk highk
- lowl highl &optional no-line-breaks)
- "
- Very much like insert-patterned, except that it has four variables: i,j,k,l.
- i varies more slowly than j, which is in turn slower than k, and
- l is fastest.
- Patterns are the same as insert-pattern (q.v.)
- except that we also allow:
- %j -- second index as number.
- %k -- third index as number
- %l -- fourht index as number.
- If you want to insert j as a character, use %[j c].
- "
- (interactive "sPattern: \nX i from: \nXi to: \nX j from: \nX j to:\nX k from: \nX k to:\nX l from: \nX l to: \nP")
- (let* ((format+args (insert-pattern-internal pattern 4))
- (fmt (first format+args))
- (args (second format+args)))
- (for-var-low-high i lowi highi
- (for-var-low-high j lowj highj
- (for-var-low-high k lowk highk
- (for-var-low-high l lowl highl
- (insert
- (apply (function format) fmt (mapcar (function eval) args))
- (if no-line-breaks "" "\n"))
- ))))))
-
-
-
- (defun string-cdr (s)
- (cond
- ((<= (length s) 1) "")
- (t (substring s 1))))
-
- (defun convert-to-string (x)
- "Convert X to a string. If X is an integer, it is treated as an integer
- rather than a character: (2str ?a) ==> \"97\". X can be anything, but the conversion
- isn't necessarily all that smart."
- (cond
- ((stringp x) x)
- ((symbolp x) (symbol-name x))
- ((numberp x) (int-to-string x))
- (t (prin1-to-string x))))
-
- (defun insert-pattern-internal (pattern nloops)
- (let ((args '())
- (pattern-tail pattern)
- (p "")
- m rfs
- insert-command
- )
- (while (setq m (string-match "^\\([^%]*\\)%\\(.\\)" pattern-tail))
- (setq p (concat p (substring pattern-tail (match-beginning 1) (match-end 1)) "%"))
- (setq pattern-tail (substring pattern-tail (match-beginning 2)))
- (case (string-to-char pattern-tail)
- (?% (setq p (concat p "%")))
- ((?c ?d)
- (push 'i args)
- (setq p (concat p (substring pattern-tail 1 1)))
- )
- ((?\[)
- (setq rfs (read-from-string pattern-tail))
- (setq pattern-tail (substring pattern-tail (cdr rfs)))
- (cond
- ((= (length (car rfs)) 1)
- (setq p (concat p "s"))
- (push (list 'convert-to-string (aref (car rfs) 0)) args))
- ((= (length (car rfs)) 2)
- (setq p (concat p (convert-to-string (aref (car rfs) 1))))
- (push (aref (car rfs) 0) args))
- (t
- (error "I don't understand the pattern %s" (convert-to-string rfs)))))
- ((?i)
- (push 'i args)
- (setq pattern-tail (string-cdr pattern-tail))
- (setq p (concat p "d")))
- ((?j)
- (when (< nloops 2) (error "No j index -- only %d loops" nloops))
- (push 'j args)
- (setq pattern-tail (string-cdr pattern-tail))
- (setq p (concat p "d")))
- ((?k)
- (when (< nloops 3) (error "No k index -- only %d loops" nloops))
- (push 'k args)
- (setq pattern-tail (string-cdr pattern-tail))
- (setq p (concat p "d")))
- ((?l)
- (when (< nloops 4) (error "No l index -- only %d loops" nloops))
- (push 'l args)
- (setq pattern-tail (string-cdr pattern-tail))
- (setq p (concat p "d")))
- (?\(
- (setq rfs (read-from-string pattern-tail))
- (setq pattern-tail (substring pattern-tail (cdr rfs)))
- (setq p (concat p "s"))
- (push (list 'convert-to-string (car rfs)) args))
- (t
- (setq p (concat p (substring pattern-tail 1 1)))
- (push 'i args)))
-
- )
- (list (concat p pattern-tail) (reverse args))
- ))
-
-
-