From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Juri Linkov Newsgroups: gmane.emacs.devel Subject: Re: Neat features in Eclipse editor Date: Sun, 23 Mar 2008 04:27:17 +0200 Organization: JURTA Message-ID: <873aqiw4xm.fsf@jurta.org> References: <873aqia0eh.fsf@stupidchicken.com> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: ger.gmane.org 1206240267 24711 80.91.229.12 (23 Mar 2008 02:44:27 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sun, 23 Mar 2008 02:44:27 +0000 (UTC) Cc: Paul Michael Reilly , rms@gnu.org, emacs-devel@gnu.org To: Chong Yidong Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sun Mar 23 03:44:56 2008 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1JdGCc-0000td-Qe for ged-emacs-devel@m.gmane.org; Sun, 23 Mar 2008 03:44:55 +0100 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1JdGC1-00050b-Vw for ged-emacs-devel@m.gmane.org; Sat, 22 Mar 2008 22:44:18 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1JdGAD-0003nB-Ny for emacs-devel@gnu.org; Sat, 22 Mar 2008 22:42:25 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1JdGAC-0003mK-BP for emacs-devel@gnu.org; Sat, 22 Mar 2008 22:42:25 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1JdGAB-0003mC-Vl for emacs-devel@gnu.org; Sat, 22 Mar 2008 22:42:24 -0400 Original-Received: from relay02.kiev.sovam.com ([62.64.120.197]) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1JdGA7-0007Ql-Ah; Sat, 22 Mar 2008 22:42:20 -0400 Original-Received: from [83.170.232.243] (helo=smtp.svitonline.com) by relay02.kiev.sovam.com with esmtp (Exim 4.67) (envelope-from ) id 1JdGA4-000A89-D3; Sun, 23 Mar 2008 04:42:16 +0200 In-Reply-To: <873aqia0eh.fsf@stupidchicken.com> (Chong Yidong's message of "Sat, 22 Mar 2008 17:56:06 -0400") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (x86_64-pc-linux-gnu) X-Scanner-Signature: 6bea4dd5e7a98ea238edf764fb0a12e1 X-DrWeb-checked: yes X-SpamTest-Envelope-From: juri@jurta.org X-SpamTest-Group-ID: 00000000 X-SpamTest-Header: Not Detected X-SpamTest-Info: Profiles 2459 [Mar 21 2008] X-SpamTest-Info: helo_type=3 X-SpamTest-Method: none X-SpamTest-Rate: 0 X-SpamTest-Status: Not detected X-SpamTest-Status-Extended: not_detected X-SpamTest-Version: SMTP-Filter Version 3.0.0 [0278], KAS30/Release X-detected-kernel: by monty-python.gnu.org: FreeBSD 6.x (1) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:93237 Archived-At: --=-=-= >> * "Perspectives" are named persistent window configurations. We have >> had the window configuration mechanism in GNU Emacs since the >> beginning but we have never developed a good user interface to take >> advantage of them. Eclipse's user interface seems to be good. > > Well, we already have `C-x r w R' (window-configuration-to-register) > and `C-x r f R' (frame-configuration-to-register) for saving window > configurations, and `C-x r j R' for restoring them. > > Though it's true that this could certainly be more user-friendly. > Maybe the simplest way to do this is to add a "window configuration" > submenu to the File menu on the menu-bar. I use such Emacs configuration where there is only one full-size Emacs frame. But it is practically impossible to use Emacs without an equivalent of Emacs frames that group a set of Emacs windows into separate frame units. So window configurations are real saver for me. But using window configurations is limited to a few inconvenient commands like `C-x r w' and `C-x r j'. So I wrote a package that displays a list of all recorded window configurations and allows to easily switch between them. It works like a list of windows in many window managers: when you type a key (e.g. M-TAB), it displays a list of window configurations (windows in window managers), another key switches to the selected window configuration. Below is the source code of this package. Initially it was part of the ee package, but I rewrote it based on buff-menu.el to remove dependencies, so now it is a standalone package. --=-=-= Content-Type: application/emacs-lisp Content-Disposition: inline; filename=wincows.el Content-Transfer-Encoding: quoted-printable Content-Description: wincows.el ;;; wincows.el --- display and switch Emacs window configurations ;; Copyright (C) 2002-2008 Juri Linkov ;; Author: Juri Linkov ;; Keywords: windows ;; Version: 1.0 ;; This package is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. ;; This package is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this package; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;; Commentary: ;; The command `wincows' displays a list of window configurations with ;; names of their buffers separated by comma. You can switch to a window ;; configuration selected from this list. ;; To create a new window configuration, run `wincows' and start creating ;; new windows without selecting an existing window configuration (you can ;; leave the current list with `q' for clarity.) ;;; Suggested keybindings ;; (define-key global-map "\e\t" 'wincows) ;; (define-key wincows-mode-map "\e\t" 'wincows-select) ;; (define-key wincows-mode-map "\t" 'wincows-next-line) ;; (define-key wincows-mode-map [backtab] 'wincows-prev-line) ;;; Code: ;;; Customizable User Options (defgroup wincows nil "Display and switch Emacs window configurations." :group 'windows) ;;; Internal Variables (defvar wincows-list nil "A list of window configurations.") (defvar wincows-column 3) ;;; Key Bindings (defvar wincows-mode-map (let ((map (make-keymap))) (suppress-keymap map t) (define-key map "q" 'quit-window) (define-key map "\C-m" 'wincows-select) (define-key map "d" 'wincows-delete) (define-key map "k" 'wincows-delete) (define-key map "\C-d" 'wincows-delete-backwards) (define-key map "\C-k" 'wincows-delete) (define-key map "x" 'wincows-execute) (define-key map " " 'wincows-next-line) (define-key map "n" 'wincows-next-line) (define-key map "p" 'wincows-prev-line) (define-key map "\177" 'wincows-backup-unmark) (define-key map "?" 'describe-mode) (define-key map "u" 'wincows-unmark) (define-key map [mouse-2] 'wincows-mouse-select) (define-key map [follow-link] 'mouse-face) map) "Local keymap for `wincows-mode' buffers.") ;;; Mode (define-derived-mode wincows-mode nil "Window Configurations" "Major mode for selecting a window configuration. Each line describes one window configuration in Emacs. Letters do not insert themselves; instead, they are commands. \\ \\[wincows-mouse-select] -- select window configuration you click on. \\[wincows-select] -- select current line's window configuration. \\[wincows-delete] -- mark that window configuration to be deleted, and mov= e down. \\[wincows-delete-backwards] -- mark that window configuration to be delete= d, and move up. \\[wincows-execute] -- delete or save marked window configurations. \\[wincows-unmark] -- remove all kinds of marks from current line. With prefix argument, also move up one line. \\[wincows-backup-unmark] -- back up a line and remove marks." (setq truncate-lines t) (setq buffer-read-only t)) (defun wincows-current (error-if-non-existent-p) "Return window configuration described by this line of the menu." (let* ((where (save-excursion (beginning-of-line) (+ 2 (point) wincows-column))) (wincow (and (not (eobp)) (get-text-property where 'wincow)))) (or (and wincow (window-configuration-p (nth 0 wincow)) wincow) (if error-if-non-existent-p (error "No window configuration on this line") nil)))) ;;; Commands (defun wincows () "Display a list of window configurations with names of their buffers. The list is displayed in a buffer named `*Wincows*'. In this menu of window configurations so you can delete or select them. Type ? after invocation to get help on commands available. Type q to remove the window configuration menu from the display. The first column shows `D' for for a window configuration you have marked for deletion." (interactive) (switch-to-buffer (wincows-noselect)) (message "Commands: d, x; RET; q to quit; ? for help.")) (defun wincows-next-line (&optional arg) (interactive) (next-line arg)) (defun wincows-prev-line (&optional arg) (interactive) (previous-line arg)) (defun wincows-unmark (&optional backup) "Cancel all requested operations on window configuration on this line and= move down. Optional prefix arg means move up." (interactive "P") (beginning-of-line) (forward-char wincows-column) (let* ((buffer-read-only nil)) (delete-char 1) (insert " ")) (forward-line (if backup -1 1)) (forward-char wincows-column)) (defun wincows-backup-unmark () "Move up and cancel all requested operations on window configuration on l= ine above." (interactive) (forward-line -1) (wincows-unmark) (forward-line -1) (forward-char wincows-column)) (defun wincows-delete (&optional arg) "Mark window configuration on this line to be deleted by \\\\[wincows-execute] command. Prefix arg is how many window configurations to delete. Negative arg means delete backwards." (interactive "p") (let ((buffer-read-only nil)) (if (or (null arg) (=3D arg 0)) (setq arg 1)) (while (> arg 0) (delete-char 1) (insert ?D) (forward-line 1) (setq arg (1- arg))) (while (< arg 0) (delete-char 1) (insert ?D) (forward-line -1) (setq arg (1+ arg))) (forward-char wincows-column))) (defun wincows-delete-backwards (&optional arg) "Mark window configuration on this line to be deleted by \\\\[wincows-execute] command and then move up one line. Prefix arg means move that many lines." (interactive "p") (wincows-delete (- (or arg 1)))) (defun wincows-execute () "Delete window configurations marked with \\\\[wincows-= delete] commands." (interactive) (save-excursion (goto-char (point-min)) (let ((buffer-read-only nil)) (while (re-search-forward (format "^%sD" (make-string wincows-column ?\040)) nil t) (forward-char -1) (let ((wincow (wincows-current nil))) (when wincow (setq wincows-list (delete wincow wincows-list)) (beginning-of-line) (delete-region (point) (progn (forward-line 1) (point)))))))) (beginning-of-line) (forward-char wincows-column)) (defun wincows-select () "Select this line's window configuration. This command deletes and replaces all the previously existing windows in the selected frame." (interactive) (let* ((wincow (wincows-current t)) (bl (delq nil (mapcar (lambda (b) (and (buffer-live-p b) b)) (nth 2 wincow)))) (bbl (delq nil (mapcar (lambda (b) (and (buffer-live-p b) b)) (nth 3 wincow))))) ;; Delete the selected window configuration (setq wincows-list (delete wincow wincows-list)) (kill-buffer (current-buffer)) (modify-frame-parameters (selected-frame) (list (cons 'buffer-list bl))) (modify-frame-parameters (selected-frame) (list (cons 'buried-buffer-li= st bbl))) (set-window-configuration (nth 0 wincow)))) (defun wincows-mouse-select (event) "Select the window configuration whose line you click on." (interactive "e") (set-buffer (window-buffer (posn-window (event-end event)))) (goto-char (posn-point (event-end event))) (wincows-select)) ;;; *Wincows* Buffer Creation (defun wincows-noselect () "Create and return a buffer with a list of window configurations. The list is displayed in a buffer named `*Wincows*'. For more information, see the function `wincows'." (wincows-add-current) (with-current-buffer (get-buffer-create "*Wincows*") (setq buffer-read-only nil) (erase-buffer) ;; Vertical alignment to the center of the frame (insert-char ?\n (/ (- (frame-height) (length wincows-list) 1) 2)) ;; Horizontal alignment to the center of the frame (setq wincows-column (- (/ (frame-width) 2) 15)) (dolist (wincow wincows-list) (insert (propertize (format "%s %s\n" (make-string wincows-column ?\040) (propertize (nth 1 wincow) 'mouse-face 'highlight 'help-echo "mouse-2: select this window configurati= on")) 'wincow wincow))) (wincows-mode) (goto-char (point-min)) (goto-char (or (next-single-property-change (point) 'wincow) (point-min= ))) (forward-char wincows-column) (set-buffer-modified-p nil) (delete-other-windows) (current-buffer))) (defun wincows-add-current () "Add current Emacs window configuration to the list." (interactive) (let ((current (list (current-window-configuration) (mapconcat (lambda (w) (buffer-name (window-buffer w))) (window-list) ", ") (delq nil (mapcar (lambda (b) (and (buffer-live-p b) b)) (frame-parameter (selected-frame) 'buffer-list))) (delq nil (mapcar (lambda (b) (and (buffer-live-p b) b)) (frame-parameter (selected-frame) 'buried-buffer-list)))))) (setq wincows-list (cons current wincows-list)))) (provide 'wincows) ;;; wincows.el ends here --=-=-= -- Juri Linkov http://www.jurta.org/emacs/ --=-=-=--