comparison lisp/hyperbole/hargs.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 ;;!emacs
2 ;;
3 ;; FILE: hargs.el
4 ;; SUMMARY: Obtains user input through Emacs for Hyperbole
5 ;; USAGE: GNU Emacs Lisp Library
6 ;; KEYWORDS: extensions, hypermedia
7 ;;
8 ;; AUTHOR: Bob Weiner
9 ;; ORG: Brown U.
10 ;;
11 ;; ORIG-DATE: 31-Oct-91 at 23:17:35
12 ;; LAST-MOD: 11-Sep-95 at 16:34:32 by Bob Weiner
13 ;;
14 ;; This file is part of Hyperbole.
15 ;; Available for use and distribution under the same terms as GNU Emacs.
16 ;;
17 ;; Copyright (C) 1991-1995, Free Software Foundation, Inc.
18 ;; Developed with support from Motorola Inc.
19 ;;
20 ;; DESCRIPTION:
21 ;;
22 ;; This module should be used for any interactive prompting and
23 ;; argument reading that Hyperbole does through Emacs.
24 ;;
25 ;; 'hargs:iform-read' provides a complete Lisp-based replacement for
26 ;; interactive argument reading (most of what 'call-interactively' does).
27 ;; It also supports prompting for new argument values with defaults drawn
28 ;; from current button arguments. A few extensions to interactive argument
29 ;; types are also provided, see 'hargs:iforms-extensions' for details.
30 ;;
31 ;; DESCRIP-END.
32
33 ;;; ************************************************************************
34 ;;; Other required Elisp libraries
35 ;;; ************************************************************************
36
37 (require 'hpath)
38 (require 'set)
39
40 ;;; ************************************************************************
41 ;;; Public variables
42 ;;; ************************************************************************
43
44 (defvar hargs:reading-p nil
45 "t only when Hyperbole is prompting user for input, else nil.")
46
47 ;;; ************************************************************************
48 ;;; Public functions
49 ;;; ************************************************************************
50
51 (defun hargs:actype-get (actype &optional modifying)
52 "Interactively gets and returns list of arguments for ACTYPE's parameters.
53 Current button is being modified when MODIFYING is non-nil."
54 (hargs:action-get (actype:action actype) modifying))
55
56 (defun hargs:at-p (&optional no-default)
57 "Returns thing at point, if of hargs:reading-p type, or default.
58 If optional argument NO-DEFAULT is non-nil, nil is returned instead of any
59 default values.
60
61 Caller should have checked whether an argument is presently being read
62 and set 'hargs:reading-p' to an appropriate argument type.
63 Handles all of the interactive argument types that 'hargs:iform-read' does."
64 (cond ((and (eq hargs:reading-p 'kcell)
65 (eq major-mode 'kotl-mode)
66 (not (looking-at "^$")))
67 (kcell-view:label))
68 ((and (eq hargs:reading-p 'klink)
69 (not (looking-at "^$")))
70 (if (eq major-mode 'kotl-mode)
71 (kcell-view:reference
72 nil (and (boundp 'default-dir) default-dir))
73 (let ((hargs:reading-p 'file))
74 (list (hargs:at-p)))))
75 ((eolp) nil)
76 ((and (eq hargs:reading-p 'hmenu)
77 (eq (selected-window) (minibuffer-window)))
78 (save-excursion
79 (char-to-string
80 (if (search-backward " " nil t)
81 (progn (skip-chars-forward " ")
82 (following-char))
83 0))))
84 ((hargs:completion t))
85 ((eq hargs:reading-p 'ebut) (ebut:label-p 'as-label))
86 ((ebut:label-p) nil)
87 ((eq hargs:reading-p 'file)
88 (cond ((hpath:at-p nil 'non-exist))
89 ((eq major-mode 'dired-mode)
90 (let ((file (dired-get-filename nil t)))
91 (and file (hpath:absolute-to file))))
92 ((eq major-mode 'monkey-mode)
93 (let ((file (monkey-filename t)))
94 (and file (hpath:absolute-to file))))
95 ;; Delimited file name.
96 ((hpath:at-p 'file))
97 ;; Unquoted remote file name.
98 ((hpath:is-p (hpath:ange-ftp-at-p) 'file))
99 (no-default nil)
100 ((buffer-file-name))
101 ))
102 ((eq hargs:reading-p 'directory)
103 (cond ((hpath:at-p 'directory 'non-exist))
104 ((eq major-mode 'dired-mode)
105 (let ((dir (dired-get-filename nil t)))
106 (and dir (setq dir (hpath:absolute-to dir))
107 (file-directory-p dir) dir)))
108 ((eq major-mode 'monkey-mode)
109 (let ((dir (monkey-filename t)))
110 (and dir (setq dir (hpath:absolute-to dir))
111 (file-directory-p dir) dir)))
112 ;; Delimited directory name.
113 ((hpath:at-p 'directory))
114 ;; Unquoted remote directory name.
115 ((hpath:is-p (hpath:ange-ftp-at-p) 'directory))
116 (no-default nil)
117 (default-directory)
118 ))
119 ((eq hargs:reading-p 'string)
120 (or (hargs:delimited "\"" "\"") (hargs:delimited "'" "'")
121 (hargs:delimited "`" "'")
122 ))
123 ((or (eq hargs:reading-p 'actype)
124 (eq hargs:reading-p 'actypes))
125 (let ((name (find-tag-default)))
126 (car (set:member name (htype:names 'actypes)))))
127 ((or (eq hargs:reading-p 'ibtype)
128 (eq hargs:reading-p 'ibtypes))
129 (let ((name (find-tag-default)))
130 (car (set:member name (htype:names 'ibtypes)))))
131 ((eq hargs:reading-p 'sexpression) (hargs:sexpression-p))
132 ((eq hargs:reading-p 'Info-node)
133 (and (eq major-mode 'Info-mode)
134 (let ((file (hpath:relative-to Info-current-file
135 Info-directory)))
136 (and (stringp file) (string-match "^\\./" file)
137 (setq file (substring file (match-end 0))))
138 (concat "(" file ")" Info-current-node))))
139 ((eq hargs:reading-p 'mail)
140 (and (hmail:reader-p) buffer-file-name
141 (prin1-to-string (list (rmail:msg-id-get) buffer-file-name))))
142 ((eq hargs:reading-p 'symbol)
143 (let ((sym (find-tag-default)))
144 (if (or (fboundp sym) (boundp sym)) sym)))
145 ((eq hargs:reading-p 'buffer)
146 (find-tag-default))
147 ((eq hargs:reading-p 'character)
148 (following-char))
149 ((eq hargs:reading-p 'key)
150 (require 'hib-kbd)
151 (let ((key-seq (hbut:label-p 'as-label "{" "}")))
152 (and key-seq (kbd-key:normalize key-seq))))
153 ((eq hargs:reading-p 'integer)
154 (save-excursion (skip-chars-backward "-0-9")
155 (if (looking-at "-?[0-9]+")
156 (read (current-buffer)))))
157 ))
158
159 (defun hargs:completion (&optional no-insert)
160 "If in the completions buffer, return completion at point. Also insert unless optional NO-INSERT is non-nil.
161 Insert in minibuffer if active or in other window if minibuffer is inactive."
162 (interactive '(nil))
163 (if (or (equal (buffer-name) "*Completions*") ;; V19
164 (equal (buffer-name) " *Completions*")) ;; V18
165 (let ((opoint (point))
166 (owind (selected-window)))
167 (if (re-search-backward "^\\|[ \t][ \t]" nil t)
168 (let ((insert-window
169 (cond ((> (minibuffer-depth) 0)
170 (minibuffer-window))
171 ((not (eq (selected-window) (next-window nil)))
172 (next-window nil))))
173 (bury-completions)
174 (entry))
175 (skip-chars-forward " \t")
176 (if (and insert-window (looking-at "[^\t\n]+"))
177 (progn (setq entry (buffer-substring (match-beginning 0)
178 (match-end 0)))
179 (select-window insert-window)
180 (let ((str (buffer-substring
181 (point)
182 (save-excursion (beginning-of-line)
183 (point)))))
184 (if (and (eq (selected-window) (minibuffer-window)))
185 ;; If entry matches tail of minibuffer prefix
186 ;; already, then return minibuffer contents
187 ;; as entry.
188 (progn
189 (setq entry
190 (if (string-match
191 (concat
192 (regexp-quote entry) "\\'")
193 str)
194 str
195 (concat
196 (if (string-match
197 "/[^/]+\\'" str)
198 (substring
199 str 0 (1+ (match-beginning 0)))
200 str)
201 entry)))
202 (or no-insert (if entry (insert entry)))
203 )
204 ;; In buffer, non-minibuffer completion.
205 ;; Only insert entry if last buffer line does
206 ;; not end in entry.
207 (cond (no-insert)
208 ((or (string-match
209 (concat
210 (regexp-quote entry) "\\'") str)
211 (null entry))
212 (setq bury-completions t))
213 (t (insert entry)))
214 ))))
215 (select-window owind) (goto-char opoint)
216 (if bury-completions
217 (progn (bury-buffer nil) (delete-window)))
218 entry)))))
219
220 (defun hargs:iform-read (iform &optional modifying)
221 "Reads action arguments according to IFORM, a list with car = 'interactive.
222 Optional MODIFYING non-nil indicates current button is being modified, so
223 button's current values should be presented as defaults. Otherwise, uses
224 hargs:defaults as list of defaults, if any.
225 See also documentation for 'interactive'."
226 ;; This is mostly a translation of 'call-interactively' to Lisp.
227 ;;
228 ;; Save this now, since use of minibuffer will clobber it.
229 (setq prefix-arg current-prefix-arg)
230 (if (not (and (listp iform) (eq (car iform) 'interactive)))
231 (error
232 "(hargs:iform-read): arg must be a list whose car = 'interactive.")
233 (setq iform (car (cdr iform)))
234 (if (or (null iform) (and (stringp iform) (equal iform "")))
235 nil
236 (let ((prev-reading-p hargs:reading-p))
237 (unwind-protect
238 (progn
239 (setq hargs:reading-p t)
240 (if (not (stringp iform))
241 (let ((defaults (if modifying
242 (hattr:get 'hbut:current 'args)
243 (and (boundp 'hargs:defaults)
244 (listp hargs:defaults)
245 hargs:defaults)
246 )))
247 (eval iform))
248 (let ((i 0) (start 0) (end (length iform))
249 (ientry) (results) (val) (default)
250 (defaults (if modifying
251 (hattr:get 'hbut:current 'args)
252 (and (boundp 'hargs:defaults)
253 (listp hargs:defaults)
254 hargs:defaults)
255 )))
256 ;;
257 ;; Handle special initial interactive string chars.
258 ;;
259 ;; '*' means error if buffer is read-only.
260 ;; Notion of when action cannot be performed due to
261 ;; read-only buffer is view-specific, so here, we just
262 ;; ignore a read-only specification since it is checked for
263 ;; earlier by any ebut edit code.
264 ;;
265 ;; '@' means select window of last mouse event.
266 ;;
267 ;; '_' means keep region in same state (active or inactive)
268 ;; after this command. (XEmacs only.)
269 ;;
270 (while (cond
271 ((eq (aref iform i) ?*))
272 ((eq (aref iform i) ?@)
273 (hargs:select-event-window)
274 t)
275 ((eq (aref iform i) ?_)
276 (setq zmacs-region-stays t)))
277 (setq i (1+ i) start i))
278 ;;
279 (while (and (< start end)
280 (string-match "\n\\|\\'" iform start))
281 (setq start (match-end 0)
282 ientry (substring iform i (match-beginning 0))
283 i start
284 default (car defaults)
285 default (if (or (null default) (stringp default))
286 default
287 (prin1-to-string default))
288 val (hargs:get ientry default (car results))
289 defaults (cdr defaults)
290 results (cond ((or (null val) (not (listp val)))
291 (cons val results))
292 ;; Is a list of args?
293 ((eq (car val) 'args)
294 (append (nreverse (cdr val)) results))
295 (t;; regular list value
296 (cons val results)))))
297 (nreverse results))))
298 (setq hargs:reading-p prev-reading-p))))))
299
300 (defun hargs:read (prompt &optional predicate default err val-type)
301 "PROMPTs without completion for a value matching PREDICATE and returns it.
302 PREDICATE is an optional boolean function of one argument. Optional DEFAULT
303 is a string to insert after PROMPT as the default return value. Optional
304 ERR is a string to display temporarily when an invalid value is given.
305 Optional VAL-TYPE is a symbol indicating type of value to be read. If
306 VAL-TYPE is not equal to 'sexpression' or 'klink' and is non-nil, value is
307 returned as a string."
308 (let ((bad-val) (val) (stringify)
309 (prev-reading-p hargs:reading-p) (read-func)
310 (owind (selected-window))
311 (obuf (current-buffer)))
312 (unwind-protect
313 (progn
314 (cond ((or (null val-type) (eq val-type 'sexpression))
315 (setq read-func 'read-minibuffer
316 hargs:reading-p 'sexpression))
317 (t (setq read-func 'read-string hargs:reading-p val-type
318 stringify t)))
319 (while (progn (and default (not (stringp default))
320 (setq default (prin1-to-string default)))
321 (condition-case ()
322 (or bad-val
323 (setq val (funcall read-func prompt default)))
324 (error (setq bad-val t)))
325 (if bad-val t
326 (and stringify
327 ;; Remove any double quoting of strings.
328 (string-match
329 "\\`\"\\([^\"]*\\)\"\\'" val)
330 (setq val (substring val (match-beginning 1)
331 (match-end 1))))
332 (and predicate (not (funcall predicate val)))))
333 (if bad-val (setq bad-val nil) (setq default val))
334 (beep)
335 (if err (progn (message err) (sit-for 3))))
336 val)
337 (setq hargs:reading-p prev-reading-p)
338 (select-window owind)
339 (switch-to-buffer obuf)
340 )))
341
342 (defun hargs:read-match (prompt table &optional
343 predicate must-match default val-type)
344 "PROMPTs with completion for a value in TABLE and returns it.
345 TABLE is an alist where each element's car is a string, or it may be an
346 obarray for symbol-name completion.
347 Optional PREDICATE limits table entries to match against.
348 Optional MUST-MATCH means value returned must be from TABLE.
349 Optional DEFAULT is a string inserted after PROMPT as default value.
350 Optional VAL-TYPE is a symbol indicating type of value to be read."
351 (if (and must-match (null table))
352 nil
353 (let ((prev-reading-p hargs:reading-p)
354 (completion-ignore-case t)
355 (owind (selected-window))
356 (obuf (current-buffer)))
357 (unwind-protect
358 (progn
359 (setq hargs:reading-p (or val-type t))
360 (completing-read prompt table predicate must-match default))
361 (setq hargs:reading-p prev-reading-p)
362 (select-window owind)
363 (switch-to-buffer obuf)
364 ))))
365
366 (defun hargs:select-p (&optional value assist-flag)
367 "Returns optional VALUE or value selected at point if any, else nil.
368 If value is the same as the contents of the minibuffer, it is used as
369 the current minibuffer argument, otherwise, the minibuffer is erased
370 and value is inserted there.
371 Optional ASSIST-FLAG non-nil triggers display of Hyperbole menu item help when
372 appropriate."
373 (if (and (> (minibuffer-depth) 0) (or value (setq value (hargs:at-p))))
374 (let ((owind (selected-window)) (back-to)
375 (str-value (and value (format "%s" value))))
376 (unwind-protect
377 (progn
378 (select-window (minibuffer-window))
379 (set-buffer (window-buffer (minibuffer-window)))
380 (cond
381 ;; Selecting a menu item
382 ((eq hargs:reading-p 'hmenu)
383 (if assist-flag (setq hargs:reading-p 'hmenu-help))
384 (hui:menu-enter str-value))
385 ;; Use value for parameter.
386 ((string= str-value (buffer-string))
387 (exit-minibuffer))
388 ;; Clear minibuffer and insert value.
389 (t (setq buffer-read-only nil)
390 (erase-buffer) (insert str-value)
391 (setq back-to t)))
392 value)
393 (if back-to (select-window owind))))))
394
395 ;;; ************************************************************************
396 ;;; Private functions
397 ;;; ************************************************************************
398
399 ;;; From etags.el, so don't have to load the whole thing.
400 (or (fboundp 'find-tag-default)
401 (defun find-tag-default ()
402 (or (and (boundp 'find-tag-default-hook)
403 (not (memq find-tag-default-hook '(nil find-tag-default)))
404 (condition-case data
405 (funcall find-tag-default-hook)
406 (error
407 (message "value of find-tag-default-hook signalled error: %s"
408 data)
409 (sit-for 1)
410 nil)))
411 (save-excursion
412 (if (not (memq (char-syntax (preceding-char)) '(?w ?_)))
413 (while (not (looking-at "\\sw\\|\\s_\\|\\'"))
414 (forward-char 1)))
415 (while (looking-at "\\sw\\|\\s_")
416 (forward-char 1))
417 (if (re-search-backward "\\sw\\|\\s_" nil t)
418 (regexp-quote
419 (progn (forward-char 1)
420 (buffer-substring (point)
421 (progn (forward-sexp -1)
422 (while (looking-at "\\s'")
423 (forward-char 1))
424 (point)))))
425 nil)))))
426
427 (defun hargs:action-get (action modifying)
428 "Interactively gets list of arguments for ACTION's parameters.
429 Current button is being modified when MODIFYING is non-nil.
430 Returns nil if ACTION is not a list or byte-code object, has no interactive
431 form or takes no arguments."
432 (and (or (hypb:v19-byte-code-p action) (listp action))
433 (let ((interactive-form (action:commandp action)))
434 (if interactive-form
435 (action:path-args-rel
436 (hargs:iform-read interactive-form modifying))))))
437
438 (defun hargs:delimited (start-delim end-delim
439 &optional start-regexp-flag end-regexp-flag)
440 "Returns a single line, delimited argument that point is within, or nil.
441 START-DELIM and END-DELIM are strings that specify the argument delimiters.
442 With optional START-REGEXP-FLAG non-nil, START-DELIM is treated as a regular
443 expression. END-REGEXP-FLAG is similar."
444 (let* ((opoint (point))
445 (limit (if start-regexp-flag opoint
446 (+ opoint (1- (length start-delim)))))
447 (start-search-func (if start-regexp-flag 're-search-forward
448 'search-forward))
449 (end-search-func (if end-regexp-flag 're-search-forward
450 'search-forward))
451 start end)
452 (save-excursion
453 (beginning-of-line)
454 (while (and (setq start (funcall start-search-func start-delim limit t))
455 (< (point) opoint)
456 ;; This is not to find the real end delimiter but to find
457 ;; end delimiters that precede the current argument and are
458 ;; therefore false matches, hence the search is limited to
459 ;; prior to the original point.
460 (funcall end-search-func end-delim opoint t))
461 (setq start nil))
462 (if start
463 (progn
464 (end-of-line) (setq limit (1+ (point)))
465 (goto-char opoint)
466 (and (funcall end-search-func end-delim limit t)
467 (setq end (match-beginning 0))
468 (buffer-substring start end)))))))
469
470 (defun hargs:get (interactive-entry &optional default prior-arg)
471 "Prompts for an argument, if need be, from INTERACTIVE-ENTRY, a string.
472 Optional DEFAULT is inserted after prompt.
473 First character of INTERACTIVE-ENTRY must be a command character from
474 the list in the documentation for 'interactive' or a `+' which indicates that
475 the following character is a Hyperbole interactive extension command
476 character.
477
478 May return a single value or a list of values, in which case the first
479 element of the list is always the symbol 'args."
480 (let (func cmd prompt)
481 (cond ((or (null interactive-entry) (equal interactive-entry ""))
482 (error "(hargs:get): Empty interactive-entry arg."))
483 ((= (aref interactive-entry 0) ?+)
484 ;; Hyperbole / user extension command character. The next
485 ;; character is the actual command character.
486 (setq cmd (aref interactive-entry 1)
487 prompt (format (substring interactive-entry 2) prior-arg)
488 func (if (< cmd (length hargs:iform-extensions-vector))
489 (aref hargs:iform-extensions-vector cmd)))
490 (if func
491 (funcall func prompt default)
492 (error
493 "(hargs:get): Bad interactive-entry extension character: '%c'."
494 cmd)))
495 (t (setq cmd (aref interactive-entry 0)
496 prompt
497 (format (substring interactive-entry 1) prior-arg)
498 func (if (< cmd (length hargs:iform-vector))
499 (aref hargs:iform-vector cmd)))
500 (if func
501 (funcall func prompt default)
502 (error
503 "(hargs:get): Bad interactive-entry command character: '%c'."
504 cmd))))))
505
506 (defun hargs:make-iform-vector (iform-alist)
507 "Return a vector built from IFORM-ALIST used for looking up interactive command code characters."
508 ;; Vector needs to have 1 more elts than the highest char code for
509 ;; interactive commands.
510 (let* ((size (1+ (car (sort (mapcar 'car iform-alist) '>))))
511 (vec (make-vector size nil)))
512 (mapcar (function
513 (lambda (elt)
514 (aset vec (car elt)
515 (` (lambda (prompt default)
516 (setq hargs:reading-p '(, (car (cdr elt))))
517 (, (cdr (cdr elt))))))))
518 iform-alist)
519 vec))
520
521 (defun hargs:prompt (prompt default &optional default-prompt)
522 "Returns string of PROMPT including DEFAULT.
523 Optional DEFAULT-PROMPT is used to describe default value."
524 (if default
525 (format "%s(%s%s%s) " prompt (or default-prompt "default")
526 (if (equal default "") "" " ")
527 default)
528 prompt))
529
530 (defun hargs:select-event-window ()
531 "Select window, if any, that mouse was over during last event."
532 (if hyperb:lemacs-p
533 (if current-mouse-event
534 (select-window
535 (or (event-window current-mouse-event)
536 (selected-window))))
537 (let* ((event last-command-event)
538 (window (posn-window (event-start event))))
539 (if (and (eq window (minibuffer-window))
540 (not (minibuffer-window-active-p
541 (minibuffer-window))))
542 (error "Attempt to select inactive minibuffer window")
543 (select-window
544 (or window (selected-window)))))))
545
546 (defun hargs:sexpression-p (&optional no-recurse)
547 "Returns an sexpression at point as a string.
548 If point follows an sexpression end character, the preceding sexpression
549 is returned. If point precedes an sexpression start character, the
550 following sexpression is returned. Otherwise, the innermost sexpression
551 that point is within is returned or nil if none."
552 (save-excursion
553 (condition-case ()
554 (let ((not-quoted
555 '(not (and (= (char-syntax (char-after (- (point) 2))) ?\\)
556 (/= (char-syntax (char-after (- (point) 3))) ?\\)))))
557 (cond ((and (= (char-syntax (preceding-char)) ?\))
558 ;; Ignore quoted end chars.
559 (eval not-quoted))
560 (buffer-substring (point)
561 (progn (forward-sexp -1) (point))))
562 ((and (= (char-syntax (following-char)) ?\()
563 ;; Ignore quoted begin chars.
564 (eval not-quoted))
565 (buffer-substring (point)
566 (progn (forward-sexp) (point))))
567 (no-recurse nil)
568 (t (save-excursion (up-list 1) (hargs:sexpression-p t)))))
569 (error nil))))
570
571 ;;; ************************************************************************
572 ;;; Private variables
573 ;;; ************************************************************************
574
575 (defvar hargs:iforms nil
576 "Alist of (interactive-cmd-chr . (argument-type . get-argument-form)) elts.")
577 (setq hargs:iforms
578 '(
579 ;; Get function symbol.
580 (?a . (symbol .
581 (intern (completing-read prompt obarray 'fboundp t default))))
582 ;; Get name of existing buffer.
583 (?b . (buffer .
584 (progn
585 (or default (setq default (other-buffer (current-buffer))))
586 (read-buffer prompt default t))))
587 ;; Get name of possibly nonexistent buffer.
588 (?B . (buffer .
589 (progn
590 (or default (setq default (other-buffer (current-buffer))))
591 (read-buffer prompt default nil))))
592 ;; Get character.
593 (?c . (character .
594 (progn (message
595 (if default
596 (hargs:prompt prompt
597 (if (integerp default)
598 (char-to-string default)
599 default)
600 "Curr:")
601 prompt))
602 (char-to-string (read-char)))))
603 ;; Get symbol for interactive function, a command.
604 (?C . (symbol .
605 (intern
606 (completing-read prompt obarray 'commandp t default))))
607 ;; Get value of point; does not do I/O.
608 (?d . (integer . (point)))
609 ;; Get directory name.
610 (?D . (directory .
611 (progn
612 (or default (setq default default-directory))
613 (read-file-name prompt default default 'existing))))
614 ;; Get existing file name.
615 (?f . (file .
616 (read-file-name prompt default default
617 (if (eq system-type 'vax-vms)
618 nil 'existing))))
619 ;; Get possibly nonexistent file name.
620 (?F . (file . (read-file-name prompt default default nil)))
621 ;; Get key sequence.
622 (?k . (key .
623 (key-description (read-key-sequence
624 (if default
625 (hargs:prompt prompt default "Curr:")
626 prompt)))))
627 ;; Get key sequence without converting uppercase or shifted
628 ;; function keys to their unshifted equivalents.
629 (?K . (key .
630 (key-description (read-key-sequence
631 (if default
632 (hargs:prompt prompt default "Curr:")
633 prompt)
634 nil t))))
635 ;; Get value of mark. Does not do I/O.
636 (?m . (integer . (marker-position (hypb:mark-marker t))))
637 ;; Get numeric prefix argument or a number from the minibuffer.
638 (?N . (integer .
639 (if prefix-arg
640 (prefix-numeric-value prefix-arg)
641 (let ((arg))
642 (while (not (integerp
643 (setq arg (read-minibuffer prompt default))))
644 (beep))
645 arg))))
646 ;; Get number from minibuffer.
647 (?n . (integer .
648 (let ((arg))
649 (while (not (integerp
650 (setq arg (read-minibuffer prompt default))))
651 (beep))
652 arg)))
653 ;; Get numeric prefix argument. No I/O.
654 (?p . (prefix-arg .
655 (prefix-numeric-value prefix-arg)))
656 ;; Get prefix argument in raw form. No I/O.
657 (?P . (prefix-arg . prefix-arg))
658 ;; Get region, point and mark as 2 args. No I/O
659 (?r . (region .
660 (if (marker-position (hypb:mark-marker t))
661 (list 'args (min (point) (hypb:mark t))
662 (max (point) (hypb:mark t)))
663 (list 'args nil nil))))
664 ;; Get string.
665 (?s . (string . (read-string prompt default)))
666 ;; Get symbol.
667 (?S . (symbol .
668 (read-from-minibuffer
669 prompt default minibuffer-local-ns-map 'sym)))
670 ;; Get variable name: symbol that is user-variable-p.
671 (?v . (symbol . (read-variable
672 (if default
673 (hargs:prompt prompt default "Curr:")
674 prompt))))
675 ;; Get Lisp expression but don't evaluate.
676 (?x . (sexpression . (read-minibuffer prompt default)))
677 ;; Get Lisp expression and evaluate.
678 (?X . (sexpression . (eval-minibuffer prompt default)))
679 ))
680
681 (defvar hargs:iform-vector nil
682 "Vector of forms for each interactive command character code.")
683 (setq hargs:iform-vector (hargs:make-iform-vector hargs:iforms))
684
685 (defvar hargs:iforms-extensions nil
686 "Hyperbole extension alist of (interactive-cmd-chr . (argument-type . get-argument-form)) elts.")
687 (setq hargs:iforms-extensions
688 '(
689 ;; Get existing Info node name and file.
690 (?I . (Info-node .
691 (let (file)
692 (require 'info)
693 (hargs:read
694 prompt
695 (function
696 (lambda (node)
697 (and (string-match "^(\\([^\)]+\\))" node)
698 (setq file (substring node (match-beginning 1)
699 (match-end 1)))
700 (memq t (mapcar
701 (function
702 (lambda (dir)
703 (file-readable-p
704 (hpath:absolute-to file dir))))
705 (if (boundp 'Info-directory-list)
706 Info-directory-list
707 (list Info-directory))
708 )))))
709 default
710 "(hargs:read): Use (readable-filename)nodename."
711 'Info-node))))
712 ;; Get kcell from koutline.
713 (?K . (kcell . (hargs:read prompt nil default nil 'kcell)))
714 ;; Get kcell or path reference for use in a link.
715 (?L . (klink . (hargs:read prompt nil default nil 'klink)))
716 ;; Get existing mail msg date and file.
717 (?M . (mail . (progn
718 (while
719 (or (not (listp
720 (setq default
721 (read-minibuffer
722 (hargs:prompt
723 prompt ""
724 "list of (date mail-file)")
725 default))))
726 (/= (length default) 2)
727 (not (and (stringp (car (cdr default)))
728 (file-exists-p
729 (car (cdr default))))))
730 (beep))
731 default)))))
732
733 (defvar hargs:iform-extensions-vector nil
734 "Vector of forms for each interactive command character code.")
735 (setq hargs:iform-extensions-vector
736 (hargs:make-iform-vector hargs:iforms-extensions))
737
738 (provide 'hargs)