comparison lisp/mouse.el @ 16989:4e31b0ff76a9

(mouse-buffer-menu): Group buffers by major modes if that seems to be useful. (mouse-buffer-menu-mode-groups): New variable. (mouse-buffer-menu-alist, mouse-buffer-menu-split): New subroutines broken out of mouse-buffer-menu.
author Richard M. Stallman <rms@gnu.org>
date Mon, 10 Feb 1997 00:10:16 +0000
parents 9d2a854bac89
children 3a99b530ad9a
comparison
equal deleted inserted replaced
16988:18b8f50567b2 16989:4e31b0ff76a9
1270 (defvar mouse-menu-buffer-maxlen 20 1270 (defvar mouse-menu-buffer-maxlen 20
1271 "*Number of buffers in one pane (submenu) of the buffer menu. 1271 "*Number of buffers in one pane (submenu) of the buffer menu.
1272 If we have lots of buffers, divide them into groups of 1272 If we have lots of buffers, divide them into groups of
1273 `mouse-menu-buffer-maxlen' and make a pane (or submenu) for each one.") 1273 `mouse-menu-buffer-maxlen' and make a pane (or submenu) for each one.")
1274 1274
1275 (defvar mouse-buffer-menu-mode-groups
1276 '(("Info\\|Help\\|Apropos\\|Man" . "Help")
1277 ("\\bVM\\b\\|\\bMH\\b\\|Message\\|Mail\\|Group\\|Score\\|Summary\\|Article"
1278 . "Mail/News")
1279 ("\\<C\\>" . "C")
1280 ("ObjC" . "C")
1281 ("Text" . "Text")
1282 ("Outline" . "Text")
1283 ("Lisp" . "Lisp"))
1284 "How to group various major modes together in \\[mouse-buffer-menu].
1285 Each element has the form (REGEXP . GROUPNAME).
1286 If the major mode's name string matches REGEXP, use GROUPNAME instead.")
1287
1275 (defun mouse-buffer-menu (event) 1288 (defun mouse-buffer-menu (event)
1276 "Pop up a menu of buffers for selection with the mouse. 1289 "Pop up a menu of buffers for selection with the mouse.
1277 This switches buffers in the window that you clicked on, 1290 This switches buffers in the window that you clicked on,
1278 and selects that window." 1291 and selects that window."
1279 (interactive "e") 1292 (interactive "e")
1280 (mouse-minibuffer-check event) 1293 (mouse-minibuffer-check event)
1281 (let* ((buffers 1294 (let (buffers alist menu split-by-major-mode sum-of-squares)
1282 ;; Make an alist of (MENU-ITEM . BUFFER). 1295 (setq buffers (buffer-list))
1283 (let ((tail (buffer-list)) 1296 ;; Make an alist of elements that look like (MENU-ITEM . BUFFER).
1284 (maxlen 0) 1297 (let ((tail buffers))
1285 head) 1298 (while tail
1286 (while tail 1299 ;; Divide all buffers into buckets for various major modes.
1287 (or (eq ?\ (aref (buffer-name (car tail)) 0)) 1300 ;; Each bucket looks like (MODE NAMESTRING BUFFERS...).
1288 (setq maxlen 1301 (with-current-buffer (car tail)
1289 (max maxlen 1302 (let* ((adjusted-major-mode major-mode) elt)
1290 (length (buffer-name (car tail)))))) 1303 (let ((tail mouse-buffer-menu-mode-groups))
1291 (setq tail (cdr tail))) 1304 (while tail
1292 (setq tail (buffer-list)) 1305 (if (string-match (car (car tail)) mode-name)
1293 (while tail 1306 (setq adjusted-major-mode (cdr (car tail))))
1294 (let ((elt (car tail))) 1307 (setq tail (cdr tail))))
1295 (if (/= (aref (buffer-name elt) 0) ?\ ) 1308 (setq elt (assoc adjusted-major-mode split-by-major-mode))
1296 (setq head 1309 (if (null elt)
1297 (cons 1310 (setq elt (list adjusted-major-mode
1298 (cons 1311 (if (stringp adjusted-major-mode)
1299 (format 1312 adjusted-major-mode
1300 (format "%%%ds %%s%%s %%s" maxlen) 1313 mode-name))
1301 (buffer-name elt) 1314 split-by-major-mode (cons elt split-by-major-mode)))
1302 (if (buffer-modified-p elt) "*" " ") 1315 (or (memq (car tail) (cdr (cdr elt)))
1303 (save-excursion 1316 (setcdr (cdr elt) (cons (car tail) (cdr (cdr elt)))))))
1304 (set-buffer elt) 1317 (setq tail (cdr tail))))
1305 (if buffer-read-only "%" " ")) 1318 ;; Compute the sum of squares of sizes of the major-mode buckets.
1306 (or (buffer-file-name elt) 1319 (let ((tail split-by-major-mode))
1307 (save-excursion 1320 (setq sum-of-squares 0)
1308 (set-buffer elt) 1321 (while tail
1309 (if list-buffers-directory 1322 (setq sum-of-squares
1310 (expand-file-name 1323 (+ sum-of-squares
1311 list-buffers-directory))) 1324 (* (length (cdr (cdr (car tail))))
1312 "")) 1325 (length (cdr (cdr (car tail)))))))
1313 elt) 1326 (setq tail (cdr tail))))
1314 head)))) 1327 (if (< (* sum-of-squares 4) (* (length buffers) (length buffers)))
1315 (setq tail (cdr tail))) 1328 ;; Subdividing by major modes really helps, so let's do it.
1316 ;; Compensate for the reversal that the above loop does. 1329 (let (subdivided-menus (buffers-left (length buffers)))
1317 (nreverse head))) 1330 ;; Sort the list to put the most popular major modes first.
1318 (menu 1331 (setq split-by-major-mode
1319 ;; If we have lots of buffers, divide them into groups of 20 1332 (sort split-by-major-mode
1320 ;; and make a pane (or submenu) for each one. 1333 (function (lambda (elt1 elt2)
1321 (if (> (length buffers) (/ (* mouse-menu-buffer-maxlen 3) 2)) 1334 (> (length elt1) (length elt2))))))
1322 (let ((buffers buffers) sublists next 1335 ;; Make a separate submenu for each major mode
1323 (i 1)) 1336 ;; that has more than one buffer,
1324 (while buffers 1337 ;; unless all the remaining buffers are less than 1/10 of them.
1325 ;; Pull off the next mouse-menu-buffer-maxlen buffers 1338 (while (and split-by-major-mode
1326 ;; and make them the next element of sublist. 1339 (and (> (length (car split-by-major-mode)) 3)
1327 (setq next (nthcdr mouse-menu-buffer-maxlen buffers)) 1340 (> (* buffers-left 10) (length buffers))))
1328 (if next 1341 (setq subdivided-menus
1329 (setcdr (nthcdr (1- mouse-menu-buffer-maxlen) buffers) 1342 (cons (cons
1330 nil)) 1343 (nth 1 (car split-by-major-mode))
1331 (setq sublists (cons (cons (format "Buffers %d" i) buffers) 1344 (mouse-buffer-menu-alist
1332 sublists)) 1345 (cdr (cdr (car split-by-major-mode)))))
1333 (setq i (1+ i)) 1346 subdivided-menus))
1334 (setq buffers next)) 1347 (setq buffers-left
1335 (cons "Buffer Menu" (nreverse sublists))) 1348 (- buffers-left (length (cdr (car split-by-major-mode)))))
1336 ;; Few buffers--put them all in one pane. 1349 (setq split-by-major-mode (cdr split-by-major-mode)))
1337 (list "Buffer Menu" (cons "Select Buffer" buffers))))) 1350 ;; If any major modes are left over,
1351 ;; make a single submenu for them.
1352 (if split-by-major-mode
1353 (setq subdivided-menus
1354 (cons (cons
1355 "Others"
1356 (mouse-buffer-menu-alist
1357 (apply 'append
1358 (mapcar 'cdr
1359 (mapcar 'cdr split-by-major-mode)))))
1360 subdivided-menus)))
1361 (setq subdivided-menus
1362 (nreverse subdivided-menus))
1363 (setq menu (cons "Buffer Menu" subdivided-menus)))
1364 (progn
1365 (setq alist (mouse-buffer-menu-alist buffers))
1366 (setq menu (cons "Buffer Menu"
1367 (mouse-buffer-menu-split "Select Buffer" alist)))))
1338 (let ((buf (x-popup-menu event menu)) 1368 (let ((buf (x-popup-menu event menu))
1339 (window (posn-window (event-start event)))) 1369 (window (posn-window (event-start event))))
1340 (if buf 1370 (if buf
1341 (progn 1371 (progn
1342 (or (framep window) (select-window window)) 1372 (or (framep window) (select-window window))
1343 (switch-to-buffer buf)))))) 1373 (switch-to-buffer buf))))))
1374
1375 (defun mouse-buffer-menu-alist (buffers)
1376 (let (tail
1377 (maxlen 0)
1378 head)
1379 (setq buffers
1380 (sort buffers
1381 (function (lambda (elt1 elt2)
1382 (string< (buffer-name elt1) (buffer-name elt2))))))
1383 (setq tail buffers)
1384 (while tail
1385 (or (eq ?\ (aref (buffer-name (car tail)) 0))
1386 (setq maxlen
1387 (max maxlen
1388 (length (buffer-name (car tail))))))
1389 (setq tail (cdr tail)))
1390 (setq tail buffers)
1391 (while tail
1392 (let ((elt (car tail)))
1393 (if (/= (aref (buffer-name elt) 0) ?\ )
1394 (setq head
1395 (cons
1396 (cons
1397 (format
1398 (format "%%%ds %%s%%s %%s" maxlen)
1399 (buffer-name elt)
1400 (if (buffer-modified-p elt) "*" " ")
1401 (save-excursion
1402 (set-buffer elt)
1403 (if buffer-read-only "%" " "))
1404 (or (buffer-file-name elt)
1405 (save-excursion
1406 (set-buffer elt)
1407 (if list-buffers-directory
1408 (expand-file-name
1409 list-buffers-directory)))
1410 ""))
1411 elt)
1412 head))))
1413 (setq tail (cdr tail)))
1414 ;; Compensate for the reversal that the above loop does.
1415 (nreverse head)))
1416
1417 (defun mouse-buffer-menu-split (title alist)
1418 ;; If we have lots of buffers, divide them into groups of 20
1419 ;; and make a pane (or submenu) for each one.
1420 (if (> (length alist) (/ (* mouse-menu-buffer-maxlen 3) 2))
1421 (let ((alist alist) sublists next
1422 (i 1))
1423 (while alist
1424 ;; Pull off the next mouse-menu-buffer-maxlen buffers
1425 ;; and make them the next element of sublist.
1426 (setq next (nthcdr mouse-menu-buffer-maxlen alist))
1427 (if next
1428 (setcdr (nthcdr (1- mouse-menu-buffer-maxlen) alist)
1429 nil))
1430 (setq sublists (cons (cons (format "Buffers %d" i) alist)
1431 sublists))
1432 (setq i (1+ i))
1433 (setq alist next))
1434 (nreverse sublists))
1435 ;; Few buffers--put them all in one pane.
1436 (list (cons title alist))))
1344 1437
1345 ;;; These need to be rewritten for the new scroll bar implementation. 1438 ;;; These need to be rewritten for the new scroll bar implementation.
1346 1439
1347 ;;;!! ;; Commands for the scroll bar. 1440 ;;;!! ;; Commands for the scroll bar.
1348 ;;;!! 1441 ;;;!!