diff options
| author | Richard M. Stallman | 1997-02-10 00:10:16 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1997-02-10 00:10:16 +0000 |
| commit | 284a88a3183fd7f05b31845f61bc8ad869acc35a (patch) | |
| tree | 2fb2ed380101562b843a2a62b8a00e03cbba121a | |
| parent | 1884e32542ed6d4aa6bcde0b4b49685355e83961 (diff) | |
| download | emacs-284a88a3183fd7f05b31845f61bc8ad869acc35a.tar.gz emacs-284a88a3183fd7f05b31845f61bc8ad869acc35a.zip | |
(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.
| -rw-r--r-- | lisp/mouse.el | 207 |
1 files changed, 150 insertions, 57 deletions
diff --git a/lisp/mouse.el b/lisp/mouse.el index 5613e73c3c1..2bc8b191fa2 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el | |||
| @@ -1272,75 +1272,168 @@ again. If you do this twice in the same position, it kills the selection." | |||
| 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 | ||