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