cd2b4a1e01294637b156a84451d700a3a7d19308
[lice.git] / src / lisp / subr.lisp
blobcd2b4a1e01294637b156a84451d700a3a7d19308
1 ;;; subr.lice --- basic lisp subroutines for Emacs
3 (in-package "LICE")
5 ;;; Argument types
7 (defun interactive (&rest prompts)
8 "Read input from the minibuffer and return it in a list."
9 (loop for p in prompts
10 collect (read-from-minibuffer p)))
12 (defvar *extended-command-history* nil)
14 (defun read-command (prompt)
15 "Read the name of a command and return as a symbol.
16 Prompt with prompt. By default, return default-value."
17 (let (cmds)
18 (maphash (lambda (k v)
19 (declare (ignore v))
20 (push k cmds))
21 *commands*)
22 (dformat +debug-v+ "commands: ~s~%" cmds)
23 ;; Sadly, a cheap hack
24 (find (completing-read prompt cmds :history '*extended-command-history*)
25 cmds :test #'string-equal :key #'symbol-name)))
27 (defun read-buffer (prompt &optional def require-match)
28 "Read the name of a buffer and return as a string.
29 Prompt with prompt.
30 Optional second arg def is value to return if user enters an empty line.
31 *If optional third arg require-match is non-nil,
32 * only existing buffer names are allowed."
33 (declare (ignore require-match))
34 (let* ((bufs (mapcar (lambda (b)
35 (cons (buffer-name b) b))
36 *buffer-list*))
37 (b (completing-read (if def
38 (format nil "~a(default ~a) " prompt def)
39 prompt)
40 bufs)))
41 (if (zerop (length b))
42 def
43 b)))
45 (defun read-file-name (prompt &key dir default-filename mustmatch initial predicate)
46 "Read file name, prompting with prompt and completing in directory dir.
47 Value is not expanded---you must call `expand-file-name' yourself.
48 Default name to default-filename if user exits the minibuffer with
49 the same non-empty string that was inserted by this function.
50 (If default-filename is omitted, the visited file name is used,
51 except that if initial is specified, that combined with dir is used.)
52 If the user exits with an empty minibuffer, this function returns
53 an empty string. (This can only happen if the user erased the
54 pre-inserted contents or if `insert-default-directory' is nil.)
55 Fourth arg mustmatch non-nil means require existing file's name.
56 Non-nil and non-t means also require confirmation after completion.
57 Fifth arg initial specifies text to start with.
58 If optional sixth arg predicate is non-nil, possible completions and
59 the resulting file name must satisfy (funcall predicate NAME).
60 dir should be an absolute directory name. It defaults to the value of
61 `:default-directory'.
63 If this command was invoked with the mouse, use a file dialog box if
64 `use-dialog-box' is non-nil, and the window system or X toolkit in use
65 provides a file dialog box.
67 See also `read-file-name-completion-ignore-case'
68 and `read-file-name-function'."
69 (declare (ignore predicate initial mustmatch default-filename dir))
70 (completing-read prompt #'file-completions :initial-input (princ-to-string *default-directory*)))
72 (defun read-string (prompt &optional initial-input history default-value)
73 "Read a string from the minibuffer, prompting with string prompt.
74 If non-nil, second arg initial-input is a string to insert before reading.
75 This argument has been superseded by default-value and should normally
76 be nil in new code. It behaves as in `read-from-minibuffer'. See the
77 documentation string of that function for details.
78 The third arg history, if non-nil, specifies a history list
79 and optionally the initial position in the list.
80 See `read-from-minibuffer' for details of history argument.
81 Fourth arg default-value is the default value. If non-nil, it is used
82 for history commands, and as the value to return if the user enters
83 the empty string.
84 **Fifth arg inherit-input-method, if non-nil, means the minibuffer inherits
85 the current input method and the setting of `enable-multibyte-characters'."
86 (read-from-minibuffer prompt :initial-contents initial-input :history history :default-value default-value))
88 (defun region-limit (beginningp)
89 "Return the start or end position of the region.
90 BEGINNINGP non-zero means return the start.
91 If there is no region active, signal an error."
92 (if beginningp
93 (min (point) (mark))
94 (max (point) (mark))))
96 (defun region-beginning ()
97 "Return position of beginning of region, as an integer."
98 (region-limit t))
100 (defun region-end ()
101 "Return position of end of region, as an integer."
102 (region-limit nil))
104 (defun add-command-arg-type (type fn)
105 "TYPE is a symbol. Add it to the hash table of command types and link it to FN, a function or function symbol."
106 (setf (gethash type *command-arg-type-hash*) fn))
108 (defun init-command-arg-types ()
109 "populate the hash table with some defaults"
110 ;; Reset the hash table. FIXME: should we do this?
111 (setf *command-arg-type-hash* (make-hash-table))
112 (add-command-arg-type :buffer 'read-buffer)
113 (add-command-arg-type :file 'read-file-name)
114 (add-command-arg-type :string 'read-from-minibuffer)
115 (add-command-arg-type :command 'read-command)
116 (add-command-arg-type :prefix 'prefix-arg)
117 (add-command-arg-type :raw-prefix 'raw-prefix-arg)
118 (add-command-arg-type :region-beginning 'region-beginning)
119 (add-command-arg-type :region-end 'region-end))
121 (defun get-buffer-window-list (buffer &optional minibuf frame)
122 "Return list of all windows displaying BUFFER, or nil if none.
123 BUFFER can be a buffer or a buffer name.
124 See `walk-windows' for the meaning of MINIBUF and FRAME."
125 (let ((buffer (if (bufferp buffer) buffer (get-buffer buffer))) windows)
126 (mapc (lambda (window)
127 (if (eq (window-buffer window) buffer)
128 (push window windows)))
129 (frame-window-list frame minibuf))
130 windows))
132 ;; FIXME: this isn't complete.
133 (defmacro defalias (from-symbol to-symbol)
134 "Set symbol's function definition to definition, and return definition."
135 `(define-symbol-macro ,from-symbol ,to-symbol))
137 (defun intern-soft (name &optional (package *package*))
138 (find-symbol name package))
140 ;;; reading from the buffer
142 (defun read-from-buffer (&aux (buffer (current-buffer)))
143 "Read 1 sexp from the buffer at the current point, moving the point to the end of what was read"
144 (when (< (buffer-char-to-aref buffer (point buffer))
145 (buffer-gap-start buffer))
146 (gap-move-to-point buffer))
147 (multiple-value-bind (obj pos)
148 (read-from-string (buffer-data buffer) t nil
149 :start (buffer-char-to-aref buffer (point buffer)))
150 (set-point (buffer-aref-to-char buffer pos))
151 obj))
153 (defcommand eval-region ((start end &optional print-flag (read-function 'read-from-string))
154 :region-beginning :region-end)
155 "Execute the region as Lisp code.
156 When called from programs, expects two arguments,
157 giving starting and ending indices in the current buffer
158 of the text to be executed.
159 Programs can pass third argument PRINTFLAG which controls output:
160 A value of nil means discard it; anything else is stream for printing it.
161 Also the fourth argument READ-FUNCTION, if non-nil, is used
162 instead of `read' to read each expression. It gets one argument
163 which is the input stream for reading characters.
165 This function does not move point."
166 (let* ((stdout (make-string-output-stream))
167 (*standard-output* stdout)
168 (*error-output* stdout)
169 (*debug-io* stdout)
170 (string (buffer-substring-no-properties start end))
171 (pos 0)
172 last obj)
173 (loop
174 (setf last obj)
175 (multiple-value-setq (obj pos) (funcall read-function string nil string :start pos))
176 (when (eq obj string)
177 (cond ((eq print-flag t)
178 (message "~s" last)))
179 (return-from eval-region last)))))
181 (defun sit-for (seconds &optional nodisp)
182 "Perform redisplay, then wait for seconds seconds or until input is available.
183 seconds may be a floating-point value, meaning that you can wait for a
184 fraction of a second.
185 (Not all operating systems support waiting for a fraction of a second.)
186 Optional arg nodisp non-nil means don't redisplay, just wait for input.
187 Redisplay is preempted as always if input arrives, and does not happen
188 if input is available before it starts.
189 Value is t if waited the full time with no input arriving."
190 (unless nodisp
191 (frame-render (selected-frame)))
192 ;; FIXME: poll for input
193 (sleep seconds)
195 ;; (let ((event (wait-for-event seconds)))
196 ;; (if event
197 ;; (progn
198 ;; (push event *unread-command-events*)
199 ;; nil)
200 ;; t))
204 ;;; Matching and match data
205 (defun match-string (num &optional string)
206 "Return string of text matched by last search.
207 NUM specifies which parenthesized expression in the last regexp.
208 Value is nil if NUMth pair didn't match, or there were less than NUM pairs.
209 Zero means the entire text matched by the whole regexp or whole string.
210 STRING should be given if the last search was by `string-match' on STRING."
211 (if (match-beginning num)
212 (if string
213 (substring string (match-beginning num) (match-end num))
214 (buffer-substring (match-beginning num) (match-end num)))))
216 (defun match-string-no-properties (num &optional string)
217 "Return string of text matched by last search, without text properties.
218 NUM specifies which parenthesized expression in the last regexp.
219 Value is nil if NUMth pair didn't match, or there were less than NUM pairs.
220 Zero means the entire text matched by the whole regexp or whole string.
221 STRING should be given if the last search was by `string-match' on STRING."
222 (if (match-beginning num)
223 (if string
224 (substring-no-properties string (match-beginning num)
225 (match-end num))
226 (buffer-substring-no-properties (match-beginning num)
227 (match-end num)))))
230 (defun force-mode-line-update (&optional all)
231 "Force redisplay of the current buffer's mode line and header line.
232 With optional non-nil ALL, force redisplay of all mode lines and
233 header lines. This function also forces recomputation of the
234 menu bar menus and the frame title."
235 (declare (ignore all))
236 (error "unimplemented")
237 ;; (if all (save-excursion (set-buffer (other-buffer))))
238 ;; (set-buffer-modified-p (buffer-modified-p))
241 (defun add-minor-mode (toggle name &optional keymap after toggle-fun)
242 "Register a new minor mode.
244 This is an XEmacs-compatibility function. Use `define-minor-mode' instead.
246 TOGGLE is a symbol which is the name of a buffer-local variable that
247 is toggled on or off to say whether the minor mode is active or not.
249 NAME specifies what will appear in the mode line when the minor mode
250 is active. NAME should be either a string starting with a space, or a
251 symbol whose value is such a string.
253 Optional KEYMAP is the keymap for the minor mode that will be added
254 to `*minor-mode-map-list*'.
256 Optional AFTER specifies that TOGGLE should be added after AFTER
257 in `*minor-mode-list*'.
259 Optional TOGGLE-FUN is an interactive function to toggle the mode.
260 It defaults to (and should by convention be) TOGGLE.
262 If TOGGLE has a non-nil `:included' property, an entry for the mode is
263 included in the mode-line minor mode menu.
264 If TOGGLE has a `:menu-tag', that is used for the menu item's label."
265 (unless (memq toggle minor-mode-list)
266 (push toggle minor-mode-list))
268 (unless toggle-fun (setq toggle-fun toggle))
269 (unless (eq toggle-fun toggle)
270 (setf (get toggle :minor-mode-function) toggle-fun))
271 ;; Add the name to the *minor-mode-list*.
272 (when name
273 (let ((existing (find toggle *minor-mode-list* :key 'first)))
274 (if existing
275 (setf (cdr existing) (list name))
276 (let ((found (member after *minor-mode-list* :key 'first)))
277 (if found
278 (let ((rest (cdr found)))
279 (setf (cdr found) nil)
280 (nconc found (list (list toggle name)) rest))
281 (push (cons (list toggle name)
282 *minor-mode-list*) *minor-mode-list*))))))
283 ;; FIXME: when menu support is added, use this code
284 ;; ;; Add the toggle to the minor-modes menu if requested.
285 ;; (when (get toggle :included)
286 ;; (define-key mode-line-mode-menu
287 ;; (vector toggle)
288 ;; (list 'menu-item
289 ;; (concat
290 ;; (or (get toggle :menu-tag)
291 ;; (if (stringp name) name (symbol-name toggle)))
292 ;; (let ((mode-name (if (symbolp name) (symbol-value name))))
293 ;; (if (and (stringp mode-name) (string-match "[^ ]+" mode-name))
294 ;; (concat " (" (match-string 0 mode-name) ")"))))
295 ;; toggle-fun
296 ;; :button (cons :toggle toggle))))
298 ;; Add the map to the *minor-mode-map-list*.
299 (when keymap
300 (let ((existing (find toggle *minor-mode-map-list* :key 'minor-mode-map-variable)))
301 (if existing
302 (setf (minor-mode-map-keymap existing) keymap)
303 (let ((found (member after *minor-mode-map-list* :key 'minor-mode-map-variable)))
304 (if found
305 (let ((rest (cdr found)))
306 (setf (cdr found) nil)
307 (nconc found (list (make-minor-mode-map :variable toggle :keymap keymap)) rest))
308 (push (make-minor-mode-map :variable toggle :keymap keymap)
309 *minor-mode-map-list*)))))))
312 (defun replace-regexp-in-string (regexp rep string &optional
313 fixedcase literal subexp start)
314 "Replace all matches for REGEXP with REP in STRING.
316 Return a new string containing the replacements.
318 Optional arguments FIXEDCASE, LITERAL and SUBEXP are like the
319 arguments with the same names of function `replace-match'. If START
320 is non-nil, start replacements at that index in STRING.
322 REP is either a string used as the NEWTEXT arg of `replace-match' or a
323 function. If it is a function, it is called with the actual text of each
324 match, and its value is used as the replacement text. When REP is called,
325 the match-data are the result of matching REGEXP against a substring
326 of STRING.
328 To replace only the first match (if any), make REGEXP match up to \\'
329 and replace a sub-expression, e.g.
330 (replace-regexp-in-string \"\\\\(foo\\\\).*\\\\'\" \"bar\" \" foo foo\" nil nil 1)
331 => \" bar foo\"
334 ;; To avoid excessive consing from multiple matches in long strings,
335 ;; don't just call `replace-match' continually. Walk down the
336 ;; string looking for matches of REGEXP and building up a (reversed)
337 ;; list MATCHES. This comprises segments of STRING which weren't
338 ;; matched interspersed with replacements for segments that were.
339 ;; [For a `large' number of replacements it's more efficient to
340 ;; operate in a temporary buffer; we can't tell from the function's
341 ;; args whether to choose the buffer-based implementation, though it
342 ;; might be reasonable to do so for long enough STRING.]
343 (let ((l (length string))
344 (start (or start 0))
345 matches str mb me)
346 (with-match-data
347 (while (and (< start l) (string-match regexp string start))
348 (setq mb (match-beginning 0)
349 me (match-end 0))
350 ;; If we matched the empty string, make sure we advance by one char
351 (when (= me mb) (setq me (min l (1+ mb))))
352 ;; Generate a replacement for the matched substring.
353 ;; Operate only on the substring to minimize string consing.
354 ;; Set up match data for the substring for replacement;
355 ;; presumably this is likely to be faster than munging the
356 ;; match data directly in Lisp.
357 (string-match regexp (setq str (substring string mb me)))
358 (setq matches
359 (cons (replace-match (if (stringp rep)
361 (funcall rep (match-string 0 str)))
362 fixedcase literal str subexp)
363 (cons (substring string start mb) ; unmatched prefix
364 matches)))
365 (setq start me))
366 ;; Reconstruct a string from the pieces.
367 (setq matches (cons (substring string start l) matches)) ; leftover
368 (apply #'concat (nreverse matches)))))
371 ;;;; Key binding commands.
373 (defcommand global-set-key ((key command)
374 (:key "Set key globally: ")
375 (:command "Set key ~a to command: "))
376 "Give KEY a global binding as COMMAND.
377 COMMAND is the command definition to use; usually it is
378 a symbol naming an interactively-callable function.
379 KEY is a key sequence; noninteractively, it is a string or vector
380 of characters or event types, and non-ASCII characters with codes
381 above 127 (such as ISO Latin-1) can be included if you use a vector.
383 Note that if KEY has a local binding in the current buffer,
384 that local binding will continue to shadow any global binding
385 that you make with this function."
386 ;;(interactive "KSet key globally: \nCSet key %s to command: ")
387 (or (vectorp key) (stringp key) (symbolp key) (clickp key)
388 (signal 'wrong-type-argument :type (list 'arrayp key)))
389 (define-key (current-global-map) key command))
391 (defcommand local-set-key ((key command)
392 (:key "Set key locally: ")
393 (:command "Set key ~a locally to command: "))
394 "Give KEY a local binding as COMMAND.
395 COMMAND is the command definition to use; usually it is
396 a symbol naming an interactively-callable function.
397 KEY is a key sequence; noninteractively, it is a string or vector
398 of characters or event types, and non-ASCII characters with codes
399 above 127 (such as ISO Latin-1) can be included if you use a vector.
401 The binding goes in the current buffer's local map,
402 which in most cases is shared with all other buffers in the same major mode."
403 ;;(interactive "KSet key locally: \nCSet key %s locally to command: ")
404 (let ((map (current-local-map)))
405 (or map
406 (use-local-map (setq map (make-sparse-keymap))))
407 (or (vectorp key) (stringp key)
408 (signal 'wrong-type-argument (list 'arrayp key)))
409 (define-key map key command)))
411 (defun global-unset-key (key)
412 "Remove global binding of KEY.
413 KEY is a string or vector representing a sequence of keystrokes."
414 (interactive "kUnset key globally: ")
415 (global-set-key key nil))
417 (defun local-unset-key (key)
418 "Remove local binding of KEY.
419 KEY is a string or vector representing a sequence of keystrokes."
420 (interactive "kUnset key locally: ")
421 (if (current-local-map)
422 (local-set-key key nil))
423 nil)
426 ;;;; substitute-key-definition and its subroutines.
428 (defvar key-substitution-in-progress nil
429 "Used internally by `substitute-key-definition'.")
431 (defun substitute-key-definition (olddef newdef keymap &optional oldmap prefix)
432 "Replace OLDDEF with NEWDEF for any keys in KEYMAP now defined as OLDDEF.
433 In other words, OLDDEF is replaced with NEWDEF where ever it appears.
434 Alternatively, if optional fourth argument OLDMAP is specified, we redefine
435 in KEYMAP as NEWDEF those keys which are defined as OLDDEF in OLDMAP.
437 If you don't specify OLDMAP, you can usually get the same results
438 in a cleaner way with command remapping, like this:
439 \(define-key KEYMAP [remap OLDDEF] NEWDEF)
440 \n(fn OLDDEF NEWDEF KEYMAP &optional OLDMAP)"
441 ;; Don't document PREFIX in the doc string because we don't want to
442 ;; advertise it. It's meant for recursive calls only. Here's its
443 ;; meaning
445 ;; If optional argument PREFIX is specified, it should be a key
446 ;; prefix, a string. Redefined bindings will then be bound to the
447 ;; original key, with PREFIX added at the front.
448 (or prefix (setq prefix ""))
449 (let* ((scan (or oldmap keymap))
450 (prefix1 (vconcat prefix [nil]))
451 (key-substitution-in-progress
452 (cons scan key-substitution-in-progress)))
453 ;; Scan OLDMAP, finding each char or event-symbol that
454 ;; has any definition, and act on it with hack-key.
455 (map-keymap
456 (lambda (char defn)
457 (aset prefix1 (length prefix) char)
458 (substitute-key-definition-key defn olddef newdef prefix1 keymap))
459 scan)))
461 (defun substitute-key-definition-key (defn olddef newdef prefix keymap)
462 (let (inner-def skipped menu-item)
463 ;; Find the actual command name within the binding.
464 (el:if (eq (car-safe defn) 'menu-item)
465 (setq menu-item defn defn (nth 2 defn))
466 ;; Skip past menu-prompt.
467 (while (stringp (car-safe defn))
468 (push (pop defn) skipped))
469 ;; Skip past cached key-equivalence data for menu items.
470 (if (consp (car-safe defn))
471 (setq defn (cdr defn))))
472 (el:if (or (eq defn olddef)
473 ;; Compare with equal if definition is a key sequence.
474 ;; That is useful for operating on function-key-map.
475 (and (or (stringp defn) (vectorp defn))
476 (equal defn olddef)))
477 (define-key keymap prefix
478 (if menu-item
479 (let ((copy (copy-sequence menu-item)))
480 (setcar (nthcdr 2 copy) newdef)
481 copy)
482 (nconc (nreverse skipped) newdef)))
483 ;; Look past a symbol that names a keymap.
484 (setq inner-def
485 (or (indirect-function defn t) defn))
486 ;; For nested keymaps, we use `inner-def' rather than `defn' so as to
487 ;; avoid autoloading a keymap. This is mostly done to preserve the
488 ;; original non-autoloading behavior of pre-map-keymap times.
489 (if (and (keymapp inner-def)
490 ;; Avoid recursively scanning
491 ;; where KEYMAP does not have a submap.
492 (let ((elt (lookup-key keymap prefix)))
493 (or (null elt) (natnump elt) (keymapp elt)))
494 ;; Avoid recursively rescanning keymap being scanned.
495 (not (memq inner-def key-substitution-in-progress)))
496 ;; If this one isn't being scanned already, scan it now.
497 (substitute-key-definition olddef newdef keymap inner-def prefix)))))
500 (provide :lice-0.1/subr)