[comp.emacs] alist help for an elisp beginner

msb@ho5cad.ATT.COM (02/12/88)

I am green at elisp -- I don't even know lisp.  Could I get some help
with the following section of code?  Then, where can I go to get help
on my own for elisp?  Would a LISP book help?

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; I have this:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar file-name-abbreviation-alist
  '(
    ("/u13/msb" . "~")
    ("^/usr/add-on/exptools" . "<TOOLS>")
    )

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; I'd like this, but I get an error on argument type of
;; "char-or-string-p" when it runs.  Any help?
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar file-name-abbreviation-alist
  '(
    ((format "^%s" (getenv "HOME")) . "~")
    ((format "^%s" (getenv "TOOLS")) . "<TOOLS>")
    )

jk3k+@ANDREW.CMU.EDU ("Joseph G. Keane") (02/13/88)

Use:
(defvar file-name-abbreviation-alist
  (list
    (cons (format "^%s" (getenv "HOME")) "~")
    (cons (format "^%s" (getenv "TOOLS")) "<TOOLS>")))

(I bet this looks pretty random if you don't know Lisp.)

--Joe

gaynor@topaz.rutgers.edu (Silver) (02/14/88)

This stuff is looking *real* familiar.  Did you grab it off the net
about, oh, say, 18 months ago?  I posted stuff then that massively
hacked the buffer identification displayed in the prompt.  I'm
including the pertinent portions of my own .emacs.el and .emacs that I
think are rather useful.

This is my .emacs.  Since I screw up my emacs environment mightily, I
want it in compiled form (I never timed things, but I assume that it
will load and run faster).  This .emacs ensures that it always stays
compiled, by `make'ing it when necessary.

------------------------------- .emacs -------------------------------
;; Byte-compile ~/.emacs from ~/.emacs.el
;; if necessary, then load ~/.emacs.elc.
(let ((el  (expand-file-name "~/.emacs.el"))
      (elc (expand-file-name "~/.emacs.elc")))

  (if (file-newer-than-file-p el elc)
    (progn
      (message "%s is not up to date, byte-compiling %s..." el elc)
      (sit-for 1)
      (byte-compile-file el)))

  (load-file elc))
----------------------------------------------------------------------


----------------------- portions of .emacs.el ------------------------
(defvar hostname (substring (system-name)
			    0
			    (string-match "\\." (system-name)))
"The name of the host sans domains, as per (system-name).")

(defvar username (user-login-name)
"The username, as per (user-login-name).")



(setq find-file-hooks  '(abbreviate-mode-line-buffer-identification))
(setq write-file-hooks '(update-mode-line-buffer-identification))



;;;;;;;;;; mode-line-format ;;;;;;;;;;

;; Make mode-line-buffer-identification local to every buffer.  A
;; find-file-hook abbreviates the buffer-file-name to something a
;; little easier to read.
;;
;;   file name, originally = buffer-file-name
;;   abbreviations         = file-name-abbreviation-alist
;;   means of abbreviation = string-replace-regexp-alist
;;   find-file hook        = abbreviate-mode-line-buffer-identification

;; Customize mode-line-format and it's constituents.  Remember,
;; mode-line-buffer-identification MUST be used to identify the
;; buffer.  mode-line-modified is retained because it is in emacs's
;; default default-mode-line-format, and emacs may do some clever
;; tricks with it.
(setq emacs-identification (list hostname))
(make-variable-buffer-local 'mode-line-buffer-identification)
(make-variable-buffer-local 'mode-line-modified)
(setq-default mode-line-buffer-identification '("%17b"))
(setq-default mode-line-format
	      '(""
		mode-line-modified
		emacs-identification
		": "
		mode-line-buffer-identification
		" "
		global-mode-string
		" %[("
		mode-name
		"%n"
		mode-line-process
		minor-mode-alist
		")%]----"
		(-3 . "%p")
		"-%-"))

(defvar file-name-abbreviations nil
"Alist of embedded filename patterns vs corresponding abbreviations.
Each element is of the form (regexp . to-string).")
;; [^/][ug/|fac/|grad/|staff/]u<N>/ -> ~
;; ~$USER -> ~
;; ~/src/ -> <null>
;; ^.*/cs431/project/documentation/requirements -> reqs
(setq file-name-abbreviations
  (list 
    '("\\(^/\\|\\)\\(ug/\\|grad/\\|fac/\\|staff/\\|\\)u[1-9][0-9]*/" . "~")
    (cons (concat "~" (getenv "USER")) "~")
    '("~/src/" . "")
    '("^.*/cs431/project/documentation/requirements" . "reqs")))


(defun abbreviate-mode-line-buffer-identification ()
"Abbreviates mode-line-buffer-identification locally, as per
string-replace-regexps and file-name-abbreviations."
  (setq mode-line-buffer-identification
    (list (string-replace-regexps buffer-file-name
				  file-name-abbreviations))))

(defun update-mode-line-buffer-identification ()
"Abbreviates mode-line-buffer-identification locally, as per
abbreviate-mode-line-buffer-identification, but only if write-file
was the most recent command.  If so, then buffer-file-name is
probably being changed and needs to be updated."
  (if (equal (car (car command-history)) 'write-file)
    (abbreviate-mode-line-buffer-identification)))

;; string-replace-regexp and string-replace-regexps are also defined
;; in my tools, where they belong.  This file is not always loaded,
;; though.

(defun string-replace-regexp (s re to-s)
"Return STRING after replacing all successive instances of REGEXP
with TO-STRING.  See replace-regexp."
  (save-excursion
    (set-buffer (get-buffer-create " *temporary*"))
    ;; Note the space here ---------^, making the buffer `invisible'.
    (erase-buffer)
    (insert s)
    (goto-char (point-min))
    (replace-regexp re to-s)
    (buffer-string)))

