Mercurial > hg > xemacs-beta
comparison lisp/gutter-items.el @ 444:576fb035e263 r21-2-37
Import from CVS: tag r21-2-37
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:36:19 +0200 |
parents | abe6d1db359e |
children | 1ccc32a20af4 |
comparison
equal
deleted
inserted
replaced
443:a8296e22da4e | 444:576fb035e263 |
---|---|
45 :set #'(lambda (var val) | 45 :set #'(lambda (var val) |
46 (set-gutter-element-visible-p default-gutter-visible-p | 46 (set-gutter-element-visible-p default-gutter-visible-p |
47 'buffers-tab val) | 47 'buffers-tab val) |
48 (setq gutter-buffers-tab-visible-p val))) | 48 (setq gutter-buffers-tab-visible-p val))) |
49 | 49 |
50 (defcustom gutter-buffers-tab-enabled t | |
51 "*Whether to enable support for buffers tab in the gutter. | |
52 This is different to `gutter-buffers-tab-visible-p' which still runs hooks | |
53 even when the gutter is invisible." | |
54 :group 'buffers-tab | |
55 :type 'boolean) | |
56 | |
50 (defvar gutter-buffers-tab-orientation 'top | 57 (defvar gutter-buffers-tab-orientation 'top |
51 "Where the buffers tab currently is. Do not set this.") | 58 "Where the buffers tab currently is. Do not set this.") |
52 | |
53 (defvar gutter-buffers-tab-extent nil) | |
54 | 59 |
55 (defcustom buffers-tab-max-size 6 | 60 (defcustom buffers-tab-max-size 6 |
56 "*Maximum number of entries which may appear on the \"Buffers\" tab. | 61 "*Maximum number of entries which may appear on the \"Buffers\" tab. |
57 If this is 10, then only the ten most-recently-selected buffers will be | 62 If this is 10, then only the ten most-recently-selected buffers will be |
58 shown. If this is nil, then all buffers will be shown. Setting this to | 63 shown. If this is nil, then all buffers will be shown. Setting this to |
70 :group 'buffers-tab) | 75 :group 'buffers-tab) |
71 | 76 |
72 (defcustom buffers-tab-omit-function 'buffers-menu-omit-invisible-buffers | 77 (defcustom buffers-tab-omit-function 'buffers-menu-omit-invisible-buffers |
73 "*If non-nil, a function specifying the buffers to omit from the buffers tab. | 78 "*If non-nil, a function specifying the buffers to omit from the buffers tab. |
74 This is passed a buffer and should return non-nil if the buffer should be | 79 This is passed a buffer and should return non-nil if the buffer should be |
75 omitted. The default value `buffers-tab-omit-invisible-buffers' omits | 80 omitted. The default value `buffers-menu-omit-invisible-buffers' omits |
76 buffers that are normally considered \"invisible\" (those whose name | 81 buffers that are normally considered \"invisible\" (those whose name |
77 begins with a space)." | 82 begins with a space)." |
78 :type '(choice (const :tag "None" nil) | 83 :type '(choice (const :tag "None" nil) |
79 function) | 84 function) |
80 :group 'buffers-tab) | 85 :group 'buffers-tab) |
86 `select-buffers-tab-buffers-by-mode' groups buffers by major mode and | 91 `select-buffers-tab-buffers-by-mode' groups buffers by major mode and |
87 by `buffers-tab-grouping-regexp'." | 92 by `buffers-tab-grouping-regexp'." |
88 | 93 |
89 :type '(choice (const :tag "None" nil) | 94 :type '(choice (const :tag "None" nil) |
90 function) | 95 function) |
96 :group 'buffers-tab) | |
97 | |
98 (defcustom buffers-tab-filter-functions (list buffers-tab-selection-function) | |
99 "*If non-nil, a list of functions specifying the buffers to select | |
100 from the buffers tab. | |
101 Each function in the list is passed two buffers, the buffer to | |
102 potentially select and the context buffer, and should return non-nil | |
103 if the first buffer should be selected. The default value groups | |
104 buffers by major mode and by `buffers-tab-grouping-regexp'." | |
105 | |
106 :type '(choice (const :tag "None" nil) | |
107 sexp) | |
91 :group 'buffers-tab) | 108 :group 'buffers-tab) |
92 | 109 |
93 (defcustom buffers-tab-sort-function nil | 110 (defcustom buffers-tab-sort-function nil |
94 "*If non-nil, a function specifying the buffers to select from the | 111 "*If non-nil, a function specifying the buffers to select from the |
95 buffers tab. This is passed the buffer list and returns the list in the | 112 buffers tab. This is passed the buffer list and returns the list in the |
157 ;; (switch-to-other-buffer). Things get way confused. | 174 ;; (switch-to-other-buffer). Things get way confused. |
158 (if (> (length (windows-of-buffer buffer)) 0) | 175 (if (> (length (windows-of-buffer buffer)) 0) |
159 (select-window (car (windows-of-buffer buffer))) | 176 (select-window (car (windows-of-buffer buffer))) |
160 (switch-to-buffer buffer)))) | 177 (switch-to-buffer buffer)))) |
161 | 178 |
162 (defun select-buffers-tab-buffers-by-mode (buf1 buf2) | 179 (defun select-buffers-tab-buffers-by-mode (buffer-to-select buf1) |
163 "For use as a value of `buffers-tab-selection-function'. | 180 "For use as a value of `buffers-tab-selection-function'. |
164 This selects buffers by major mode `buffers-tab-grouping-regexp'." | 181 This selects buffers by major mode `buffers-tab-grouping-regexp'." |
165 (let ((mode1 (symbol-name (symbol-value-in-buffer 'major-mode buf1))) | 182 (let ((mode1 (symbol-name (symbol-value-in-buffer 'major-mode buf1))) |
166 (mode2 (symbol-name (symbol-value-in-buffer 'major-mode buf2))) | 183 (mode2 (symbol-name (symbol-value-in-buffer 'major-mode |
184 buffer-to-select))) | |
167 (modenm1 (symbol-value-in-buffer 'mode-name buf1)) | 185 (modenm1 (symbol-value-in-buffer 'mode-name buf1)) |
168 (modenm2 (symbol-value-in-buffer 'mode-name buf2))) | 186 (modenm2 (symbol-value-in-buffer 'mode-name buffer-to-select))) |
169 (cond ((or (eq mode1 mode2) | 187 (cond ((or (eq mode1 mode2) |
170 (eq modenm1 modenm2) | 188 (eq modenm1 modenm2) |
171 (and (string-match "^[^-]+-" mode1) | 189 (and (string-match "^[^-]+-" mode1) |
172 (string-match | 190 (string-match |
173 (concat "^" (regexp-quote | 191 (concat "^" (regexp-quote |
210 (buffer-name buffer)) | 228 (buffer-name buffer)) |
211 :selected selected) | 229 :selected selected) |
212 (when selected (setq selected nil)))) | 230 (when selected (setq selected nil)))) |
213 buffers))) | 231 buffers))) |
214 | 232 |
215 ;;; #### SJT I'd really like this function to have just two hooks: (1) the | 233 ;;; #### SJT would like this function to have a sort function list. I |
216 ;;; buffer filter list and (2) a sort function list. Both should be lists | 234 ;;; don't see how this could work given that sorting is not |
217 ;;; of functions. Each filter takes two arguments: a buffer and a model | 235 ;;; cumulative --andyp. |
218 ;;; buffer. (The model buffer argument allows selecting according to the | |
219 ;;; mode or directory of that buffer.) The filter returns t if the buffer | |
220 ;;; should be listed and nil otherwise. Effectively the filter amounts to | |
221 ;;; the conjuction of the filter list. (Optionally the filter could take a | |
222 ;;; frame instead of a buffer or generalize to a locale as in a specifier?) | |
223 ;;; The filtering is done this way to preserve the ordering imposed by | |
224 ;;; `buffer-list'. In addition, the in-deletion argument will be used the | |
225 ;;; same way as in the current design. | |
226 ;;; The list is checked for length and pruned according to least-recently- | |
227 ;;; selected. (Optionally there could be some kind of sort function here, | |
228 ;;; too.) | |
229 ;;; Finally the list is sorted to gutter display order, and the tab data | |
230 ;;; structure is created and returned. | |
231 ;;; #### Docstring isn't very well expressed. | |
232 (defun buffers-tab-items (&optional in-deletion frame force-selection) | 236 (defun buffers-tab-items (&optional in-deletion frame force-selection) |
233 "This is the tab filter for the top-level buffers \"Buffers\" tab. | 237 "Return a list of tab instantiators based on the current buffers list. |
234 It dynamically creates a list of buffers to use as the contents of the tab. | 238 This function is used as the tab filter for the top-level buffers |
235 Only the most-recently-used few buffers will be listed on the tab, for | 239 \"Buffers\" tab. It dynamically creates a list of tab instantiators |
236 efficiency reasons. You can control how many buffers will be shown by | 240 to use as the contents of the tab. The contents and order of the list |
237 setting `buffers-tab-max-size'. You can control the text of the tab | 241 is controlled by `buffers-tab-filter-functions' which by default |
238 items by redefining the function `format-buffers-menu-line'." | 242 groups buffers according to major mode and removes invisible buffers. |
243 You can control how many buffers will be shown by setting | |
244 `buffers-tab-max-size'. You can control the text of the tab items by | |
245 redefining the function `format-buffers-menu-line'." | |
239 (save-match-data | 246 (save-match-data |
240 (let* ((buffers (delete-if buffers-tab-omit-function (buffer-list frame))) | 247 ;; NB it is too late if we run the omit function as part of the |
248 ;; filter functions because we need to know which buffer is the | |
249 ;; context buffer before they get run. | |
250 (let* ((buffers (delete-if | |
251 buffers-tab-omit-function (buffer-list frame))) | |
241 (first-buf (car buffers))) | 252 (first-buf (car buffers))) |
242 ;; maybe force the selected window | 253 ;; maybe force the selected window |
243 (when (and force-selection | 254 (when (and force-selection |
244 (not in-deletion) | 255 (not in-deletion) |
245 (not (eq first-buf (window-buffer (selected-window frame))))) | 256 (not (eq first-buf (window-buffer (selected-window frame))))) |
247 (delq first-buf buffers)))) | 258 (delq first-buf buffers)))) |
248 ;; if we're in deletion ignore the current buffer | 259 ;; if we're in deletion ignore the current buffer |
249 (when in-deletion | 260 (when in-deletion |
250 (setq buffers (delq (current-buffer) buffers)) | 261 (setq buffers (delq (current-buffer) buffers)) |
251 (setq first-buf (car buffers))) | 262 (setq first-buf (car buffers))) |
252 ;; select buffers in group (default is by mode) | 263 ;; filter buffers |
253 (when buffers-tab-selection-function | 264 (when buffers-tab-filter-functions |
254 (delete-if-not #'(lambda (buf) | 265 (setq buffers |
255 (funcall buffers-tab-selection-function | 266 (delete-if |
256 first-buf buf)) buffers)) | 267 #'null |
268 (mapcar #'(lambda (buf) | |
269 (let ((tmp-buf buf)) | |
270 (mapc #'(lambda (fun) | |
271 (unless (funcall fun buf first-buf) | |
272 (setq tmp-buf nil))) | |
273 buffers-tab-filter-functions) | |
274 tmp-buf)) | |
275 buffers)))) | |
257 ;; maybe shorten list of buffers | 276 ;; maybe shorten list of buffers |
258 (and (integerp buffers-tab-max-size) | 277 (and (integerp buffers-tab-max-size) |
259 (> buffers-tab-max-size 1) | 278 (> buffers-tab-max-size 1) |
260 (> (length buffers) buffers-tab-max-size) | 279 (> (length buffers) buffers-tab-max-size) |
261 (setcdr (nthcdr buffers-tab-max-size buffers) nil)) | 280 (setcdr (nthcdr buffers-tab-max-size buffers) nil)) |
267 buffers))) | 286 buffers))) |
268 | 287 |
269 (defun add-tab-to-gutter () | 288 (defun add-tab-to-gutter () |
270 "Put a tab control in the gutter area to hold the most recent buffers." | 289 "Put a tab control in the gutter area to hold the most recent buffers." |
271 (setq gutter-buffers-tab-orientation (default-gutter-position)) | 290 (setq gutter-buffers-tab-orientation (default-gutter-position)) |
272 (let ((gutter-string (copy-sequence "\n"))) | 291 (let* ((gutter-string (copy-sequence "\n")) |
273 (unless gutter-buffers-tab-extent | 292 (gutter-buffers-tab-extent (make-extent 0 1 gutter-string))) |
274 (setq gutter-buffers-tab-extent (make-extent 0 1 gutter-string))) | 293 (set-extent-begin-glyph gutter-buffers-tab-extent |
275 (set-extent-begin-glyph | 294 (setq gutter-buffers-tab |
276 gutter-buffers-tab-extent | 295 (make-glyph))) |
277 (setq gutter-buffers-tab | |
278 (make-glyph))) | |
279 | |
280 ;; Nuke all existing tabs | 296 ;; Nuke all existing tabs |
281 (remove-gutter-element top-gutter 'buffers-tab) | 297 (remove-gutter-element top-gutter 'buffers-tab) |
282 (remove-gutter-element bottom-gutter 'buffers-tab) | 298 (remove-gutter-element bottom-gutter 'buffers-tab) |
283 (remove-gutter-element left-gutter 'buffers-tab) | 299 (remove-gutter-element left-gutter 'buffers-tab) |
284 (remove-gutter-element right-gutter 'buffers-tab) | 300 (remove-gutter-element right-gutter 'buffers-tab) |
296 (set-gutter-element bottom-gutter 'buffers-tab | 312 (set-gutter-element bottom-gutter 'buffers-tab |
297 gutter-string 'global x)) | 313 gutter-string 'global x)) |
298 ((eq gutter-buffers-tab-orientation 'left) | 314 ((eq gutter-buffers-tab-orientation 'left) |
299 (set-specifier left-gutter-border-width 0 'global x) | 315 (set-specifier left-gutter-border-width 0 'global x) |
300 (set-gutter-element left-gutter 'buffers-tab | 316 (set-gutter-element left-gutter 'buffers-tab |
301 gutter-string 'global x) | 317 gutter-string 'global x)) |
302 (set-specifier left-gutter-width | |
303 (glyph-width gutter-buffers-tab) | |
304 'global x)) | |
305 ((eq gutter-buffers-tab-orientation 'right) | 318 ((eq gutter-buffers-tab-orientation 'right) |
306 (set-specifier right-gutter-border-width 0 'global x) | 319 (set-specifier right-gutter-border-width 0 'global x) |
307 (set-gutter-element right-gutter 'buffers-tab | 320 (set-gutter-element right-gutter 'buffers-tab |
308 gutter-string 'global x) | 321 gutter-string 'global x)) |
309 (set-specifier right-gutter-width | |
310 (glyph-width gutter-buffers-tab) | |
311 'global x)) | |
312 ))) | 322 ))) |
313 (console-type-list)))) | 323 (console-type-list)))) |
314 | 324 |
315 (defun update-tab-in-gutter (frame &optional force-selection) | 325 (defun update-tab-in-gutter (frame &optional force-selection) |
316 "Update the tab control in the gutter area." | 326 "Update the tab control in the gutter area." |
331 :pixel-width :pixel-height) | 341 :pixel-width :pixel-height) |
332 (if (or (eq gutter-buffers-tab-orientation 'top) | 342 (if (or (eq gutter-buffers-tab-orientation 'top) |
333 (eq gutter-buffers-tab-orientation 'bottom)) | 343 (eq gutter-buffers-tab-orientation 'bottom)) |
334 '(gutter-pixel-width) '(gutter-pixel-height)) | 344 '(gutter-pixel-width) '(gutter-pixel-height)) |
335 :items (buffers-tab-items nil frame force-selection)) | 345 :items (buffers-tab-items nil frame force-selection)) |
336 frame))))) | 346 frame) |
347 ;; set-glyph-image will not make the gutter dirty | |
348 (set-specifier-dirty-flag | |
349 (eval (intern (concat | |
350 (symbol-name gutter-buffers-tab-orientation) | |
351 "-gutter")))))))) | |
337 | 352 |
338 ;; A myriad of different update hooks all doing slightly different things | 353 ;; A myriad of different update hooks all doing slightly different things |
339 (add-hook 'create-frame-hook | 354 (add-one-shot-hook |
340 #'(lambda (frame) | 355 'after-init-hook |
341 (when gutter-buffers-tab (update-tab-in-gutter frame t)))) | 356 #'(lambda () |
342 (add-hook 'buffer-list-changed-hook 'update-tab-in-gutter) | 357 ;; don't add the hooks if the user really doesn't want them |
343 (add-hook 'default-gutter-position-changed-hook | 358 (when gutter-buffers-tab-enabled |
344 #'(lambda () | 359 (add-hook 'create-frame-hook |
345 (when gutter-buffers-tab | 360 #'(lambda (frame) |
346 (mapc #'update-tab-in-gutter (frame-list))))) | 361 (when gutter-buffers-tab (update-tab-in-gutter frame t)))) |
347 (add-hook 'gutter-element-visibility-changed-hook | 362 (add-hook 'buffer-list-changed-hook 'update-tab-in-gutter) |
348 #'(lambda (prop visible-p) | 363 (add-hook 'default-gutter-position-changed-hook |
349 (when (and (eq prop 'buffers-tab) visible-p) | 364 #'(lambda () |
350 (mapc #'update-tab-in-gutter (frame-list))))) | 365 (when gutter-buffers-tab |
366 (mapc #'update-tab-in-gutter (frame-list))))) | |
367 (add-hook 'gutter-element-visibility-changed-hook | |
368 #'(lambda (prop visible-p) | |
369 (when (and (eq prop 'buffers-tab) visible-p) | |
370 (mapc #'update-tab-in-gutter (frame-list))))) | |
371 (update-tab-in-gutter (selected-frame) t)))) | |
372 | |
351 ;; | 373 ;; |
352 ;; progress display | 374 ;; progress display |
353 ;; ripped off from message display | 375 ;; ripped off from message display |
354 ;; | 376 ;; |
355 (defcustom progress-feedback-use-echo-area nil | 377 (defcustom progress-feedback-use-echo-area nil |