Mercurial > emacs
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 ;;;!! |