(defun string-replace-regexps (s al)
"Return STRING after replacing all successive instances of regexp cars
of ALIST with to-string cdrs."
  (save-excursion
    (set-buffer (get-buffer-create " *temporary*"))
    (erase-buffer)
    (insert s)
    (mapcar '(lambda (el) (goto-char (point-min))
			  (replace-regexp (car el) (cdr el)))
	    al)
    (buffer-string)))
----------------------------------------------------------------------


As to your problem that you posted, 
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> ;; I'd like this, but I get an error on argument type of
> ;; "char-or-string-p" when it runs.  Any help?
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> (defvar file-name-abbreviation-alist
>   '(
>     ((format "^%s" (getenv "HOME")) . "~")
>     ((format "^%s" (getenv "TOOLS")) . "<TOOLS>")
                     ^^^^^^^^^^^^^^^^
>     )

The arrowed portion is probably what's causing you problems.  If the
envariable TOOLS was not set at the time that emacs was invoked, then
`getenv'ing it should return nil, which is neither a char nor a
string.  NG.  Either mention the path explicitly, or setenv TOOLS
before starting emacs.		 ___
				 \o/
			  Cheers, V [Ag]
				 _|_

		  LOOKING FOR GNU EMACS DEVELOPMENT
 Andy Gaynor   201-545-0458   81 Hassart St, New Brunswick, NJ 08901
   gaynor@topaz.rutgers.edu   ...!rutgers!topaz.rutgers.edu!gaynor
       "There is no Editor but Emacs, and Lisp is its Prophet."

klm@cme-durer.ARPA (Ken Manheimer) (02/18/88)

In article <MW4rYsy00WAIyc00P7@andrew.cmu.edu> jk3k+@ANDREW.CMU.EDU ("Joseph G. Keane") writes:
>Use:
>(defvar file-name-abbreviation-alist
>  (list
>    (cons (format "^%s" (getenv "HOME")) "~")
>    (cons (format "^%s" (getenv "TOOLS")) "<TOOLS>")))
>
>(I bet this looks pretty random if you don't know Lisp.)
>
>--Joe

It's funny; just yesterday i was scrambling around gnuEmacs with
someone who was just learning to maneuver around the editor and its
elisp, and he pointed out a particularly fine little suite of mutually
circular definitions.  Of course, it was the fundamental (and most
beguilingly named) lisp functions that were being "defined".

The quest started with a question about 'assq' and alists; referring
to describe-function, we get:

assq:
Returns non-nil if ELT is the car of an element of LIST.  Comparison
done with eq. The value is actually the element of LIST whose car is ELT.

Well, ok, but if you're a spanking brand new beginner, you're going to
wonder about 'car'.  If you know lisp, you know 'car' means "first
element of a list (or nil for nil)" (or, "Contents of the Accumulator
Register", historically speaking...).

However, if you once again resort to emacs' helping hand,

car:
Return the car of CONSCELL.  If arg is nil, return nil.

Hmm.  CONSCELL.  We've seen 'cons' around, right?  What about that
one?

cons:
Create a new cons, give it CAR and CDR as components, and return it.

Oh, that's much better.  How about cdr?

cdr:
Return the cdr of CONSCELL.  If arg is nil, return nil.

I know that emacs help is not intended to provide a tutorial for or
introduction to lisp.  If you don't have some idea about the list data
structure and its accessors and CONStructors, you ought to start
elsewhere; however i think it's at least a little amusing how
blatantly circular these definitions are.  I mean, the definition for
'cdr' above provides some info about what happens for the boundary
condition nil, but it doesn't say anything about the error that's
provoked when a non-list expression is provided to cdr, and saying
that cdr returns "the cdr of CONSCELL" is *not* an example of a
recursive def, but instead a vacuous one.

Would it hurt, eg for 'cdr', to say something to the effect of "nil
for a null list, the portion of a list after the first element, or
else an error"?  I expect that some such more informative (though less
formal) description might help answer questions like the one Barry
asks, about the difference between 'append' and 'cons'.  (Btw, is this
phrasing sound for dotted pairs?)  Or is the idea specifically to send
the novice scrambling for a real Lisp manual?

Ken Manheimer	 klm@cme-durer.arpa	or	..!uunet!cme-durer.arpa!klm

"For without the inner the outer loses its meaning; and without the
outer, the inner loses its substance."			  R.D.Laing

mayer@hplabsz.HPL.HP.COM (Niels Mayer) (02/22/88)

In article <232@stylus.cme-durer.ARPA> klm@cme-amrf.arpa (Ken Manheimer) writes:
>If you don't have some idea about the list data
>structure and its accessors and CONStructors, you ought to start
>elsewhere; however i think it's at least a little amusing how
>blatantly circular these definitions are.

But the definitions of cons, car and cdr are supposed to be implicitly
circular -- it's often easiest to think of them in terms of a
"decomposition property" that defines all three terms at once:
		x == (cons (car x) (cdr x))

jr@PEBBLES.BBN.COM (John Robinson) (03/22/88)

Ken described trying to find definitions of cons, car and cdr.  I went
to the source (John McCarthy, "Recursive Functions of Symbolic
Expressions and Their Computation by Machine," CACM v. 3 pp. 184-195,
April 1960, as reprinted in Saul Rosen, _Programming Systems and
Languages_, McGraw-Hill, 1967).  I think his definition makes it
pretty apparent what is meant by a cons cell, and also what the origin
of car and cdr are:

  {\it car.}  Computing car [x] involves getting the _c_ontents of the
  _a_ddress part of the _r_egister x.  This is essentially
  accomplished by the single instruction CLA 0, i, where the argument
  is the index register i, and the result appears in the address part
  of the accumulator.  (We take the view that the places from which a
  function takes its arguments and into which it puts the results are
  prescribed in the definition of the function, and it is the
  responsibility of the programmer or the compiler to insert the
  required data-moving instructions to get the results of one
  calculation in postion for the next.)  ("car" stands for "_c_ontents
  of the _a_ddress part of _r_egister.")

  {\it cdr.}  cdr is handled in the same way as car, except that the
  result appears in the decrement part of the accumulator.  ("cdr"
  stands for "_c_ontents of the _d_ecrement part of _r_egister.")

  {\it cons.}  The value of cons [x; y] must be the location of a
  register that has x and y in its address part and decrement part,
  respectively.  There may not be such a register in the computer and,
  even if there were, it would be time-consuming to find it.
  Actually, what we do is to take the first available register from
  the {\it free-storage list,} put x and y in the address part and
  decrement part, respectively, and make the value of the function the
  location of the register taken.  ("cons" is an abbreviation for
  "construct.")

  It is the subroutine for cons that initiates the reclamation when
  the free-storage list is exhausted.  In the version of the system
  that is used at present cons is represented by a closed subroutine.
  In the compiled version, cons is open.  ["open" means "in-line" -
  jr]

This description sounds quaint at first, but in fact it is very
precise and, though a little circular, conveys the necessary
information.  LISP was the first language where the distinction
between use and mention (value and name) was so visible, and it made
for difficulty in getting definitions right.

LISP originally ran on the IBM 704 at the MIT AI Lab.  "Address part"
and "Decrement part" refer to the way the 704 did address and index
arithmetic.  It was a 36-bit machine, and the two parts were the
18-bit word halfs (plenty to address the whole machine!).  Love of
36-bit-ness has persisted in the LISP world to this day.

/jr
jr@bbn.com or jr@bbn.uucp