Mercurial > emacs
annotate lisp/emacs-lisp/backquote.el @ 1717:aa7d6d57504b
* frame.h (struct frame): New fields `can_have_scrollbars' and
`has_vertical_scrollbars'.
(FRAME_CAN_HAVE_SCROLLBARS, FRAME_HAS_VERTICAL_SCROLLBARS): New
accessors, for both the MULTI_FRAME and non-MULTI_FRAME.
(VERTICAL_SCROLLBAR_WIDTH, WINDOW_VERTICAL_SCROLLBAR,
WINDOW_VERTICAL_SCROLLBAR_COLUMN,
WINDOW_VERTICAL_SCROLLBAR_HEIGHT): New macros.
* window.h (struct window): New field `vertical_scrollbar'.
* xterm.h (struct x_display): vertical_scrollbars,
judge_timestamp, vertical_scrollbar_extra: New fields.
(struct scrollbar): New struct.
(VERTICAL_SCROLLBAR_PIXEL_WIDTH, VERTICAL_SCROLLBAR_PIXEL_HEIGHT,
VERTICAL_SCROLLBAR_LEFT_BORDER, VERTICAL_SCROLLBAR_RIGHT_BORDER,
VERTICAL_SCROLLBAR_TOP_BORDER, VERTICAL_SCROLLBAR_BOTTOM_BORDER,
CHAR_TO_PIXEL_WIDTH, CHAR_TO_PIXEL_HEIGHT, PIXEL_TO_CHAR_WIDTH,
PIXEL_TO_CHAR_HEIGHT): New accessors and macros.
* frame.c (make_frame): Initialize the `can_have_scrollbars' and
`has_vertical_scrollbars' fields of the frame.
* term.c (term_init): Note that TERMCAP terminals don't support
scrollbars.
(mouse_position_hook): Document new args.
(set_vertical_scrollbar_hook, condemn_scrollbars_hook,
redeem_scrollbar_hook, judge_scrollbars_hook): New hooks.
* termhooks.h: Declare and document them.
(enum scrollbar_part): New type.
(struct input_event): Describe the new form of the scrollbar_click
event type. Change `part' from a Lisp_Object to an enum
scrollbar_part. Add a new field `scrollbar'.
* keyboard.c (kbd_buffer_get_event): Pass appropriate new
parameters to *mouse_position_hook, and make_lispy_movement.
* xfns.c (x_set_vertical_scrollbar): New function.
(x_figure_window_size): Use new macros to calculate frame size.
(Fx_create_frame): Note that X Windows frames do support scroll
bars. Default to "yes".
* xterm.c: #include <X11/cursorfont.h> and "window.h".
(x_vertical_scrollbar_cursor): New variable.
(x_term_init): Initialize it.
(last_mouse_bar, last_mouse_bar_frame, last_mouse_part,
last_mouse_scroll_range_start, last_mouse_scroll_range_end): New
variables.
(XTmouse_position): Use them to return scrollbar movement events.
Take new arguments, for that purpose.
(x_window_to_scrollbar, x_scrollbar_create,
x_scrollbar_set_handle, x_scrollbar_remove, x_scrollbar_move,
XTset_scrollbar, XTcondemn_scrollbars, XTredeem_scrollbar,
XTjudge_scrollbars, x_scrollbar_expose,
x_scrollbar_background_expose, x_scrollbar_handle_click,
x_scrollbar_handle_motion): New functions to implement scrollbars.
(x_term_init): Set the termhooks.h hooks to point to them.
(x_set_window_size): Use new macros to calculate frame size. Set
vertical_scrollbar_extra field.
(x_make_frame_visible): Use the frame accessor
FRAME_HAS_VERTICAL_SCROLLBARS to decide if we need to map the
frame's subwindows as well.
(XTread_socket): Use new size-calculation macros from xterm.h when
processing ConfigureNotify events.
(x_wm_set_size_hint): Use PIXEL_TO_CHAR_WIDTH and
PIXEL_TO_CHAR_HEIGHT macros.
* ymakefile (xdisp.o): This now depends on termhooks.h.
(xterm.o): This now depends on window.h.
| author | Jim Blandy <jimb@redhat.com> |
|---|---|
| date | Thu, 24 Dec 1992 06:17:18 +0000 |
| parents | ab73b8d8243c |
| children | bd3c525fa6fc |
| rev | line source |
|---|---|
|
662
8a533acedb77
*** empty log message ***
Eric S. Raymond <esr@snark.thyrsus.com>
parents:
584
diff
changeset
|
1 ;; backquote.el --- backquoting for Emacs Lisp macros |
|
8a533acedb77
*** empty log message ***
Eric S. Raymond <esr@snark.thyrsus.com>
parents:
584
diff
changeset
|
2 |
| 845 | 3 ;; Copyright (C) 1985 Free Software Foundation, Inc. |
| 4 | |
|
807
4f28bd14272c
*** empty log message ***
Eric S. Raymond <esr@snark.thyrsus.com>
parents:
662
diff
changeset
|
5 ;; Author: Dick King (king@kestrel). |
|
811
e694e0879463
*** empty log message ***
Eric S. Raymond <esr@snark.thyrsus.com>
parents:
807
diff
changeset
|
6 ;; Keywords: extensions |
|
807
4f28bd14272c
*** empty log message ***
Eric S. Raymond <esr@snark.thyrsus.com>
parents:
662
diff
changeset
|
7 |
| 181 | 8 ;; This file is part of GNU Emacs. |
| 9 | |
| 10 ;; GNU Emacs is free software; you can redistribute it and/or modify | |
| 11 ;; it under the terms of the GNU General Public License as published by | |
|
807
4f28bd14272c
*** empty log message ***
Eric S. Raymond <esr@snark.thyrsus.com>
parents:
662
diff
changeset
|
12 ;; the Free Software Foundation; either version 2, or (at your option) |
| 181 | 13 ;; any later version. |
| 14 | |
| 15 ;; GNU Emacs is distributed in the hope that it will be useful, | |
| 16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 18 ;; GNU General Public License for more details. | |
| 19 | |
| 20 ;; You should have received a copy of the GNU General Public License | |
| 21 ;; along with GNU Emacs; see the file COPYING. If not, write to | |
| 22 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | |
| 23 | |
|
807
4f28bd14272c
*** empty log message ***
Eric S. Raymond <esr@snark.thyrsus.com>
parents:
662
diff
changeset
|
24 ;;; Commentary: |
| 181 | 25 |
|
807
4f28bd14272c
*** empty log message ***
Eric S. Raymond <esr@snark.thyrsus.com>
parents:
662
diff
changeset
|
26 ;;; This is a rudimentry backquote package written by D. King, |
| 181 | 27 ;;; king@kestrel, on 8/31/85. (` x) is a macro |
| 28 ;;; that expands to a form that produces x. (` (a b ..)) is | |
| 29 ;;; a macro that expands into a form that produces a list of what a b | |
| 30 ;;; etc. would have produced. Any element can be of the form | |
| 31 ;;; (, <form>) in which case the resulting form evaluates | |
| 32 ;;; <form> before putting it into place, or (,@ <form>), in which | |
| 33 ;;; case the evaluation of <form> is arranged for and each element | |
| 34 ;;; of the result (which must be a (possibly null) list) is inserted. | |
| 35 ;;; As an example, the immediately following macro push (v l) could | |
| 36 ;;; have been written | |
| 37 ;;; (defmacro push (v l) | |
| 38 ;;; (` (setq (, l) (cons (,@ (list v l)))))) | |
| 39 ;;; although | |
| 40 ;;; (defmacro push (v l) | |
| 41 ;;; (` (setq (, l) (cons (, v) (, l))))) | |
| 42 ;;; is far more natural. The magic atoms , | |
| 43 ;;; and ,@ are user-settable and list-valued. We recommend that | |
| 44 ;;; things never be removed from this list lest you break something | |
| 45 ;;; someone else wrote in the dim past that comes to be recompiled in | |
| 46 ;;; the distant future. | |
| 47 | |
| 48 ;;; LIMITATIONS: tail consing is not handled correctly. Do not say | |
| 49 ;;; (` (a . (, b))) - say (` (a (,@ b))) | |
| 50 ;;; which works even if b is not list-valued. | |
| 51 ;;; No attempt is made to handle vectors. (` [a (, b) c]) doesn't work. | |
| 52 ;;; Sorry, you must say things like | |
| 53 ;;; (` (a (,@ 'b))) to get (a . b) and | |
| 54 ;;; (` ((, ',) c)) to get (, c) - [(` (a , b)) will work but is a bad habit] | |
| 55 ;;; I haven't taught it the joys of nconc. | |
| 56 ;;; (` atom) dies. (` (, atom)) or anything else is okay. | |
| 57 | |
| 58 ;;; BEWARE BEWARE BEWARE | |
| 59 ;;; inclusion of (,atom) rather than (, atom) or (,@atom) rather than | |
| 60 ;;; (,@ atom) will result in errors that will show up very late. | |
| 61 ;;; This is so crunchy that I am considering including a check for | |
| 62 ;;; this or changing the syntax to ... ,(<form>). RMS: opinion? | |
| 63 | |
|
807
4f28bd14272c
*** empty log message ***
Eric S. Raymond <esr@snark.thyrsus.com>
parents:
662
diff
changeset
|
64 ;;; Code: |
| 181 | 65 |
| 66 ;;; a raft of general-purpose macros follows. See the nearest | |
| 67 ;;; Commonlisp manual. | |
| 68 (defmacro bq-push (v l) | |
| 69 "Pushes evaluated first form onto second unevaluated object | |
| 70 a list-value atom" | |
| 71 (list 'setq l (list 'cons v l))) | |
| 72 | |
| 73 (defmacro bq-caar (l) | |
| 74 (list 'car (list 'car l))) | |
| 75 | |
| 76 (defmacro bq-cadr (l) | |
| 77 (list 'car (list 'cdr l))) | |
| 78 | |
| 79 (defmacro bq-cdar (l) | |
| 80 (list 'cdr (list 'car l))) | |
| 81 | |
| 82 | |
| 83 ;;; These two advertised variables control what characters are used to | |
| 84 ;;; unquote things. I have included , and ,@ as the unquote and | |
| 85 ;;; splice operators, respectively, to give users of MIT CADR machine | |
| 86 ;;; derivitive machines a warm, cosy feeling. | |
| 87 | |
| 88 (defconst backquote-unquote '(,) | |
| 89 "*A list of all objects that stimulate unquoting in `. Memq test.") | |
| 90 | |
| 91 | |
| 92 (defconst backquote-splice '(,@) | |
| 93 "*A list of all objects that stimulate splicing in `. Memq test.") | |
| 94 | |
| 95 | |
| 96 ;;; This is the interface | |
| 256 | 97 ;;;###autoload |
| 181 | 98 (defmacro ` (form) |
| 99 "(` FORM) is a macro that expands to code to construct FORM. | |
| 100 Note that this is very slow in interpreted code, but fast if you compile. | |
| 101 FORM is one or more nested lists, which are `almost quoted': | |
| 102 They are copied recursively, with non-lists used unchanged in the copy. | |
| 103 (` a b) == (list 'a 'b) constructs a new list with two elements, `a' and `b'. | |
| 104 (` a (b c)) == (list 'a (list 'b 'c)) constructs two nested new lists. | |
| 105 | |
| 106 However, certain special lists are not copied. They specify substitution. | |
| 107 Lists that look like (, EXP) are evaluated and the result is substituted. | |
| 108 (` a (, (+ x 5))) == (list 'a (+ x 5)) | |
| 109 | |
| 110 Elements of the form (,@ EXP) are evaluated and then all the elements | |
| 111 of the result are substituted. This result must be a list; it may | |
| 112 be `nil'. | |
| 113 | |
| 114 As an example, a simple macro `push' could be written: | |
| 115 (defmacro push (v l) | |
| 116 (` (setq (, l) (cons (,@ (list v l)))))) | |
| 117 or as | |
| 118 (defmacro push (v l) | |
| 119 (` (setq (, l) (cons (, v) (, l))))) | |
| 120 | |
| 121 LIMITATIONS: \"dotted lists\" are not allowed in FORM. | |
| 122 The ultimate cdr of each list scanned by ` must be `nil'. | |
| 123 \(This does not apply to constants inside expressions to be substituted.) | |
| 124 | |
| 125 Substitution elements are not allowed as the cdr | |
| 126 of a cons cell. For example, (` (A . (, B))) does not work. | |
| 127 Instead, write (` (A (,@ B))). | |
| 128 | |
| 129 You cannot construct vectors, only lists. Vectors are treated as | |
| 130 constants. | |
| 131 | |
| 132 BEWARE BEWARE BEWARE | |
| 133 Inclusion of (,ATOM) rather than (, ATOM) | |
| 134 or of (,@ATOM) rather than (,@ ATOM) | |
| 135 will result in errors that will show up very late." | |
| 136 (bq-make-maker form)) | |
| 137 | |
| 138 ;;; We develop the method for building the desired list from | |
| 139 ;;; the end towards the beginning. The contract is that there be a | |
| 140 ;;; variable called state and a list called tailmaker, and that the form | |
| 141 ;;; (cons state tailmaker) deliver the goods. Exception - if the | |
| 142 ;;; state is quote the tailmaker is the form itself. | |
| 143 ;;; This function takes a form and returns what I will call a maker in | |
| 144 ;;; what follows. Evaluating the maker would produce the form, | |
| 145 ;;; properly evaluated according to , and ,@ rules. | |
| 146 ;;; I work backwards - it seemed a lot easier. The reason for this is | |
| 147 ;;; if I'm in some sort of a routine building a maker and I switch | |
| 148 ;;; gears, it seemed to me easier to jump into some other state and | |
| 149 ;;; glue what I've already done to the end, than to to prepare that | |
| 150 ;;; something and go back to put things together. | |
| 151 (defun bq-make-maker (form) | |
| 1234 | 152 "Given argument FORM, a `mostly quoted' object, produces a maker. |
| 181 | 153 See backquote.el for details" |
| 154 (let ((tailmaker (quote nil)) (qc 0) (ec 0) (state nil)) | |
| 155 (mapcar 'bq-iterative-list-builder (reverse form)) | |
| 156 (and state | |
| 157 (cond ((eq state 'quote) | |
| 340 | 158 (list state (if (equal form tailmaker) form tailmaker))) |
| 181 | 159 ((= (length tailmaker) 1) |
| 160 (funcall (bq-cadr (assq state bq-singles)) tailmaker)) | |
| 161 (t (cons state tailmaker)))))) | |
| 162 | |
| 163 ;;; There are exceptions - we wouldn't want to call append of one | |
| 164 ;;; argument, for example. | |
| 165 (defconst bq-singles '((quote bq-quotecar) | |
| 166 (append car) | |
| 167 (list bq-make-list) | |
| 168 (cons bq-id))) | |
| 169 | |
| 170 (defun bq-id (x) x) | |
| 171 | |
| 172 (defun bq-quotecar (x) (list 'quote (car x))) | |
| 173 | |
| 174 (defun bq-make-list (x) (cons 'list x)) | |
| 175 | |
| 176 ;;; fr debugging use only | |
| 177 ;(defun funcalll (a b) (funcall a b)) | |
| 178 ;(defun funcalll (a b) (debug nil 'enter state tailmaker a b) | |
| 179 ; (let ((ans (funcall a b))) (debug nil 'leave state tailmaker) | |
| 180 ; ans)) | |
| 181 | |
| 182 ;;; Given a state/tailmaker pair that already knows how to make a | |
| 183 ;;; partial tail of the desired form, this function knows how to add | |
| 184 ;;; yet another element to the burgening list. There are four cases; | |
| 185 ;;; the next item is an atom (which will certainly be quoted); a | |
| 186 ;;; (, xxx), which will be evaluated and put into the list at the top | |
| 187 ;;; level; a (,@ xxx), which will be evaluated and spliced in, or | |
| 188 ;;; some other list, in which case we first compute the form's maker, | |
| 189 ;;; and then we either launch into the quoted case if the maker's | |
| 190 ;;; top level function is quote, or into the comma case if it isn't. | |
| 191 ;;; The fourth case reduces to one of the other three, so here we have | |
| 192 ;;; a choice of three ways to build tailmaker, and cit turns out we | |
| 193 ;;; use five possible values of state (although someday I'll add | |
| 194 ;;; nconcto the possible values of state). | |
| 195 ;;; This maintains the invariant that (cons state tailmaker) is the | |
| 196 ;;; maker for the elements of the tail we've eaten so far. | |
| 197 (defun bq-iterative-list-builder (form) | |
| 198 (cond ((atom form) | |
| 199 (funcall (bq-cadr (assq state bq-quotefns)) form)) | |
| 200 ((memq (car form) backquote-unquote) | |
| 201 (funcall (bq-cadr (assq state bq-evalfns)) (bq-cadr form))) | |
| 202 ((memq (car form) backquote-splice) | |
| 203 (funcall (bq-cadr (assq state bq-splicefns)) (bq-cadr form))) | |
| 204 (t | |
| 205 (let ((newform (bq-make-maker form))) | |
| 206 (if (and (listp newform) (eq (car newform) 'quote)) | |
| 207 (funcall (bq-cadr (assq state bq-quotefns)) (bq-cadr newform)) | |
| 208 (funcall (bq-cadr (assq state bq-evalfns)) newform)))) | |
| 209 )) | |
| 210 | |
| 211 ;;; We do a 2-d branch on the form of splicing and the old state. | |
| 212 ;;; Here's fifteen functions' names... | |
| 213 (defconst bq-splicefns '((nil bq-splicenil) | |
| 214 (append bq-spliceappend) | |
| 215 (list bq-splicelist) | |
| 216 (quote bq-splicequote) | |
| 217 (cons bq-splicecons))) | |
| 218 | |
| 219 (defconst bq-evalfns '((nil bq-evalnil) | |
| 220 (append bq-evalappend) | |
| 221 (list bq-evallist) | |
| 222 (quote bq-evalquote) | |
| 223 (cons bq-evalcons))) | |
| 224 | |
| 225 (defconst bq-quotefns '((nil bq-quotenil) | |
| 226 (append bq-quoteappend) | |
| 227 (list bq-quotelist) | |
| 228 (quote bq-quotequote) | |
| 229 (cons bq-quotecons))) | |
| 230 | |
| 231 ;;; The name of each function is | |
| 232 ;;; (concat 'bq- <type-of-element-addition> <old-state>) | |
| 233 ;;; I'll comment the non-obvious ones before the definitions... | |
| 234 ;;; In what follows, uppercase letters and form will always be | |
| 235 ;;; metavariables that don't need commas in backquotes, and I will | |
| 236 ;;; assume the existence of something like matches that takes a | |
| 237 ;;; backquote-like form and a value, binds metavariables and returns | |
| 238 ;;; t if the pattern match is successful, returns nil otherwise. I | |
| 239 ;;; will write such a goodie someday. | |
| 240 | |
| 241 ;;; (setq tailmaker | |
| 242 ;;; (if (matches ((quote X) Y) tailmaker) | |
| 243 ;;; (` ((quote (form X)) Y)) | |
| 244 ;;; (` ((list form (quote X)) Y)))) | |
| 245 ;;; (setq state 'append) | |
| 246 (defun bq-quotecons (form) | |
| 247 (if (and (listp (car tailmaker)) | |
| 248 (eq (bq-caar tailmaker) 'quote)) | |
| 249 (setq tailmaker | |
| 250 (list (list 'quote (list form (bq-cadr (car tailmaker)))) | |
| 251 (bq-cadr tailmaker))) | |
| 252 (setq tailmaker | |
| 253 (list (list 'list | |
| 254 (list 'quote form) | |
| 255 (car tailmaker)) | |
| 256 (bq-cadr tailmaker)))) | |
| 257 (setq state 'append)) | |
| 258 | |
| 259 (defun bq-quotequote (form) | |
| 260 (bq-push form tailmaker)) | |
| 261 | |
| 262 ;;; Could be improved to convert (list 'a 'b 'c .. 'w x) | |
| 263 ;;; to (append '(a b c .. w) x) | |
| 264 ;;; when there are enough elements | |
| 265 (defun bq-quotelist (form) | |
| 266 (bq-push (list 'quote form) tailmaker)) | |
| 267 | |
| 268 ;;; (setq tailmaker | |
| 269 ;;; (if (matches ((quote X) (,@ Y))) | |
| 270 ;;; (` ((quote (, (cons form X))) (,@ Y))))) | |
| 271 (defun bq-quoteappend (form) | |
| 272 (cond ((and (listp tailmaker) | |
| 273 (listp (car tailmaker)) | |
| 274 (eq (bq-caar tailmaker) 'quote)) | |
| 275 (rplaca (bq-cdar tailmaker) | |
| 276 (cons form (car (bq-cdar tailmaker))))) | |
| 277 (t (bq-push (list 'quote (list form)) tailmaker)))) | |
| 278 | |
| 279 (defun bq-quotenil (form) | |
| 280 (setq tailmaker (list form)) | |
| 281 (setq state 'quote)) | |
| 282 | |
| 283 ;;; (if (matches (X Y) tailmaker) ; it must | |
| 284 ;;; (` ((list form X) Y))) | |
| 285 (defun bq-evalcons (form) | |
| 286 (setq tailmaker | |
| 287 (list (list 'list form (car tailmaker)) | |
| 288 (bq-cadr tailmaker))) | |
| 289 (setq state 'append)) | |
| 290 | |
| 291 ;;; (if (matches (X Y Z (,@ W))) | |
| 292 ;;; (progn (setq state 'append) | |
| 293 ;;; (` ((list form) (quote (X Y Z (,@ W)))))) | |
| 294 ;;; (progn (setq state 'list) | |
| 295 ;;; (list form 'X 'Y .. ))) ; quote each one there is | |
| 296 (defun bq-evalquote (form) | |
| 297 (cond ((< (length tailmaker) 3) | |
| 298 (setq tailmaker | |
| 299 (cons form | |
| 300 (mapcar (function (lambda (x) | |
| 301 (list 'quote x))) | |
| 302 tailmaker))) | |
| 303 (setq state 'list)) | |
| 304 (t | |
| 305 (setq tailmaker | |
| 306 (list (list 'list form) | |
| 307 (list 'quote tailmaker))) | |
| 308 (setq state 'append)))) | |
| 309 | |
| 310 (defun bq-evallist (form) | |
| 311 (bq-push form tailmaker)) | |
| 312 | |
| 313 ;;; (cond ((matches ((list (,@ X)) (,@ Y))) | |
| 314 ;;; (` ((list form (,@ X)) (,@ Y)))) | |
| 315 ;;; ((matches (X)) | |
| 316 ;;; (` (form (,@ X))) (setq state 'cons)) | |
| 317 ;;; ((matches ((,@ X))) | |
| 318 ;;; (` (form (,@ X))))) | |
| 319 (defun bq-evalappend (form) | |
| 320 (cond ((and (listp tailmaker) | |
| 321 (listp (car tailmaker)) | |
| 322 (eq (bq-caar tailmaker) 'list)) | |
| 323 (rplacd (car tailmaker) | |
| 324 (cons form (bq-cdar tailmaker)))) | |
| 325 ((= (length tailmaker) 1) | |
| 326 (setq tailmaker (cons form tailmaker) | |
| 327 state 'cons)) | |
| 328 (t (bq-push (list 'list form) tailmaker)))) | |
| 329 | |
| 330 (defun bq-evalnil (form) | |
| 331 (setq tailmaker (list form) | |
| 332 state 'list)) | |
| 333 | |
| 334 ;;; (if (matches (X Y)) ; it must | |
| 335 ;;; (progn (setq state 'append) | |
| 336 ;;; (` (form (cons X Y))))) ; couldn't think of anything clever | |
| 337 (defun bq-splicecons (form) | |
| 338 (setq tailmaker | |
| 339 (list form | |
| 340 (list 'cons (car tailmaker) (bq-cadr tailmaker))) | |
| 341 state 'append)) | |
| 342 | |
| 343 (defun bq-splicequote (form) | |
| 344 (setq tailmaker (list form (list 'quote tailmaker)) | |
| 345 state 'append)) | |
| 346 | |
| 347 (defun bq-splicelist (form) | |
| 348 (setq tailmaker (list form (cons 'list tailmaker)) | |
| 349 state 'append)) | |
| 350 | |
| 351 (defun bq-spliceappend (form) | |
| 352 (bq-push form tailmaker)) | |
| 353 | |
| 354 (defun bq-splicenil (form) | |
| 355 (setq state 'append | |
| 356 tailmaker (list form))) | |
| 584 | 357 |
| 358 (provide 'backquote) | |
| 359 | |
|
662
8a533acedb77
*** empty log message ***
Eric S. Raymond <esr@snark.thyrsus.com>
parents:
584
diff
changeset
|
360 ;;; backquote.el ends here |
