comparison lisp/comint/history.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children b82b59fe008d
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 ;; Copyright (C) 1989 Free Software Foundation, Inc.
2
3 ;; This file is part of XEmacs.
4
5 ;; XEmacs is free software; you can redistribute it and/or modify it
6 ;; under the terms of the GNU General Public License as published by
7 ;; the Free Software Foundation; either version 2, or (at your option)
8 ;; any later version.
9
10 ;; XEmacs is distributed in the hope that it will be useful, but
11 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
12 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 ;; General Public License for more details.
14
15 ;; You should have received a copy of the GNU General Public License
16 ;; along with XEmacs; see the file COPYING. If not, write to the Free
17 ;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 ;; suggested generic history stuff -- tale
20
21 ;; This is intended to provided easy access to a list of elements
22 ;; being kept as a history ring.
23
24 ;; To use, variables for a list and the index to it need to be kept, and
25 ;; a limit to how large the list can grow. Short wrappers can than be provided
26 ;; to interact with these functions.
27
28 ;; For example, a typical application of this is in interactive processes,
29 ;; like shell or gdb. A history can be kept of commands that are sent
30 ;; to the process so that they are easily retrieved for re-inspection or
31 ;; re-use. Using process "foo" to illustrate:
32
33 ;; Variable foo-history will be the list. foo-history-index would be the
34 ;; pointer to the current item within the list; it is based with 0 being
35 ;; the most recent element added to the list. foo-history-size can be a
36 ;; user-variable which controls how many items are allowed to exist.
37
38 ;; The following functions could interactive with the list; foo-mark
39 ;; in these examples trackes the end of output from foo-process.
40
41 ;; (defun foo-history-previous (arg) ;; Suggested binding: C-c C-p
42 ;; "Retrieve the previous command sent to the foo process.
43 ;; ARG means to select that message out of the list (0 is the first)."
44 ;; (interactive "P")
45 ;; (history-fetch 'foo-history 'foo-history-index (or arg 'previous)
46 ;; foo-mark (point-max)))
47
48 ;; foo-history-next would look practically the same, but substituting "next"
49 ;; for "previous". Suggested binding: C-c C-n
50
51 ;; (defun foo-history-clear () ;; Suggested binding: C-c C-u
52 ;; "Clear the input region for the foo-process and reset history location."
53 ;; (interactive)
54 ;; (delete-region foo-mark (goto-char (point-max))))
55
56 ;; To get the history on the stack, an extremely minimal function would look
57 ;; something like this, probably bound to RET:
58
59 ;; (defun foo-send ()
60 ;; "Send a command to foo-process."
61 ;; (interactive)
62 ;; (let ((str (buffer-substring foo-mark (goto-char (point-max)))))
63 ;; (insert ?\C-j)
64 ;; (setq foo-history-index -1) ; reset the index
65 ;; (set-marker foo-mark (point))
66 ;; (send-string foo-process str)
67 ;; (history-add 'foo-history str foo-history-size)))
68
69 ;; ToDo: history-isearch
70
71 (provide 'history)
72
73 (defvar history-last-search ""
74 "The last regexp used by history-search which resulted in a match.")
75
76 (defun history-add (list item size)
77 "At the head of LIST append ITEM. Limit the length of LIST to SIZE elements.
78 LIST should be the name of the list."
79 (set list (append (list item) (eval list)))
80 (let ((elist (eval list)))
81 (if (> (length elist) size)
82 (setcdr (nthcdr (1- size) elist) nil))))
83
84 (defun history-fetch (list index dir &optional beg end)
85 "Retrieve an entry from LIST, working from INDEX in direction DIR.
86 LIST should be the name of the list, for message purposes. INDEX should be
87 the name of the variable used to index the list, so it can be maintained.
88 DIR non-nil means to use previous entry, unless it is the symbol ``next''
89 to get the next entry or a number to get an absolute reference. DIR
90 nil is equivalent to ``next''.
91
92 If optional numeric argument BEG is preset, it is taken as the point to insert
93 the entry in the current buffer, leaving point at the start of the entry.
94 If followed by a numeric END, the region between BEG and END will be deleted
95 before the entry is inserted."
96 (let (str (eind (eval index)) (elist (eval list)))
97 (cond
98 ((numberp dir)
99 (setq str (nth dir elist))
100 (if str (set index dir) (message "No entry %d in %s." dir list)))
101 ((or (not dir) (eq dir 'next))
102 (if (= eind -1)
103 (message "No next entry in %s." list)
104 (set index (1- eind))
105 (setq str (if (zerop eind) "" (nth (1- eind) elist)))))
106 (t
107 (if (>= (1+ eind) (length elist))
108 (message "No previous entry in %s." list)
109 (set index (1+ eind))
110 (setq str (nth (1+ eind) elist)))))
111 (if (not (and (integer-or-marker-p beg) str)) ()
112 (if (integer-or-marker-p end) (delete-region beg end))
113 (insert str)
114 (goto-char beg))
115 str))
116
117 (defun history-search (list index dir regexp &optional beg end)
118 "In history LIST, starting at INDEX and working in direction DIR, find REGEXP.
119 LIST and INDEX should be their respective symbol names. DIR nil or 'forward
120 means to search from the current index toward the most recent history entry.
121 DIR non-nil means to search toward the oldest entry. The current entry is
122 not checked in either case.
123
124 If an entry is found and optional numeric argument BEG exists then the entry
125 will be inserted there and point left at BEG. If numeric END also exists
126 then the region will be deleted between BEG and END."
127 (let* ((forw (or (not dir) (eq dir 'forward))) str found
128 (eind (eval index))
129 (elist (eval list))
130 (slist (if forw
131 (nthcdr (- (length elist) eind) (reverse elist))
132 (nthcdr (1+ eind) elist))))
133 (while (and (not found) slist)
134 (if (string-match regexp (car slist))
135 (setq found (car slist)
136 history-last-search regexp))
137 (setq eind (+ (if forw -1 1) eind)
138 slist (cdr slist)))
139 (if (not found)
140 (error "\"%s\" not found %s in %s"
141 regexp (if forw "forward" "backward") list)
142 (set index eind)
143 (if (not (integer-or-marker-p beg)) ()
144 (if (integer-or-marker-p end) (delete-region beg end))
145 (insert found)
146 (goto-char beg)))
147 found))
148
149 (defun history-menu (list buffer &optional notemp)
150 "Show the history kept by LIST in BUFFER.
151 This function will use ``with-output-to-temp-buffer'' unless optional third
152 argument NOTEMP is non-nil."
153 (let ((pop-up-windows t) (line 0)
154 (menu
155 (mapconcat (function (lambda (item)
156 (setq line (1+ line))
157 (format (format "%%%dd: %%s"
158 (int-to-string (length list)))
159 line item)))
160 list "\n")))
161 (if notemp
162 (save-excursion
163 (insert menu)
164 (display-buffer buffer))
165 (with-output-to-temp-buffer buffer (princ menu)))))