From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dan Davison Subject: Using Org for browsing and managing buffers Date: Thu, 08 Apr 2010 21:17:20 -0400 Message-ID: <87aatda0gv.fsf@stats.ox.ac.uk> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O02qq-0007CU-LG for emacs-orgmode@gnu.org; Thu, 08 Apr 2010 21:17:40 -0400 Received: from [140.186.70.92] (port=58341 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O02qk-0007BV-6F for emacs-orgmode@gnu.org; Thu, 08 Apr 2010 21:17:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O02qb-00031o-Dt for emacs-orgmode@gnu.org; Thu, 08 Apr 2010 21:17:28 -0400 Received: from markov.stats.ox.ac.uk ([163.1.210.1]:63173) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O02qb-00031f-2z for emacs-orgmode@gnu.org; Thu, 08 Apr 2010 21:17:25 -0400 Received: from blackcap.stats.ox.ac.uk (blackcap.stats [163.1.210.5]) by markov.stats.ox.ac.uk (8.13.6/8.13.6) with ESMTP id o391HNt7021552 for ; Fri, 9 Apr 2010 02:17:23 +0100 (BST) List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: emacs org-mode mailing list --=-=-= I've been working on an Org tool to browse Emacs buffers. Emacs has the function list-buffers (C-x C-b), where you can view a list of buffers, delete buffers, etc. This is intended to be a replacement for list-buffers, implemented in Org-mode. The code is attached, and there's a git repo at http://github.com/dandavison/org-buffers After putting the code in your load-path and doing (require 'org-buffers), use the function `org-buffers-list' to create the listing buffer. This is a read-only Org-mode buffer populated with links to open buffers. Information is stored for each buffer using properties. By default, the buffers are grouped by major mode. Here's a screenshot. http://www.princeton.edu/~ddavison/org-buffers/by-major-mode.png The buffer has some special key-bindings: --=-=-= Content-Type: multipart/alternative; boundary="==-=-=" --==-=-= | ? | Show all keybindings | | g | Update buffer (prefix arg does hard reset) | | b | Select a different property to group by | | RET | follow link to buffer on this line | | d | Mark buffer for deletion | | u | Remove mark | | x | Delete marked buffers | | o | Like RET (see variable org-buffers-follow-link-method) | | . | Like RET but switch to buffer in same window | | h | toggle between headings and plain entries for buffers | | p | toggle in-buffer properties on/off | | c | Switch to column-view | --==-=-= Content-Type: text/html
?Show all keybindings
gUpdate buffer (prefix arg does hard reset)
bSelect a different property to group by
RETfollow link to buffer on this line
dMark buffer for deletion
uRemove mark
xDelete marked buffers
oLike RET (see variable org-buffers-follow-link-method)
.Like RET but switch to buffer in same window
htoggle between headings and plain entries for buffers
ptoggle in-buffer properties on/off
cSwitch to column-view
--==-=-=-- --=-=-= If there's an active region, d and u operate on all buffers in the region. Some variables that can be configured: - org-buffers-buffer-properties - org-buffers-excluded-modes - org-buffers-excluded-buffers - org-buffers-follow-link-method - org-buffers-mode-hook - org-buffers-buffer-name Some possible extensions: - Browse recent files using recentf - Allow several buffers to be marked for side-by-side display - Maintain folding configuration across buffer updates - Make faster As always, any feedback, suggestions and patches will be very welcome! Dan p.s. The column-view mode works for following links, but does need further attention. --=-=-= Content-Disposition: inline; filename=org-buffers.el ;;; org-buffers.el --- An Org-mode tool for buffer management ;; Copyright (C) 2010 Dan Davison ;; Author: Dan Davison ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org ;;; License: ;; This program 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 3, or (at your option) ;; any later version. ;; ;; This program 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 GNU Emacs; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;;; Code: (require 'org) (require 'cl) ;;; Variables (defvar org-buffers-buffer-name "*Buffers*" "Name of buffer in which buffer list is displayed") (defvar org-buffers-state '((:by . "major-mode") (:atom . heading) (:properties . nil)) "Association list specifiying the current state of org-buffers.") (defvar org-buffers-follow-link-method 'org-open-at-point "Method used to follow link with RET. Must be one of 'org-open-at-point :: use `org-open-at-point' to follow link. 'current-window :: use switch-to-buffer 'other-window :: use switch-to-buffer-other-window Setting this variable to 'current-window makes the behaviour more consistent with that of `Buffer-menu-mode' and `dired-mode'") (defvar org-buffers-buffer-properties '(("buffer-name" . (buffer-name)) ("major-mode" . (let ((mode (symbol-name major-mode))) (if (string-match "-mode$" mode) (replace-match "" nil t mode) mode))) ("buffer-file-name" . (buffer-file-name)) ("default-directory" . default-directory) ("buffer-modified-p" . (format "%s" (buffer-modified-p)))) "Association list specifying properties to be stored for each buffer. The car of each element is the name of the property, and the cdr is an expression which, when evaluated in the buffer, yields the property value.") (defcustom org-buffers-excluded-buffers `("*Completions*" ,org-buffers-buffer-name) "List of names of buffers that should not be listed by org-buffers-list." :group 'org-buffers) (defcustom org-buffers-excluded-modes nil "List of names of major-modes (strings) that should not be listed by org-buffers-list." :group 'org-buffers) ;;; Mode (defvar org-buffers-mode-map (make-sparse-keymap)) (defvar org-buffers-mode-hook nil "Hook for functions to be called after buffer listing is created. Note that the buffer is read-only, so if the hook function is to modify the buffer it should use a let binding to temporarily bind buffer-read-only to nil.") (define-minor-mode org-buffers-mode "An Org-mode tool for buffer management. \\{org-buffers-mode-map}" nil " buffers" nil (org-set-local 'org-tag-alist '(("delete" . ?d))) (org-set-local'org-tags-column -50) (org-set-local 'org-columns-default-format "%25buffer-name(Buffer) %25major-mode(Mode) %25default-directory(Dir) %5buffer-modified-p(Modified)") (add-hook 'kill-buffer-hook 'org-buffers-reset-state nil 'local)) (defun org-buffers-help () (interactive) (describe-function 'org-buffers-mode)) ;;; Keys (define-key org-buffers-mode-map [(return)] 'org-buffers-follow-link) (define-key org-buffers-mode-map "b" 'org-buffers-list:by) (define-key org-buffers-mode-map "c" 'org-buffers-columns-view) (define-key org-buffers-mode-map "d" 'org-buffers-tag-for-deletion) (define-key org-buffers-mode-map "g" 'org-buffers-list:refresh) (define-key org-buffers-mode-map "." 'org-buffers-switch-to-buffer) (define-key org-buffers-mode-map "h" 'org-buffers-toggle-headings) (define-key org-buffers-mode-map "o" 'org-buffers-switch-to-buffer-other-window) (define-key org-buffers-mode-map "p" 'org-buffers-toggle-properties) (define-key org-buffers-mode-map "u" 'org-buffers-remove-tags) (define-key org-buffers-mode-map "x" 'org-buffers-execute-pending-operations) (define-key org-buffers-mode-map "?" 'org-buffers-help) ;;; Listing and view cycling (defun org-buffers-list (&optional refresh frame) "Create an Org-mode listing of Emacs buffers. By default, buffers are grouped by major mode. Optional argument FRAME specifies the frame whose buffers should be listed." (interactive) (pop-to-buffer (or (and (not refresh) (get-buffer org-buffers-buffer-name)) (let ((org-buffers-p (equal (buffer-name) org-buffers-buffer-name)) (by (or (org-buffers-state-get :by) "major-mode")) (atom (org-buffers-state-get :atom)) target) (when org-buffers-p (if (and (org-before-first-heading-p) (not (org-on-heading-p))) (outline-next-heading)) (setq target (condition-case nil (org-make-org-heading-search-string) (error nil)))) (with-current-buffer (get-buffer-create org-buffers-buffer-name) (setq buffer-read-only nil) (erase-buffer) (org-mode) (dolist (buffer (sort (remove-if 'org-buffers-exclude-p (mapcar 'buffer-name (buffer-list frame))) 'string<)) (org-insert-heading t) (insert (org-make-link-string (concat "buffer:" buffer) buffer) "\n") (dolist (pair (org-buffers-get-buffer-props buffer)) (org-set-property (car pair) (cdr pair)))) (org-buffers-set-state '((:atom . heading))) (goto-char (point-min)) (unless (equal by "NONE") (org-buffers-group-by by)) (if target (condition-case nil (org-link-search target) (error nil))) (beginning-of-line) (if (equal by "NONE") (org-overview) (case atom ('heading (progn (org-overview) (org-content))) ('line (progn (show-all) (org-buffers-toggle-headings))))) (save-excursion (mark-whole-buffer) (indent-region (point-min) (point-max))) (org-buffers-mode) (setq buffer-read-only t) (current-buffer)))))) (defun org-buffers-list:refresh (&optional arg) "Refresh org-buffers listing." (interactive "P") (if arg (org-buffers-reset-state)) (org-buffers-list 'refresh)) (defun org-buffers-list:by (&optional prop) "Group buffers according to value of property PROP." (interactive) (let ((buffer-read-only nil) (headings-p (org-buffers-state-eq :atom 'heading))) (unless (org-buffers-state-get :properties) (org-buffers-toggle-properties)) (org-buffers-set-state `((:by . ,(or prop (org-completing-read "Property to group by: " (cons "NONE" (mapcar 'car org-buffers-buffer-properties))))))) (org-buffers-list 'refresh) (unless headings-p (org-buffers-toggle-headings)))) (defun org-buffers-toggle-properties () "Toggle entry properties in org-buffers listing buffer. Removing properties may provide a less cluttered appearance for browsing. However, in-buffer properties will be restored during certain operations, such as `org-buffers-list:by'." (interactive) (if (org-buffers-state-get :properties) (progn (org-buffers-delete-properties) (show-all) (org-buffers-set-state '((:properties . nil)))) (org-buffers-set-state '((:atom . heading) (:properties . t))) (org-buffers-list 'refresh))) (defun org-buffers-toggle-headings () "Toggle viewing of buffers as org headings. Headings will be automatically restored during certain operations, such as setting deletion tags." (interactive) (let ((buffer-read-only nil) (headings-p (org-buffers-state-eq :atom 'heading)) (flat-p (org-buffers-state-eq :by "NONE"))) (if (and headings-p (org-buffers-state-get :properties)) (org-buffers-toggle-properties)) (save-excursion (goto-char (point-min)) (if (and (or headings-p (not flat-p)) (not (outline-on-heading-p))) (outline-next-heading)) (if flat-p (progn (push-mark (point) 'nomsg 'activate) (end-of-buffer) (org-ctrl-c-star) (pop-mark)) (while (not (eobp)) (push-mark (save-excursion (forward-line 1) (point)) 'nomsg 'activate) (org-forward-same-level 1) (org-ctrl-c-star) (pop-mark))) (mark-whole-buffer) (indent-region (point-min) (point-max))) (org-buffers-set-state `((:atom . ,(if headings-p 'line 'heading)))))) (defun org-buffers-delete-properties () (let ((buffer-read-only nil)) (save-excursion (goto-char (point-min)) (org-buffers-delete-regions (nreverse (org-buffers-map-entries 'org-buffers-get-property-block)))))) (defun org-buffers-get-property-block () "Return the (beg . end) range of the property drawer. Unlike the org version the limits include the keywords delimiting the drawer." (let ((beg (point)) (end (progn (outline-next-heading) (point)))) (goto-char beg) (if (re-search-forward org-property-drawer-re end t) (cons (match-beginning 1) (match-end 0))))) (defun org-buffers-group-by (property) "Group top level headings according to the value of PROPERTY." (let ((atom (org-buffers-state-get :atom))) (save-excursion (goto-char (point-min)) (mapc (lambda (subtree) ;; Create subtree for each value of `property' (org-insert-heading t) (if (> (org-buffers-outline-level) 1) (org-promote)) (insert (car subtree) "\n") (org-insert-subheading t) (mapc 'org-buffers-insert-parsed-entry (cdr subtree))) (prog1 (mapcar (lambda (val) ;; Form list of parsed entries for each unique value of `property' (cons val (org-buffers-parse-selected-entries property val))) (sort (delete-dups (org-buffers-map-entries (lambda () (org-entry-get nil property nil)))) 'string<)) (erase-buffer)))))) (defun org-buffers-exclude-p (buffer) "Return non-nil if BUFFER should not be listed." (or (member (with-current-buffer buffer major-mode) org-buffers-excluded-modes) (member buffer org-buffers-excluded-buffers) (string= (substring buffer 0 1) " "))) (defun org-buffers-reset-state () (org-buffers-set-state '((:by . "major-mode") (:atom . heading) (:properties . nil)))) (defun org-buffers-columns-view () "View buffers in Org-mode columns view. This is currently experimental. RET can be used to follow links in the first column, but certain other org-buffers keys conflict with column-view or otherwise do not work correctly." (interactive) (let ((by (org-buffers-state-get :by)) (buffer-read-only nil)) (unless (equal by "NONE") (org-buffers-list:by "NONE")) (unless (org-buffers-state-get :properties) (org-buffers-toggle-properties)) (unless (equal by "NONE") (goto-char (point-min)) (org-sort-entries-or-items nil ?r nil nil by) (org-overview)) (mark-whole-buffer) (org-columns))) ;;; Parsing and inserting entries (defun org-buffers-parse-selected-entries (prop val) "Parse all entries with property PROP value VAL." (delq nil (org-buffers-map-entries (lambda () (when (equal (org-entry-get nil prop) val) (cons (org-get-heading) (org-get-entry))))))) (defun org-buffers-insert-parsed-entry (entry) "Insert a parsed entry" (unless (org-at-heading-p) (org-insert-heading)) (insert (car entry) "\n") (if (org-buffers-state-get :properties) (insert (cdr entry)))) (defun org-buffers-get-buffer-props (buffer) "Create alist of properties of BUFFER, as strings." (with-current-buffer buffer (mapcar (lambda (pair) (cons (car pair) (eval (cdr pair)))) org-buffers-buffer-properties))) ;;; Follow-link behaviour (defun org-buffers-follow-link () "Follow link to buffer on this line. The buffer-switching behaviour of this function is determined by the variable `org-buffers-follow-link-method'. See also `org-buffers-switch-to-buffer' and `org-buffers-switch-to-buffer-other-window', whose behaviour is hard-wired." (interactive) (org-buffers-switch-to-buffer-generic org-buffers-follow-link-method)) (defun org-buffers-switch-to-buffer () "Switch to this entry's buffer in current window." (interactive) (org-buffers-switch-to-buffer-generic 'current-window)) (defun org-buffers-switch-to-buffer-other-window () "Switch to this entry's buffer in other window." (interactive) (org-buffers-switch-to-buffer-generic 'other-window)) (defun org-buffers-switch-to-buffer-generic (method) (save-excursion (let ((atom (org-buffers-state-get :atom)) buffer) (cond ((eq atom 'heading) (org-back-to-heading)) (t (beginning-of-line))) (setq buffer (org-buffers-get-buffer-name)) (if (get-buffer buffer) (case method ('org-open-at-point (org-open-at-point)) ('current-window (switch-to-buffer buffer)) ('other-window (switch-to-buffer-other-window buffer))) (error "No such buffer: %s" buffer))))) (defun org-buffers-get-buffer-name () "Get buffer-name for current entry." (let ((headings-p (org-buffers-state-eq :atom 'heading))) (or (and headings-p (org-entry-get nil "buffer-name")) (and (save-excursion (if headings-p (org-back-to-heading)) (re-search-forward "\\[\\[buffer:\\([^\]]*\\)" (point-at-eol) t)) (org-link-unescape (match-string 1)))))) ;;; Setting tags and executing operations (defun org-buffers-tag-for-deletion () "Mark buffer for deletion. If a region is selected, all buffers in the region are marked for deletion. Buffers marked for deletion can be deleted using `org-buffers-execute-pending-operations'." (interactive) (org-buffers-set-tags '("delete"))) (defun org-buffers-remove-tags () "Remove deletion marks from buffers. If a region is selected, marks are removed from all buffers in the region." (interactive) (org-buffers-set-tags nil)) (defun org-buffers-set-tags (data) "Set tags to DATA at all non top-level headings in region. DATA should be a list of strings. If DATA is nil, remove all tags at such headings." (let* ((buffer-read-only nil) (region-p (org-region-active-p)) (beg (if region-p (region-beginning) (point))) (end (if region-p (region-end) (point))) (headings-p (org-buffers-state-eq :atom 'heading))beg-line end-line) (save-excursion (setq beg-line (progn (goto-char beg) (org-current-line)) end-line (progn (goto-char end) (org-current-line))) (if headings-p (setq end (if (and region-p (not (eq end-line beg-line)) (not (eobp))) (progn (goto-char end) (org-back-to-heading) (point)) (progn (outline-end-of-heading) (point))) beg (progn (goto-char beg) (point-at-bol))) (org-buffers-toggle-headings) ;; doesn't alter line numbers (setq beg (progn (org-goto-line beg-line) (point-at-bol)) end (if (eq end-line beg-line) (point-at-eol) (progn (org-goto-line end-line) (point-at-bol))))) (narrow-to-region beg end) (goto-char (point-min)) (org-buffers-map-entries (lambda () (when (or (org-buffers-state-eq :by "NONE") (> (org-outline-level) 1)) (org-set-tags-to (if data (delete-duplicates (append data (org-get-tags)) :test 'string-equal)))))) (widen) (org-content)) (unless region-p (outline-next-heading) (unless (or (> (org-outline-level) 1) (org-buffers-state-eq :by "NONE")) (outline-next-heading))) (unless headings-p (org-buffers-toggle-headings)))) (defun org-buffers-execute-pending-operations () "Execute all pending operations. Currently the only type of operation supported is deletion. Buffers are tagged for deletion using `org-buffers-tag-for-deletion'. Remove such tags from buffers using `org-buffers-remove-tags'." (interactive) (let ((buffer-read-only nil) (headings-p (org-buffers-state-eq :atom 'heading)) buffer) (unless headings-p (org-buffers-toggle-headings)) (org-buffers-delete-regions (nreverse (org-buffers-map-entries (lambda () (if (setq buffer (org-buffers-get-buffer-name)) (if (not (kill-buffer buffer)) (error "Failed to kill buffer %s" buffer) (if (and (org-first-sibling-p) (not (save-excursion (org-goto-sibling)))) (org-up-heading-safe)) ;; Only child so delete parent also (cons (point) (1+ (org-end-of-subtree)))))) "+delete"))) (unless headings-p (org-buffers-toggle-headings)))) ;;; Utilities (defun org-buffers-map-entries (func &optional match) (org-scan-tags func (if match (cdr (org-make-tags-matcher match)) t))) (defun org-buffers-set-state (state) "Add STATE to global state list. New settings have precedence over existing ones." (mapc (lambda (pair) (unless (assoc (car pair) state) (add-to-list 'state pair))) org-buffers-state) (setq org-buffers-state state)) (defmacro org-buffers-delete-regions (regions) "Delete regions in list. REGIONS is a list of (beg . end) cons cells specifying buffer regions." `(mapc (lambda (pair) (if pair (delete-region (car pair) (cdr pair)))) ,regions)) (defmacro org-buffers-state-get (key) `(cdr (assoc ,key org-buffers-state))) (defmacro org-buffers-state-eq (key val) `(equal (org-buffers-state-get ,key) ,val)) (defmacro org-buffers-outline-level () '(save-excursion (beginning-of-line) (org-outline-level))) ;;; Links to buffers (org-add-link-type "buffer" 'display-buffer) (add-hook 'org-store-link-functions 'org-buffers-store-link) (defun org-buffers-store-link (&optional force) "Store a link to an Emacs buffer. Returns nil by default, to avoid hijacking other link types." (if force (let* ((target (buffer-name)) (desc target) link) (org-store-link-props :type "buffer") (setq link (org-make-link "buffer:" target)) (org-add-link-props :link link :description desc) link))) (provide 'org-buffers) ;;; org-buffers.el ends here --=-=-= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Emacs-orgmode mailing list Please use `Reply All' to send replies to the list. Emacs-orgmode@gnu.org http://lists.gnu.org/mailman/listinfo/emacs-orgmode --=-=-=-- From mboxrd@z Thu Jan 1 00:00:00 1970 From: Austin Frank Subject: Re: Using Org for browsing and managing buffers Date: Thu, 08 Apr 2010 23:43:16 -0400 Message-ID: References: <87aatda0gv.fsf@stats.ox.ac.uk> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1418307215==" Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O0580-0007Lh-UZ for emacs-orgmode@gnu.org; Thu, 08 Apr 2010 23:43:32 -0400 Received: from [140.186.70.92] (port=35667 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O057z-0007LD-CX for emacs-orgmode@gnu.org; Thu, 08 Apr 2010 23:43:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O057y-0001wl-0M for emacs-orgmode@gnu.org; Thu, 08 Apr 2010 23:43:31 -0400 Received: from lo.gmane.org ([80.91.229.12]:55807) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O057x-0001wY-Pk for emacs-orgmode@gnu.org; Thu, 08 Apr 2010 23:43:29 -0400 Received: from list by lo.gmane.org with local (Exim 4.69) (envelope-from ) id 1O057v-0004Xz-Mk for emacs-orgmode@gnu.org; Fri, 09 Apr 2010 05:43:27 +0200 Received: from colossus.cvs.rochester.edu ([128.151.80.181]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Fri, 09 Apr 2010 05:43:27 +0200 Received: from austin.frank by colossus.cvs.rochester.edu with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Fri, 09 Apr 2010 05:43:27 +0200 List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: emacs-orgmode@gnu.org --===============1418307215== Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha1; protocol="application/pgp-signature" --=-=-= Content-Transfer-Encoding: quoted-printable Dan-- Very nice. I will say, though, that the very first thing I did was (define-key org-buffers-mode-map "q" 'bury-buffer) I would request that something like this be included in the default keybindings. A smarter version might try to restore the window config From=20before org-buffers-list was called. See ibuffer-quit for an example. Will report back after more testing! Thanks! /au =2D-=20 Austin Frank http://aufrank.net GPG Public Key (D7398C2F): http://aufrank.net/personal.asc --=-=-= Content-Type: application/pgp-signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (Darwin) iEYEARECAAYFAku+olUACgkQlHMl2/XbR4EkGQCcD2JmxDG49EHZ9hGpd/H+GXyF Jd0AoIBAyUV9vLCGteVLIvJXgpMgNqoW =qWlE -----END PGP SIGNATURE----- --=-=-=-- --===============1418307215== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Emacs-orgmode mailing list Please use `Reply All' to send replies to the list. Emacs-orgmode@gnu.org http://lists.gnu.org/mailman/listinfo/emacs-orgmode --===============1418307215==-- From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dan Davison Subject: Re: Re: Using Org for browsing and managing buffers Date: Fri, 09 Apr 2010 10:49:33 -0400 Message-ID: <87y6gwof42.fsf@stats.ox.ac.uk> References: <87aatda0gv.fsf@stats.ox.ac.uk> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O0FWg-0003Y9-3Q for emacs-orgmode@gnu.org; Fri, 09 Apr 2010 10:49:42 -0400 Received: from [140.186.70.92] (port=39281 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O0FWe-0003XE-E3 for emacs-orgmode@gnu.org; Fri, 09 Apr 2010 10:49:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O0FWc-0003C6-Mp for emacs-orgmode@gnu.org; Fri, 09 Apr 2010 10:49:40 -0400 Received: from markov.stats.ox.ac.uk ([163.1.210.1]:46655) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O0FWc-0003Br-Eb for emacs-orgmode@gnu.org; Fri, 09 Apr 2010 10:49:38 -0400 In-Reply-To: (Austin Frank's message of "Thu, 08 Apr 2010 23:43:16 -0400") List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: Austin Frank Cc: emacs-orgmode@gnu.org Austin Frank writes: > Dan-- > > Very nice. I will say, though, that the very first thing I did was > > (define-key org-buffers-mode-map "q" 'bury-buffer) Thanks Austin, I've added that. > I would request that something like this be included in the default > keybindings. A smarter version might try to restore the window config > From before org-buffers-list was called. See ibuffer-quit for an > example. Will do. ibuffer does lots of nice things and I think a version using org-mode, with org's hierarchical structuring, would be even better. If anyone wanted to help out that would be great. Maybe the correct approach is to make use of the existing ibuffer machinery and build the org version on top of ibuffer? Dan > > Will report back after more testing! > > Thanks! > /au From mboxrd@z Thu Jan 1 00:00:00 1970 From: Eric S Fraga Subject: Re: Using Org for browsing and managing buffers Date: Wed, 14 Apr 2010 21:23:32 +0100 Message-ID: <87d3y1pyuz.wl%ucecesf@ucl.ac.uk> References: <87aatda0gv.fsf@stats.ox.ac.uk> Reply-To: e.fraga@ucl.ac.uk Mime-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset=US-ASCII Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O2981-0007yh-24 for emacs-orgmode@gnu.org; Wed, 14 Apr 2010 16:24:05 -0400 Received: from [140.186.70.92] (port=51060 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O297u-0007rp-KQ for emacs-orgmode@gnu.org; Wed, 14 Apr 2010 16:24:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O297s-0004Qf-Am for emacs-orgmode@gnu.org; Wed, 14 Apr 2010 16:23:58 -0400 Received: from vscane-b.ucl.ac.uk ([144.82.108.141]:60483) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O297s-0004QI-3u for emacs-orgmode@gnu.org; Wed, 14 Apr 2010 16:23:56 -0400 In-Reply-To: <87aatda0gv.fsf@stats.ox.ac.uk> List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: Dan Davison Cc: emacs org-mode mailing list On Thu, 08 Apr 2010 21:17:20 -0400, Dan Davison wrote: > I've been working on an Org tool to browse Emacs buffers. Emacs has the > function list-buffers (C-x C-b), where you can view a list of buffers, > delete buffers, etc. This is intended to be a replacement for > list-buffers, implemented in Org-mode. Excellent! I really like this. I currently use both bs-show and ido for buffer selection but I could easily be convinced to use this instead of bs-show. Some comments: > The buffer has some special key-bindings: I have a problem with the current bindings: you are (I guess) trying to emulate dired to some degree (cf. bindings for RET, 'd', 'o' [1] and 'x'). It would be nice therefore to have movement bindings as well ('n' and 'p'). I can obviously bind these myself but 'p' is already taken and it would be nice to be as consistent with the defaults as possible. Maybe 'P' for properties on/off? When I tried column view, the default widths are much too wide for my netbook. Can these be changed? More importantly, when I left column view, the buffer view was now different than the original view. Originally, I had two levels (mode + buffer) and now it was a single level (buffer). How do I get back to mode+buffer two level view? Thanks again! eric Footnotes: [1] I found 'o' initially annoying as knowing that I was in org, I expected it to behave like 'o' in agenda (hide other window)... From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dan Davison Subject: Re: Using Org for browsing and managing buffers Date: Thu, 15 Apr 2010 00:20:31 -0400 Message-ID: <87mxx5cpo0.fsf@stats.ox.ac.uk> References: <87aatda0gv.fsf@stats.ox.ac.uk> <87d3y1pyuz.wl%ucecesf@ucl.ac.uk> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O2GZG-0000Cn-CL for emacs-orgmode@gnu.org; Thu, 15 Apr 2010 00:20:42 -0400 Received: from [140.186.70.92] (port=34432 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O2GZD-0000C2-Uz for emacs-orgmode@gnu.org; Thu, 15 Apr 2010 00:20:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O2GZA-0005wO-DO for emacs-orgmode@gnu.org; Thu, 15 Apr 2010 00:20:39 -0400 Received: from markov.stats.ox.ac.uk ([163.1.210.1]:54650) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O2GZA-0005w9-2Y for emacs-orgmode@gnu.org; Thu, 15 Apr 2010 00:20:36 -0400 List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: e.fraga@ucl.ac.uk Cc: emacs org-mode mailing list --=-=-= Eric S Fraga writes: > On Thu, 08 Apr 2010 21:17:20 -0400, Dan Davison wrote: > >> I've been working on an Org tool to browse Emacs buffers. Emacs has the >> function list-buffers (C-x C-b), where you can view a list of buffers, >> delete buffers, etc. This is intended to be a replacement for >> list-buffers, implemented in Org-mode. > > Excellent! I really like this. I currently use both bs-show and ido > for buffer selection but I could easily be convinced to use this > instead of bs-show. Hi Eric, > Some comments: > >> The buffer has some special key-bindings: > > I have a problem with the current bindings: you are (I guess) trying > to emulate dired to some degree (cf. bindings for RET, 'd', 'o' [1] and > 'x'). It would be nice therefore to have movement bindings as well > ('n' and 'p'). I can obviously bind these myself but 'p' is already > taken and it would be nice to be as consistent with the defaults as > possible. Yes, I think I'm trying to emulate dired while still staying true to Org. But I hadn't thought carefully about the keybindings yet and your comments are very helpful. As an experiment at least, I've now changed things so that Org speed commands are turned on everywhere in the buffer. That means that we gain all the commands listed in `org-speed-commands-default', including n, p, f, b, u for movement. Another one I notice is useful is '.' for outline-mark-subtree, so that '. d x' deletes a group of buffers This does also mean that various inappropriate speed commands become exposed (but then pressing random keys is a strategy that should be confined to gnus). > Maybe 'P' for properties on/off? Done. > When I tried column view, the default widths are much too wide for my > netbook. Can these be changed? I've made them narrower by default, and introduced a customizable variable org-buffers-columns-format. > More importantly, when I left column > view, the buffer view was now different than the original view. Thanks. I've fixed that. > Originally, I had two levels (mode + buffer) and now it was a single > level (buffer). How do I get back to mode+buffer two level view? org-buffers-list:by, which is now bound to B (used to be b). It brings up minibuffer completion for the property you want to group by, so B maj RET would be enough to regroup by major-mode (should you need to). > > Thanks again! > > eric > > Footnotes: > [1] I found 'o' initially annoying as knowing that I was in org, I > expected it to behave like 'o' in agenda (hide other window)... Noted. On the other hand o in Org speed commands is bound to org-open-at-point. I've got rid of my binding and am allowing it to fall through to the speed command default but I'd welcome any further suggestions. Note that the variable org-buffers-follow-link-method can be used so specify the behaviour of RET on a line with a buffer link. Thanks a lot for the comments. The columns view thing is a bit experimental still; I'm not sure what to do about the key bindings, or indeed quite what the purpose of it is in this context, but it did seem like a natural buffer to allow it in. I haven't used bs-show. It might be interesting to try to get some of the power of ibuffer in this mode. But Org is better than the alternatives at hierarchical grouping and tree navigation. And also, the alternatives are very ugly. Current code below and at http://github.com/dandavison/org-buffers. Dan --=-=-= Content-Disposition: inline; filename=org-buffers.el ;;; org-buffers.el --- An Org-mode tool for buffer management ;; Copyright (C) 2010 Dan Davison ;; Author: Dan Davison ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org ;;; License: ;; This program 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 3, or (at your option) ;; any later version. ;; ;; This program 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 GNU Emacs; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;;; Code: (require 'org) (require 'cl) ;;; Variables (defvar org-buffers-buffer-name "*Buffers*" "Name of buffer in which buffer list is displayed") (defvar org-buffers-state '((:by . "major-mode") (:atom . heading) (:properties . nil)) "Association list specifying the current state of org-buffers.") (defvar org-buffers-follow-link-method 'org-open-at-point "Method used to follow link with RET. Must be one of 'org-open-at-point :: use `org-open-at-point' to follow link. 'current-window :: use switch-to-buffer 'other-window :: use switch-to-buffer-other-window Setting this variable to 'current-window makes the behaviour more consistent with that of `Buffer-menu-mode' and `dired-mode'") (defvar org-buffers-buffer-properties '(("buffer-name" . (buffer-name)) ("major-mode" . (let ((mode (symbol-name major-mode))) (if (string-match "-mode$" mode) (replace-match "" nil t mode) mode))) ("buffer-file-name" . (buffer-file-name)) ("default-directory" . default-directory) ("buffer-modified-p" . (format "%s" (buffer-modified-p)))) "Association list specifying properties to be stored for each buffer. The car of each element is the name of the property, and the cdr is an expression which, when evaluated in the buffer, yields the property value.") (defgroup org-buffers nil "Options for customising `org-buffers-mode'" :tag "Org-buffers Mode" :group 'org) (defcustom org-buffers-columns-format (mapconcat 'identity '("%15buffer-name(Buffer)" "%15major-mode(Mode)" "%20default-directory(Dir)" "%5buffer-modified-p(Modified)") " ") "Format for columns when viewing buffers listing in columns view. See `org-columns-default-format'." :group 'org-buffers) (defcustom org-buffers-excluded-buffers `("*Completions*" ,org-buffers-buffer-name) "List of names of buffers that should not be listed by org-buffers-list." :group 'org-buffers) (defcustom org-buffers-excluded-modes nil "List of names of major-modes (strings) that should not be listed by org-buffers-list." :group 'org-buffers) ;;; Mode (defvar org-buffers-mode-map (make-sparse-keymap)) (defvar org-buffers-mode-hook nil "Hook for functions to be called after buffer listing is created. Note that the buffer is read-only, so if the hook function is to modify the buffer it should use a let binding to temporarily bind inhibit-read-only to a non-nil value.") (define-minor-mode org-buffers-mode "An Org-mode tool for buffer management. In addition to the following org-buffers commands, all the commands listed in `org-speed-commands-default' are available. \\{org-buffers-mode-map}" nil " buffers" nil (org-set-local 'org-tag-alist '(("delete" . ?d))) (org-set-local'org-tags-column -50) (org-set-local 'org-columns-default-format org-buffers-columns-format) (org-set-local 'org-use-speed-commands (lambda () t)) (add-hook 'kill-buffer-hook 'org-buffers-reset-state nil 'local)) (defun org-buffers-help () (interactive) (describe-function 'org-buffers-mode)) ;;; Keys (define-key org-buffers-mode-map "B" 'org-buffers-list:by) (define-key org-buffers-mode-map "c" 'org-buffers-columns-view) (define-key org-buffers-mode-map "d" 'org-buffers-tag-for-deletion) (define-key org-buffers-mode-map "g" 'org-buffers-list:refresh) (define-key org-buffers-mode-map "h" 'org-buffers-toggle-headings) (define-key org-buffers-mode-map "P" 'org-buffers-toggle-properties) (define-key org-buffers-mode-map "q" 'bury-buffer) (define-key org-buffers-mode-map "u" 'org-buffers-remove-tags) (define-key org-buffers-mode-map "x" 'org-buffers-execute-pending-operations) (define-key org-buffers-mode-map [(return)] 'org-buffers-follow-link) (define-key org-buffers-mode-map "?" 'org-buffers-help) ;;; Listing and view cycling (defun org-buffers-list (&optional refresh frame) "Create an Org-mode listing of Emacs buffers. By default, buffers are grouped by major mode. Optional argument FRAME specifies the frame whose buffers should be listed." (interactive) (pop-to-buffer (or (and (not refresh) (get-buffer org-buffers-buffer-name)) (let ((org-buffers-p (equal (buffer-name) org-buffers-buffer-name)) (by (or (org-buffers-state-get :by) "major-mode")) (atom (org-buffers-state-get :atom)) target) (when org-buffers-p (if (and (org-before-first-heading-p) (not (org-on-heading-p))) (outline-next-heading)) (setq target (condition-case nil (org-make-org-heading-search-string) (error nil)))) (with-current-buffer (get-buffer-create org-buffers-buffer-name) (setq buffer-read-only nil) (erase-buffer) (org-mode) (dolist (buffer (sort (remove-if 'org-buffers-exclude-p (mapcar 'buffer-name (buffer-list frame))) 'string<)) (org-insert-heading t) (insert (org-make-link-string (concat "buffer:" buffer) buffer) "\n") (dolist (pair (org-buffers-get-buffer-props buffer)) (org-set-property (car pair) (cdr pair)))) (org-buffers-set-state '((:atom . heading))) (goto-char (point-min)) (unless (equal by "NONE") (org-buffers-group-by by)) (if target (condition-case nil (org-link-search target) (error nil))) (beginning-of-line) (if (equal by "NONE") (org-overview) (case atom ('heading (progn (org-overview) (org-content))) ('line (progn (show-all) (org-buffers-toggle-headings))))) (save-excursion (mark-whole-buffer) (indent-region (point-min) (point-max))) (org-buffers-mode) (setq buffer-read-only t) (current-buffer)))))) (defun org-buffers-list:refresh (&optional arg) "Refresh org-buffers listing." (interactive "P") (if arg (org-buffers-reset-state)) (org-buffers-list 'refresh)) (defun org-buffers-list:by (&optional prop) "Group buffers according to value of property PROP." (interactive) (let ((inhibit-read-only t) (headings-p (org-buffers-state-eq :atom 'heading))) (unless (org-buffers-state-get :properties) (org-buffers-toggle-properties)) (org-buffers-set-state `((:by . ,(or prop (org-completing-read "Property to group by: " (cons "NONE" (mapcar 'car org-buffers-buffer-properties))))))) (org-buffers-list 'refresh) (unless headings-p (org-buffers-toggle-headings)))) (defun org-buffers-toggle-properties () "Toggle entry properties in org-buffers listing buffer. Removing properties may provide a less cluttered appearance for browsing. However, in-buffer properties will be restored during certain operations, such as `org-buffers-list:by'." (interactive) (if (org-buffers-state-get :properties) (progn (org-buffers-delete-properties) (show-all) (org-buffers-set-state '((:properties . nil)))) (org-buffers-set-state '((:atom . heading) (:properties . t))) (org-buffers-list 'refresh))) (defun org-buffers-toggle-headings () "Toggle viewing of buffers as org headings. Headings will be automatically restored during certain operations, such as setting deletion tags." (interactive) (let ((inhibit-read-only t) (headings-p (org-buffers-state-eq :atom 'heading)) (flat-p (org-buffers-state-eq :by "NONE"))) (if (and headings-p (org-buffers-state-get :properties)) (org-buffers-toggle-properties)) (save-excursion (goto-char (point-min)) (if (and (or headings-p (not flat-p)) (not (outline-on-heading-p))) (outline-next-heading)) (if flat-p (progn (push-mark (point) 'nomsg 'activate) (goto-char (point-max)) (org-ctrl-c-star) (pop-mark)) (while (not (eobp)) (push-mark (save-excursion (forward-line 1) (point)) 'nomsg 'activate) (org-forward-same-level 1) (org-ctrl-c-star) (pop-mark))) (mark-whole-buffer) (indent-region (point-min) (point-max))) (org-buffers-set-state `((:atom . ,(if headings-p 'line 'heading)))))) (defun org-buffers-delete-properties () (let ((inhibit-read-only t)) (save-excursion (goto-char (point-min)) (org-buffers-delete-regions (nreverse (org-buffers-map-entries 'org-buffers-get-property-block)))))) (defun org-buffers-get-property-block () "Return the (beg . end) range of the property drawer. Unlike the org version the limits include the keywords delimiting the drawer." (let ((beg (point)) (end (progn (outline-next-heading) (point)))) (goto-char beg) (if (re-search-forward org-property-drawer-re end t) (cons (match-beginning 1) (match-end 0))))) (defun org-buffers-group-by (property) "Group top level headings according to the value of PROPERTY." (let ((atom (org-buffers-state-get :atom))) (save-excursion (goto-char (point-min)) (mapc (lambda (subtree) ;; Create subtree for each value of `property' (org-insert-heading t) (if (> (org-buffers-outline-level) 1) (org-promote)) (insert (car subtree) "\n") (org-insert-subheading t) (mapc 'org-buffers-insert-parsed-entry (cdr subtree))) (prog1 (mapcar (lambda (val) ;; Form list of parsed entries for each unique value of `property' (cons val (org-buffers-parse-selected-entries property val))) (sort (delete-dups (org-buffers-map-entries (lambda () (org-entry-get nil property nil)))) 'string<)) (erase-buffer)))))) (defun org-buffers-exclude-p (buffer) "Return non-nil if BUFFER should not be listed." (or (member (with-current-buffer buffer major-mode) org-buffers-excluded-modes) (member buffer org-buffers-excluded-buffers) (string= (substring buffer 0 1) " "))) (defun org-buffers-reset-state () (org-buffers-set-state '((:by . "major-mode") (:atom . heading) (:properties . nil)))) (defun org-buffers-columns-view () "View buffers in Org-mode columns view. This is currently experimental. RET can be used to follow links in the first column, but certain other org-buffers keys conflict with column-view or otherwise do not work correctly." (interactive) (let ((inhibit-read-only t)) (unless (org-buffers-state-get :properties) (org-buffers-toggle-properties)) (save-excursion (goto-char (point-min)) (org-columns)))) ;;; Parsing and inserting entries (defun org-buffers-parse-selected-entries (prop val) "Parse all entries with property PROP value VAL." (delq nil (org-buffers-map-entries (lambda () (when (equal (org-entry-get nil prop) val) (cons (org-get-heading) (org-get-entry))))))) (defun org-buffers-insert-parsed-entry (entry) "Insert a parsed entry" (unless (org-at-heading-p) (org-insert-heading)) (insert (car entry) "\n") (if (org-buffers-state-get :properties) (insert (cdr entry)))) (defun org-buffers-get-buffer-props (buffer) "Create alist of properties of BUFFER, as strings." (with-current-buffer buffer (mapcar (lambda (pair) (cons (car pair) (eval (cdr pair)))) org-buffers-buffer-properties))) ;;; Follow-link behaviour (defun org-buffers-follow-link () "Follow link to buffer on this line. The buffer-switching behaviour of this function is determined by the variable `org-buffers-follow-link-method'. See also `org-buffers-switch-to-buffer' and `org-buffers-switch-to-buffer-other-window', whose behaviour is hard-wired." (interactive) (org-buffers-switch-to-buffer-generic org-buffers-follow-link-method)) (defun org-buffers-switch-to-buffer () "Switch to this entry's buffer in current window." (interactive) (org-buffers-switch-to-buffer-generic 'current-window)) (defun org-buffers-switch-to-buffer-other-window () "Switch to this entry's buffer in other window." (interactive) (org-buffers-switch-to-buffer-generic 'other-window)) (defun org-buffers-switch-to-buffer-generic (method) (save-excursion (let ((atom (org-buffers-state-get :atom)) buffer) (cond ((eq atom 'heading) (org-back-to-heading)) (t (beginning-of-line))) (setq buffer (org-buffers-get-buffer-name)) (if (get-buffer buffer) (case method ('org-open-at-point (org-open-at-point)) ('current-window (switch-to-buffer buffer)) ('other-window (switch-to-buffer-other-window buffer))) (error "No such buffer: %s" buffer))))) (defun org-buffers-get-buffer-name () "Get buffer-name for current entry." (let ((headings-p (org-buffers-state-eq :atom 'heading))) (or (and headings-p (org-entry-get nil "buffer-name")) (and (save-excursion (if headings-p (org-back-to-heading)) (re-search-forward "\\[\\[buffer:\\([^\]]*\\)" (point-at-eol) t)) (org-link-unescape (match-string 1)))))) ;;; Setting tags and executing operations (defun org-buffers-tag-for-deletion () "Mark buffer for deletion. If a region is selected, all buffers in the region are marked for deletion. Buffers marked for deletion can be deleted using `org-buffers-execute-pending-operations'." (interactive) (org-buffers-set-tags '("delete"))) (defun org-buffers-remove-tags () "Remove deletion marks from buffers. If a region is selected, marks are removed from all buffers in the region." (interactive) (org-buffers-set-tags nil)) (defun org-buffers-set-tags (data) "Set tags to DATA at all non top-level headings in region. DATA should be a list of strings. If DATA is nil, remove all tags at such headings." (let* ((inhibit-read-only t) (region-p (org-region-active-p)) (beg (if region-p (region-beginning) (point))) (end (if region-p (region-end) (point))) (headings-p (org-buffers-state-eq :atom 'heading)) beg-line end-line end-of-last-heading) (save-excursion (setq beg-line (progn (goto-char beg) (org-current-line)) end-line (progn (goto-char end) (org-current-line)) end-of-last-heading (progn (outline-end-of-heading) (point))) (if headings-p (setq end (if (and region-p (not (eq end-line beg-line)) (not (eq end end-of-last-heading))) (progn (goto-char end) (org-back-to-heading) (point)) end-of-last-heading) beg (progn (goto-char beg) (point-at-bol))) (org-buffers-toggle-headings) ;; doesn't alter line numbers (setq beg (progn (org-goto-line beg-line) (point-at-bol)) end (if (eq end-line beg-line) (point-at-eol) (progn (org-goto-line end-line) (point-at-bol))))) (narrow-to-region beg end) (goto-char (point-min)) (org-buffers-map-entries (lambda () (when (or (org-buffers-state-eq :by "NONE") (> (org-outline-level) 1)) (org-set-tags-to (if data (delete-duplicates (append data (org-get-tags)) :test 'string-equal)))))) (widen) (org-content)) (unless region-p (outline-next-heading) (unless (or (> (org-outline-level) 1) (org-buffers-state-eq :by "NONE")) (outline-next-heading))) (unless headings-p (org-buffers-toggle-headings)))) (defun org-buffers-execute-pending-operations () "Execute all pending operations. Currently the only type of operation supported is deletion. Buffers are tagged for deletion using `org-buffers-tag-for-deletion'. Remove such tags from buffers using `org-buffers-remove-tags'." (interactive) (let ((inhibit-read-only t) (headings-p (org-buffers-state-eq :atom 'heading)) buffer) (unless headings-p (org-buffers-toggle-headings)) (org-buffers-delete-regions (nreverse (org-buffers-map-entries (lambda () (if (setq buffer (org-buffers-get-buffer-name)) (if (not (kill-buffer buffer)) (error "Failed to kill buffer %s" buffer) (cons (point) (1+ (org-end-of-subtree)))))) "+delete"))) (org-buffers-delete-regions (nreverse (org-buffers-map-entries (lambda () (if (and (eq (org-outline-level) 1) (eq (point-at-eol) (org-end-of-subtree))) (cons (point-at-bol) (1+ (point)))))))) (unless headings-p (org-buffers-toggle-headings)))) ;;; Utilities (defun org-buffers-map-entries (func &optional match) (org-scan-tags func (if match (cdr (org-make-tags-matcher match)) t))) (defun org-buffers-set-state (state) "Add STATE to global state list. New settings have precedence over existing ones." (mapc (lambda (pair) (unless (assoc (car pair) state) (add-to-list 'state pair))) org-buffers-state) (setq org-buffers-state state)) (defmacro org-buffers-delete-regions (regions) "Delete regions in list. REGIONS is a list of (beg . end) cons cells specifying buffer regions." `(mapc (lambda (pair) (if pair (delete-region (car pair) (cdr pair)))) ,regions)) (defmacro org-buffers-state-get (key) `(cdr (assoc ,key org-buffers-state))) (defmacro org-buffers-state-eq (key val) `(equal (org-buffers-state-get ,key) ,val)) (defmacro org-buffers-outline-level () '(save-excursion (beginning-of-line) (org-outline-level))) ;;; Links to buffers (org-add-link-type "buffer" 'display-buffer) (add-hook 'org-store-link-functions 'org-buffers-store-link) (defun org-buffers-store-link (&optional force) "Store a link to an Emacs buffer. Returns nil by default, to avoid hijacking other link types." (if force (let* ((target (buffer-name)) (desc target) link) (org-store-link-props :type "buffer") (setq link (org-make-link "buffer:" target)) (org-add-link-props :link link :description desc) link))) (provide 'org-buffers) ;;; org-buffers.el ends here --=-=-= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Emacs-orgmode mailing list Please use `Reply All' to send replies to the list. Emacs-orgmode@gnu.org http://lists.gnu.org/mailman/listinfo/emacs-orgmode --=-=-=-- From mboxrd@z Thu Jan 1 00:00:00 1970 From: Livin Stephen Sharma Subject: Re: Using Org for browsing and managing buffers Date: Thu, 15 Apr 2010 15:41:43 +0530 Message-ID: References: <87aatda0gv.fsf@stats.ox.ac.uk> Mime-Version: 1.0 (Apple Message framework v1078) Content-Type: multipart/mixed; boundary="===============1622594151==" Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O2M3K-0001Mg-To for emacs-orgmode@gnu.org; Thu, 15 Apr 2010 06:12:07 -0400 Received: from [140.186.70.92] (port=56421 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O2M3G-0001JR-Vw for emacs-orgmode@gnu.org; Thu, 15 Apr 2010 06:12:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O2M3B-0001I2-RR for emacs-orgmode@gnu.org; Thu, 15 Apr 2010 06:12:02 -0400 Received: from mail-ew0-f214.google.com ([209.85.219.214]:36338) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O2M3B-0001Hf-Ae for emacs-orgmode@gnu.org; Thu, 15 Apr 2010 06:11:57 -0400 Received: by ewy6 with SMTP id 6so434594ewy.32 for ; Thu, 15 Apr 2010 03:11:56 -0700 (PDT) In-Reply-To: <87aatda0gv.fsf@stats.ox.ac.uk> List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: emacs-org-mode-help gnu Cc: Dan Davison --===============1622594151== Content-Type: multipart/alternative; boundary=Apple-Mail-6-961327285 --Apple-Mail-6-961327285 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii Am I the only one encountering: > org-buffers-list: Invalid function: org-buffers-state-get I do see many people are using this successfully :) Livin Stephen On Apr 09, 2010, at 06:47:20 , Dan Davison wrote: > I've been working on an Org tool to browse Emacs buffers. Emacs has = the > function list-buffers (C-x C-b), where you can view a list of buffers, > delete buffers, etc. This is intended to be a replacement for > list-buffers, implemented in Org-mode. >=20 > The code is attached, and there's a git repo at > http://github.com/dandavison/org-buffers >=20 > After putting the code in your load-path and doing=20 > (require 'org-buffers), use the function `org-buffers-list' to create > the listing buffer. This is a read-only Org-mode buffer populated with > links to open buffers. Information is stored for each buffer using > properties. By default, the buffers are grouped by major mode. Here's = a > screenshot. >=20 > http://www.princeton.edu/~ddavison/org-buffers/by-major-mode.png >=20 > The buffer has some special key-bindings: >=20 > ? Show all keybindings > g Update buffer (prefix arg does hard reset) > b Select a different property to group by > RET follow link to buffer on this line > d Mark buffer for deletion > u Remove mark > x Delete marked buffers > o Like RET (see variable org-buffers-follow-link-method) > . Like RET but switch to buffer in same window > h toggle between headings and plain entries for buffers > p toggle in-buffer properties on/off > c Switch to column-view >=20 > If there's an active region, d and u operate on all buffers in the > region. >=20 > Some variables that can be configured: > - org-buffers-buffer-properties > - org-buffers-excluded-modes > - org-buffers-excluded-buffers > - org-buffers-follow-link-method > - org-buffers-mode-hook > - org-buffers-buffer-name >=20 > Some possible extensions: > - Browse recent files using recentf > - Allow several buffers to be marked for side-by-side display > - Maintain folding configuration across buffer updates > - Make faster >=20 > As always, any feedback, suggestions and patches will be very welcome! >=20 > Dan >=20 > p.s. The column-view mode works for following links, but does need > further attention. >=20 > ;;; org-buffers.el --- An Org-mode tool for buffer management >=20 > ;; Copyright (C) 2010 Dan Davison >=20 > ;; Author: Dan Davison > ;; Keywords: outlines, hypermedia, calendar, wp > ;; Homepage: http://orgmode.org >=20 > ;;; License: >=20 > ;; This program 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 3, or (at your option) > ;; any later version. > ;; > ;; This program 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 GNU Emacs; see the file COPYING. If not, write to the > ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, > ;; Boston, MA 02110-1301, USA. >=20 > ;;; Commentary: >=20 > ;;; Code: >=20 > (require 'org) > (require 'cl) >=20 > ;;; Variables > (defvar org-buffers-buffer-name > "*Buffers*" > "Name of buffer in which buffer list is displayed") >=20 > (defvar org-buffers-state > '((:by . "major-mode") (:atom . heading) (:properties . nil)) > "Association list specifiying the current state of org-buffers.") >=20 > (defvar org-buffers-follow-link-method 'org-open-at-point > "Method used to follow link with RET. Must be one of >=20 > 'org-open-at-point :: use `org-open-at-point' to follow link. > 'current-window :: use switch-to-buffer > 'other-window :: use switch-to-buffer-other-window >=20 > Setting this variable to 'current-window makes the behaviour more > consistent with that of `Buffer-menu-mode' and `dired-mode'") >=20 > (defvar org-buffers-buffer-properties > '(("buffer-name" . (buffer-name)) > ("major-mode" . (let ((mode (symbol-name major-mode))) > (if (string-match "-mode$" mode) > (replace-match "" nil t mode) mode))) > ("buffer-file-name" . (buffer-file-name)) > ("default-directory" . default-directory) > ("buffer-modified-p" . (format "%s" (buffer-modified-p)))) > "Association list specifying properties to be stored for each > buffer. The car of each element is the name of the property, and > the cdr is an expression which, when evaluated in the buffer, > yields the property value.") >=20 > (defcustom org-buffers-excluded-buffers > `("*Completions*" ,org-buffers-buffer-name) > "List of names of buffers that should not be listed by > org-buffers-list." > :group 'org-buffers) >=20 > (defcustom org-buffers-excluded-modes nil > "List of names of major-modes (strings) that should not be listed > by org-buffers-list." > :group 'org-buffers) >=20 > ;;; Mode > (defvar org-buffers-mode-map (make-sparse-keymap)) >=20 > (defvar org-buffers-mode-hook nil > "Hook for functions to be called after buffer listing is > created. Note that the buffer is read-only, so if the hook > function is to modify the buffer it should use a let binding to > temporarily bind buffer-read-only to nil.") >=20 > (define-minor-mode org-buffers-mode > "An Org-mode tool for buffer management. > \\{org-buffers-mode-map}" > nil " buffers" nil > (org-set-local 'org-tag-alist '(("delete" . ?d))) > (org-set-local'org-tags-column -50) > (org-set-local 'org-columns-default-format "%25buffer-name(Buffer) = %25major-mode(Mode) %25default-directory(Dir) = %5buffer-modified-p(Modified)") > (add-hook 'kill-buffer-hook 'org-buffers-reset-state nil 'local)) >=20 > (defun org-buffers-help () > (interactive) > (describe-function 'org-buffers-mode)) >=20 > ;;; Keys > (define-key org-buffers-mode-map [(return)] 'org-buffers-follow-link) > (define-key org-buffers-mode-map "b" 'org-buffers-list:by) > (define-key org-buffers-mode-map "c" 'org-buffers-columns-view) > (define-key org-buffers-mode-map "d" 'org-buffers-tag-for-deletion) > (define-key org-buffers-mode-map "g" 'org-buffers-list:refresh) > (define-key org-buffers-mode-map "." 'org-buffers-switch-to-buffer) > (define-key org-buffers-mode-map "h" 'org-buffers-toggle-headings) > (define-key org-buffers-mode-map "o" = 'org-buffers-switch-to-buffer-other-window) > (define-key org-buffers-mode-map "p" 'org-buffers-toggle-properties) > (define-key org-buffers-mode-map "u" 'org-buffers-remove-tags) > (define-key org-buffers-mode-map "x" = 'org-buffers-execute-pending-operations) > (define-key org-buffers-mode-map "?" 'org-buffers-help) > ;;; Listing and view cycling >=20 > (defun org-buffers-list (&optional refresh frame) > "Create an Org-mode listing of Emacs buffers. > By default, buffers are grouped by major mode. Optional > argument FRAME specifies the frame whose buffers should be > listed." > (interactive) > (pop-to-buffer > (or > (and (not refresh) (get-buffer org-buffers-buffer-name)) > (let ((org-buffers-p (equal (buffer-name) org-buffers-buffer-name)) > (by (or (org-buffers-state-get :by) "major-mode")) > (atom (org-buffers-state-get :atom)) target) > (when org-buffers-p > (if (and (org-before-first-heading-p) (not (org-on-heading-p))) > (outline-next-heading)) > (setq target > (condition-case nil (org-make-org-heading-search-string) = (error nil)))) > (with-current-buffer (get-buffer-create org-buffers-buffer-name) > (setq buffer-read-only nil) > (erase-buffer) > (org-mode) > (dolist > (buffer > (sort (remove-if 'org-buffers-exclude-p > (mapcar 'buffer-name (buffer-list frame))) = 'string<)) > (org-insert-heading t) > (insert > (org-make-link-string (concat "buffer:" buffer) buffer) "\n") > (dolist (pair (org-buffers-get-buffer-props buffer)) > (org-set-property (car pair) (cdr pair)))) > (org-buffers-set-state '((:atom . heading))) > (goto-char (point-min)) > (unless (equal by "NONE") (org-buffers-group-by by)) > (if target (condition-case nil (org-link-search target) (error = nil))) > (beginning-of-line) > (if (equal by "NONE") > (org-overview) > (case atom > ('heading (progn (org-overview) (org-content))) > ('line (progn (show-all) (org-buffers-toggle-headings))))) > (save-excursion > (mark-whole-buffer) > (indent-region (point-min) (point-max))) > (org-buffers-mode) > (setq buffer-read-only t) > (current-buffer)))))) >=20 > (defun org-buffers-list:refresh (&optional arg) > "Refresh org-buffers listing." > (interactive "P") > (if arg (org-buffers-reset-state)) > (org-buffers-list 'refresh)) >=20 > (defun org-buffers-list:by (&optional prop) > "Group buffers according to value of property PROP." > (interactive) > (let ((buffer-read-only nil) > (headings-p (org-buffers-state-eq :atom 'heading))) > (unless (org-buffers-state-get :properties) > (org-buffers-toggle-properties)) > (org-buffers-set-state > `((:by . > ,(or prop > (org-completing-read > "Property to group by: " > (cons "NONE" (mapcar 'car = org-buffers-buffer-properties))))))) > (org-buffers-list 'refresh) > (unless headings-p (org-buffers-toggle-headings)))) >=20 > (defun org-buffers-toggle-properties () > "Toggle entry properties in org-buffers listing buffer. > Removing properties may provide a less cluttered appearance for > browsing. However, in-buffer properties will be restored during > certain operations, such as `org-buffers-list:by'." > (interactive) > (if (org-buffers-state-get :properties) > (progn (org-buffers-delete-properties) > (show-all) > (org-buffers-set-state '((:properties . nil)))) > (org-buffers-set-state > '((:atom . heading) (:properties . t))) > (org-buffers-list 'refresh))) >=20 > (defun org-buffers-toggle-headings () > "Toggle viewing of buffers as org headings. > Headings will be automatically restored during certain > operations, such as setting deletion tags." > (interactive) > (let ((buffer-read-only nil) > (headings-p (org-buffers-state-eq :atom 'heading)) > (flat-p (org-buffers-state-eq :by "NONE"))) > (if (and headings-p (org-buffers-state-get :properties)) > (org-buffers-toggle-properties)) > (save-excursion > (goto-char (point-min)) > (if (and (or headings-p (not flat-p)) > (not (outline-on-heading-p))) > (outline-next-heading)) > (if flat-p > (progn=20 > (push-mark (point) 'nomsg 'activate) > (end-of-buffer) > (org-ctrl-c-star) > (pop-mark)) > (while (not (eobp)) > (push-mark > (save-excursion (forward-line 1) (point)) 'nomsg 'activate) > (org-forward-same-level 1)=09 > (org-ctrl-c-star) > (pop-mark))) > (mark-whole-buffer) > (indent-region (point-min) (point-max))) > (org-buffers-set-state > `((:atom . ,(if headings-p 'line 'heading)))))) >=20 > (defun org-buffers-delete-properties () > (let ((buffer-read-only nil)) > (save-excursion > (goto-char (point-min)) > (org-buffers-delete-regions > (nreverse > (org-buffers-map-entries 'org-buffers-get-property-block)))))) >=20 > (defun org-buffers-get-property-block () > "Return the (beg . end) range of the property drawer. > Unlike the org version the limits include the keywords delimiting > the drawer." > (let ((beg (point)) > (end (progn (outline-next-heading) (point)))) > (goto-char beg) > (if (re-search-forward org-property-drawer-re end t) > (cons (match-beginning 1) (match-end 0))))) >=20 > (defun org-buffers-group-by (property) > "Group top level headings according to the value of PROPERTY." > (let ((atom (org-buffers-state-get :atom))) > (save-excursion > (goto-char (point-min)) > (mapc (lambda (subtree) ;; Create subtree for each value of = `property' > (org-insert-heading t) > (if (> (org-buffers-outline-level) 1) > (org-promote)) > (insert (car subtree) "\n") > (org-insert-subheading t) > (mapc 'org-buffers-insert-parsed-entry (cdr subtree))) > (prog1 > (mapcar (lambda (val) ;; Form list of parsed entries for = each unique value of `property' > (cons val (org-buffers-parse-selected-entries = property val))) > (sort > (delete-dups (org-buffers-map-entries (lambda = () (org-entry-get nil property nil)))) > 'string<)) > (erase-buffer)))))) >=20 > (defun org-buffers-exclude-p (buffer) > "Return non-nil if BUFFER should not be listed." > (or (member (with-current-buffer buffer major-mode) > org-buffers-excluded-modes) > (member buffer org-buffers-excluded-buffers) > (string=3D (substring buffer 0 1) " "))) >=20 > (defun org-buffers-reset-state () > (org-buffers-set-state > '((:by . "major-mode") (:atom . heading) (:properties . nil)))) >=20 > (defun org-buffers-columns-view () > "View buffers in Org-mode columns view. > This is currently experimental. RET can be used to follow links > in the first column, but certain other org-buffers keys conflict > with column-view or otherwise do not work correctly." > (interactive) > (let ((by (org-buffers-state-get :by)) > (buffer-read-only nil)) > (unless (equal by "NONE") (org-buffers-list:by "NONE")) > (unless (org-buffers-state-get :properties) > (org-buffers-toggle-properties)) > (unless (equal by "NONE") > (goto-char (point-min)) > (org-sort-entries-or-items nil ?r nil nil by) > (org-overview)) > (mark-whole-buffer) > (org-columns))) >=20 > ;;; Parsing and inserting entries > (defun org-buffers-parse-selected-entries (prop val) > "Parse all entries with property PROP value VAL." > (delq nil > (org-buffers-map-entries > (lambda () (when (equal (org-entry-get nil prop) val) > (cons (org-get-heading) (org-get-entry))))))) >=20 > (defun org-buffers-insert-parsed-entry (entry) > "Insert a parsed entry" > (unless (org-at-heading-p) (org-insert-heading)) > (insert (car entry) "\n") > (if (org-buffers-state-get :properties) > (insert (cdr entry)))) >=20 > (defun org-buffers-get-buffer-props (buffer) > "Create alist of properties of BUFFER, as strings." > (with-current-buffer buffer > (mapcar=20 > (lambda (pair) (cons (car pair) (eval (cdr pair)))) > org-buffers-buffer-properties))) >=20 > ;;; Follow-link behaviour >=20 > (defun org-buffers-follow-link () > "Follow link to buffer on this line. > The buffer-switching behaviour of this function is determined by > the variable `org-buffers-follow-link-method'. See also > `org-buffers-switch-to-buffer' and > `org-buffers-switch-to-buffer-other-window', whose behaviour is > hard-wired." > (interactive) > (org-buffers-switch-to-buffer-generic = org-buffers-follow-link-method)) >=20 > (defun org-buffers-switch-to-buffer () > "Switch to this entry's buffer in current window." > (interactive) > (org-buffers-switch-to-buffer-generic 'current-window)) >=20 > (defun org-buffers-switch-to-buffer-other-window () > "Switch to this entry's buffer in other window." > (interactive) > (org-buffers-switch-to-buffer-generic 'other-window)) >=20 > (defun org-buffers-switch-to-buffer-generic (method) > (save-excursion > (let ((atom (org-buffers-state-get :atom)) buffer) > (cond > ((eq atom 'heading) (org-back-to-heading)) > (t (beginning-of-line))) > (setq buffer (org-buffers-get-buffer-name)) > (if (get-buffer buffer) > (case method > ('org-open-at-point (org-open-at-point)) > ('current-window (switch-to-buffer buffer)) > ('other-window (switch-to-buffer-other-window buffer))) > (error "No such buffer: %s" buffer))))) >=20 > (defun org-buffers-get-buffer-name () > "Get buffer-name for current entry." > (let ((headings-p (org-buffers-state-eq :atom 'heading))) > (or (and headings-p (org-entry-get nil "buffer-name")) > (and (save-excursion > (if headings-p (org-back-to-heading)) > (re-search-forward "\\[\\[buffer:\\([^\]]*\\)" = (point-at-eol) t)) > (org-link-unescape (match-string 1)))))) >=20 > ;;; Setting tags and executing operations >=20 > (defun org-buffers-tag-for-deletion () > "Mark buffer for deletion. > If a region is selected, all buffers in the region are marked for > deletion. Buffers marked for deletion can be deleted using > `org-buffers-execute-pending-operations'." > (interactive) > (org-buffers-set-tags '("delete"))) >=20 > (defun org-buffers-remove-tags () > "Remove deletion marks from buffers. > If a region is selected, marks are removed from all buffers in > the region." > (interactive) > (org-buffers-set-tags nil)) >=20 > (defun org-buffers-set-tags (data) > "Set tags to DATA at all non top-level headings in region. > DATA should be a list of strings. If DATA is nil, remove all tags > at such headings." > (let* ((buffer-read-only nil) > (region-p (org-region-active-p)) > (beg (if region-p (region-beginning) (point))) > (end (if region-p (region-end) (point))) > (headings-p (org-buffers-state-eq :atom 'heading))beg-line = end-line) > (save-excursion > (setq beg-line (progn (goto-char beg) (org-current-line)) > end-line (progn (goto-char end) (org-current-line))) > (if headings-p > (setq > end (if (and region-p (not (eq end-line beg-line)) (not = (eobp))) > (progn (goto-char end) (org-back-to-heading) (point)) > (progn (outline-end-of-heading) (point))) > beg (progn (goto-char beg) (point-at-bol))) > (org-buffers-toggle-headings) ;; doesn't alter line numbers > (setq beg (progn (org-goto-line beg-line) (point-at-bol)) > end (if (eq end-line beg-line) (point-at-eol) > (progn (org-goto-line end-line) (point-at-bol))))) > (narrow-to-region beg end) > (goto-char (point-min)) > (org-buffers-map-entries > (lambda () > (when (or (org-buffers-state-eq :by "NONE") > (> (org-outline-level) 1)) > (org-set-tags-to > (if data (delete-duplicates (append data (org-get-tags)) = :test 'string-equal)))))) > (widen) > (org-content)) > (unless region-p > (outline-next-heading) > (unless (or (> (org-outline-level) 1) (org-buffers-state-eq :by = "NONE")) > (outline-next-heading))) > (unless headings-p (org-buffers-toggle-headings)))) >=20 > (defun org-buffers-execute-pending-operations () > "Execute all pending operations. > Currently the only type of operation supported is > deletion. Buffers are tagged for deletion using > `org-buffers-tag-for-deletion'. Remove such tags from buffers > using `org-buffers-remove-tags'." > (interactive) > (let ((buffer-read-only nil) > (headings-p (org-buffers-state-eq :atom 'heading)) buffer) > (unless headings-p (org-buffers-toggle-headings)) > (org-buffers-delete-regions > (nreverse > (org-buffers-map-entries > (lambda () > (if (setq buffer (org-buffers-get-buffer-name)) > (if (not (kill-buffer buffer)) > (error "Failed to kill buffer %s" buffer) > (if (and (org-first-sibling-p) > (not (save-excursion (org-goto-sibling)))) > (org-up-heading-safe)) ;; Only child so delete parent = also > (cons (point) (1+ (org-end-of-subtree)))))) > "+delete"))) > (unless headings-p (org-buffers-toggle-headings)))) >=20 > ;;; Utilities >=20 > (defun org-buffers-map-entries (func &optional match) > (org-scan-tags > func (if match (cdr (org-make-tags-matcher match)) t))) >=20 > (defun org-buffers-set-state (state) > "Add STATE to global state list. > New settings have precedence over existing ones." > (mapc > (lambda (pair) (unless (assoc (car pair) state) > (add-to-list 'state pair))) > org-buffers-state) > (setq org-buffers-state state)) >=20 > (defmacro org-buffers-delete-regions (regions) > "Delete regions in list. > REGIONS is a list of (beg . end) cons cells specifying buffer > regions." > `(mapc (lambda (pair) (if pair (delete-region (car pair) (cdr = pair)))) > ,regions)) >=20 > (defmacro org-buffers-state-get (key) > `(cdr (assoc ,key org-buffers-state))) >=20 > (defmacro org-buffers-state-eq (key val) > `(equal (org-buffers-state-get ,key) ,val)) >=20 > (defmacro org-buffers-outline-level () > '(save-excursion (beginning-of-line) (org-outline-level))) >=20 > ;;; Links to buffers >=20 > (org-add-link-type "buffer" 'display-buffer) > (add-hook 'org-store-link-functions 'org-buffers-store-link) >=20 > (defun org-buffers-store-link (&optional force) > "Store a link to an Emacs buffer. > Returns nil by default, to avoid hijacking other link types." > (if force > (let* ((target (buffer-name)) > (desc target) link) > (org-store-link-props :type "buffer") > (setq link (org-make-link "buffer:" target)) > (org-add-link-props :link link :description desc) > link))) >=20 > (provide 'org-buffers) > ;;; org-buffers.el ends here > _______________________________________________ > Emacs-orgmode mailing list > Please use `Reply All' to send replies to the list. > Emacs-orgmode@gnu.org > http://lists.gnu.org/mailman/listinfo/emacs-orgmode --Apple-Mail-6-961327285 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=us-ascii Am I = the only one encountering:
org-buffers-list: Invalid = function: = org-buffers-state-get


I = do see many people are using this = successfully
:)

Livin = Stephen



On Apr 09, 2010, at 06:47:20 , Dan Davison wrote:

I've been = working on an Org tool to browse Emacs buffers. Emacs has = the
function list-buffers (C-x C-b), where you can view a list of = buffers,
delete buffers, etc. This is intended to be a replacement = for
list-buffers, implemented in Org-mode.

The code is = attached, and there's a git repo at
http://github.com/dandav= ison/org-buffers

After putting the code in your load-path and = doing
(require 'org-buffers), use the function `org-buffers-list' to = create
the listing buffer. This is a read-only Org-mode buffer = populated with
links to open buffers. Information is stored for each = buffer using
properties. By default, the buffers are grouped by major = mode. Here's = a
screenshot.

http://www.princeton.edu/~ddavison/org-buffers/by-= major-mode.png

The buffer has some special = key-bindings:

?Show all keybindings
gUpdate buffer (prefix arg does hard reset)
bSelect a different property to group by
RETfollow link to buffer on this line
dMark buffer for deletion
uRemove mark
xDelete marked buffers
oLike RET (see variable = org-buffers-follow-link-method)
.Like RET but switch to buffer in same window
htoggle between headings and plain entries for = buffers
ptoggle in-buffer properties on/off
cSwitch to column-view

If there's an active region, d and u operate on all buffers in = the
region.

Some variables that can be configured:
- = org-buffers-buffer-properties
- org-buffers-excluded-modes
- = org-buffers-excluded-buffers
- org-buffers-follow-link-method
- = org-buffers-mode-hook
- org-buffers-buffer-name

Some possible = extensions:
- Browse recent files using recentf
- Allow several = buffers to be marked for side-by-side display
- Maintain folding = configuration across buffer updates
- Make faster

As always, = any feedback, suggestions and patches will be very = welcome!

Dan

p.s. The column-view mode works for following = links, but does need
further attention.

;;; org-buffers.el --- = An Org-mode tool for buffer management

;; Copyright (C) 2010 =  Dan Davison

;; Author: Dan Davison <dandavison0 at gmail = dot com>
;; Keywords: outlines, hypermedia, calendar, wp
;; = Homepage: http://orgmode.org

;;; License:

;; This program = 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 3, or (at your option)
;; = any later version.
;;
;; This program 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 GNU Emacs; see the file COPYING. =  If not, write to the
;; Free Software Foundation, Inc., 51 = Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, = USA.

;;; Commentary:

;;; Code:

(require = 'org)
(require 'cl)

;;; Variables
(defvar = org-buffers-buffer-name
 "*Buffers*"
 "Name of buffer = in which buffer list is displayed")

(defvar org-buffers-state
=  '((:by . "major-mode") (:atom . heading) (:properties . nil))
=  "Association list specifiying the current state of = org-buffers.")

(defvar org-buffers-follow-link-method = 'org-open-at-point
 "Method used to follow link with RET. Must = be one of

'org-open-at-point :: use `org-open-at-point' to follow = link.
'current-window    :: use = switch-to-buffer
'other-window      :: use = switch-to-buffer-other-window

Setting this variable to = 'current-window makes the behaviour more
consistent with that of = `Buffer-menu-mode' and `dired-mode'")

(defvar = org-buffers-buffer-properties
 '(("buffer-name" . = (buffer-name))
   ("major-mode" . (let ((mode = (symbol-name major-mode)))
=      (if (string-match "-mode$" mode)
=  (replace-match "" nil t mode) mode)))
=    ("buffer-file-name" . (buffer-file-name))
=    ("default-directory" . default-directory)
=    ("buffer-modified-p" . (format "%s" = (buffer-modified-p))))
 "Association list specifying properties = to be stored for each
buffer. The car of each element is the name of = the property, and
the cdr is an expression which, when evaluated in = the buffer,
yields the property value.")

(defcustom = org-buffers-excluded-buffers
 `("*Completions*" = ,org-buffers-buffer-name)
 "List of names of buffers that = should not be listed by
 org-buffers-list."
 :group = 'org-buffers)

(defcustom org-buffers-excluded-modes nil
=  "List of names of major-modes (strings) that should not be = listed
 by org-buffers-list."
 :group = 'org-buffers)

;;; Mode
(defvar org-buffers-mode-map = (make-sparse-keymap))

(defvar org-buffers-mode-hook nil
=  "Hook for functions to be called after buffer listing is
=  created. Note that the buffer is read-only, so if the hook
=  function is to modify the buffer it should use a let binding = to
 temporarily bind buffer-read-only to = nil.")

(define-minor-mode org-buffers-mode
 "An Org-mode = tool for buffer management.
\\{org-buffers-mode-map}"
 nil " = buffers" nil
 (org-set-local 'org-tag-alist '(("delete" . = ?d)))
 (org-set-local'org-tags-column -50)
=  (org-set-local 'org-columns-default-format "%25buffer-name(Buffer) = %25major-mode(Mode) %25default-directory(Dir) = %5buffer-modified-p(Modified)")
 (add-hook 'kill-buffer-hook = 'org-buffers-reset-state nil 'local))

(defun org-buffers-help = ()
 (interactive)
 (describe-function = 'org-buffers-mode))

;;; Keys
(define-key org-buffers-mode-map = [(return)] 'org-buffers-follow-link)
(define-key org-buffers-mode-map = "b" 'org-buffers-list:by)
(define-key org-buffers-mode-map "c" = 'org-buffers-columns-view)
(define-key org-buffers-mode-map "d" = 'org-buffers-tag-for-deletion)
(define-key org-buffers-mode-map "g" = 'org-buffers-list:refresh)
(define-key org-buffers-mode-map "." = 'org-buffers-switch-to-buffer)
(define-key org-buffers-mode-map "h" = 'org-buffers-toggle-headings)
(define-key org-buffers-mode-map "o" = 'org-buffers-switch-to-buffer-other-window)
(define-key = org-buffers-mode-map "p" 'org-buffers-toggle-properties)
(define-key = org-buffers-mode-map "u" 'org-buffers-remove-tags)
(define-key = org-buffers-mode-map "x" = 'org-buffers-execute-pending-operations)
(define-key = org-buffers-mode-map "?" 'org-buffers-help)
;;; Listing and view = cycling

(defun org-buffers-list (&optional refresh frame)
=  "Create an Org-mode listing of Emacs buffers.
By default, = buffers are grouped by major mode. Optional
argument FRAME specifies = the frame whose buffers should be
listed."
=  (interactive)
 (pop-to-buffer
  (or
=    (and (not refresh) (get-buffer = org-buffers-buffer-name))
   (let ((org-buffers-p = (equal (buffer-name) org-buffers-buffer-name))
=  (by (or (org-buffers-state-get :by) "major-mode"))
=  (atom (org-buffers-state-get :atom)) target)
=      (when org-buffers-p
(if (and = (org-before-first-heading-p) (not (org-on-heading-p)))
=    (outline-next-heading))
(setq = target
=      (condition-case nil = (org-make-org-heading-search-string) (error nil))))
=      (with-current-buffer (get-buffer-create = org-buffers-buffer-name)
(setq buffer-read-only = nil)
= (erase-buffer)
(org-mode)
= (dolist
=    (buffer
    (sort = (remove-if 'org-buffers-exclude-p
=      (mapcar 'buffer-name (buffer-list frame))) = 'string<))
=  (org-insert-heading t)
=  (insert
=   (org-make-link-string (concat "buffer:" = buffer) buffer) "\n")
 (dolist (pair = (org-buffers-get-buffer-props buffer))
=    (org-set-property (car pair) (cdr pair))))
= (org-buffers-set-state '((:atom . heading)))
= (goto-char (point-min))
(unless (equal by "NONE") = (org-buffers-group-by by))
(if target (condition-case nil = (org-link-search target) (error nil)))
(beginning-of-line)
(if = (equal by "NONE")
=    (org-overview)
 (case atom
=    ('heading (progn (org-overview) = (org-content)))
   ('line (progn = (show-all) (org-buffers-toggle-headings)))))
= (save-excursion
=  (mark-whole-buffer)
 (indent-region (point-min) = (point-max)))
= (org-buffers-mode)
(setq buffer-read-only = t)
= (current-buffer))))))

(defun org-buffers-list:refresh = (&optional arg)
 "Refresh org-buffers listing."
=  (interactive "P")
 (if arg (org-buffers-reset-state))
=  (org-buffers-list 'refresh))

(defun org-buffers-list:by = (&optional prop)
 "Group buffers according to value of = property PROP."
 (interactive)
 (let = ((buffer-read-only nil)
(headings-p (org-buffers-state-eq = :atom 'heading)))
   (unless (org-buffers-state-get = :properties)
=      (org-buffers-toggle-properties))
=    (org-buffers-set-state
=     `((:by .
   ,(or = prop
= = (org-completing-read
 "Property to group by: = "
= =  (cons "NONE" (mapcar 'car = org-buffers-buffer-properties)))))))
=    (org-buffers-list 'refresh)
=    (unless headings-p = (org-buffers-toggle-headings))))

(defun = org-buffers-toggle-properties ()
 "Toggle entry properties in = org-buffers listing buffer.
Removing properties may provide a less = cluttered appearance for
browsing. However, in-buffer properties will = be restored during
certain operations, such as = `org-buffers-list:by'."
 (interactive)
 (if = (org-buffers-state-get :properties)
=      (progn = (org-buffers-delete-properties)
=     (show-all)
=     (org-buffers-set-state '((:properties . = nil))))
   (org-buffers-set-state
=     '((:atom . heading) (:properties . t)))
=    (org-buffers-list 'refresh)))

(defun = org-buffers-toggle-headings ()
 "Toggle viewing of buffers as = org headings.
Headings will be automatically restored during = certain
operations, such as setting deletion tags."
=  (interactive)
 (let ((buffer-read-only nil)
= (headings-p (org-buffers-state-eq :atom 'heading))
(flat-p = (org-buffers-state-eq :by "NONE")))
   (if (and = headings-p (org-buffers-state-get :properties))
= (org-buffers-toggle-properties))
=    (save-excursion
=      (goto-char (point-min))
=      (if (and (or headings-p (not = flat-p))
=       (not = (outline-on-heading-p)))
=  (outline-next-heading))
     (if = flat-p
=  (progn
   (push-mark = (point) 'nomsg 'activate)
=    (end-of-buffer)
=    (org-ctrl-c-star)
=    (pop-mark))
(while (not (eobp))
=  (push-mark
  (save-excursion = (forward-line 1) (point)) 'nomsg 'activate)
=  (org-forward-same-level 1)
 (org-ctrl-c-star)
=  (pop-mark)))
=      (mark-whole-buffer)
=      (indent-region (point-min) = (point-max)))
   (org-buffers-set-state
=     `((:atom . ,(if headings-p 'line = 'heading))))))

(defun org-buffers-delete-properties ()
=  (let ((buffer-read-only nil))
=    (save-excursion
=      (goto-char (point-min))
=      (org-buffers-delete-regions
=       (nreverse
= (org-buffers-map-entries = 'org-buffers-get-property-block))))))

(defun = org-buffers-get-property-block ()
 "Return the (beg . end) = range of the property drawer.
Unlike the org version the limits = include the keywords delimiting
the drawer."
 (let ((beg = (point))
= (end (progn (outline-next-heading) (point))))
=    (goto-char beg)
   (if = (re-search-forward org-property-drawer-re end t)
(cons = (match-beginning 1) (match-end 0)))))

(defun org-buffers-group-by = (property)
 "Group top level headings according to the value of = PROPERTY."
 (let ((atom (org-buffers-state-get :atom)))
=    (save-excursion
=      (goto-char (point-min))
=      (mapc (lambda (subtree) ;; Create subtree = for each value of `property'
=      (org-insert-heading t)
=      (if (> (org-buffers-outline-level) = 1)
= =  (org-promote))
=      (insert (car subtree) "\n")
=      (org-insert-subheading t)
=      (mapc 'org-buffers-insert-parsed-entry = (cdr subtree)))
=    (prog1
(mapcar (lambda (val) ;; Form = list of parsed entries for each unique value of `property'
=  (cons val (org-buffers-parse-selected-entries property = val)))
= = = (sort
= = = (delete-dups (org-buffers-map-entries (lambda () (org-entry-get = nil property nil))))
'string<))
=      (erase-buffer))))))

(defun = org-buffers-exclude-p (buffer)
 "Return non-nil if BUFFER = should not be listed."
 (or (member (with-current-buffer buffer = major-mode)
=      org-buffers-excluded-modes)
=      (member buffer = org-buffers-excluded-buffers)
     (string=3D= (substring buffer 0 1) " ")))

(defun org-buffers-reset-state = ()
 (org-buffers-set-state
  '((:by . = "major-mode") (:atom . heading) (:properties . nil))))

(defun = org-buffers-columns-view ()
 "View buffers in Org-mode columns = view.
This is currently experimental. RET can be used to follow = links
in the first column, but certain other org-buffers keys = conflict
with column-view or otherwise do not work correctly."
=  (interactive)
 (let ((by (org-buffers-state-get = :by))
= (buffer-read-only nil))
   (unless (equal by = "NONE") (org-buffers-list:by "NONE"))
   (unless = (org-buffers-state-get :properties)
=      (org-buffers-toggle-properties))
=    (unless (equal by "NONE")
=      (goto-char (point-min))
=      (org-sort-entries-or-items nil ?r nil nil = by)
     (org-overview))
=    (mark-whole-buffer)
=    (org-columns)))

;;; Parsing and inserting = entries
(defun org-buffers-parse-selected-entries (prop val)
=  "Parse all entries with property PROP value VAL."
 (delq = nil
= (org-buffers-map-entries
(lambda () (when (equal = (org-entry-get nil prop) val)
=      (cons (org-get-heading) = (org-get-entry)))))))

(defun org-buffers-insert-parsed-entry = (entry)
 "Insert a parsed entry"
 (unless = (org-at-heading-p) (org-insert-heading))
 (insert (car entry) = "\n")
 (if (org-buffers-state-get :properties)
=      (insert (cdr entry))))

(defun = org-buffers-get-buffer-props (buffer)
 "Create alist of = properties of BUFFER, as strings."
 (with-current-buffer = buffer
   (mapcar
=     (lambda (pair) (cons (car pair) (eval (cdr = pair))))
=     org-buffers-buffer-properties)))

;;; = Follow-link behaviour

(defun org-buffers-follow-link ()
=  "Follow link to buffer on this line.
The buffer-switching = behaviour of this function is determined by
the variable = `org-buffers-follow-link-method'. See = also
`org-buffers-switch-to-buffer' = and
`org-buffers-switch-to-buffer-other-window', whose behaviour = is
hard-wired."
 (interactive)
=  (org-buffers-switch-to-buffer-generic = org-buffers-follow-link-method))

(defun = org-buffers-switch-to-buffer ()
"Switch to this entry's buffer in = current window."
 (interactive)
=  (org-buffers-switch-to-buffer-generic = 'current-window))

(defun = org-buffers-switch-to-buffer-other-window ()
 "Switch to this = entry's buffer in other window."
 (interactive)
=  (org-buffers-switch-to-buffer-generic = 'other-window))

(defun org-buffers-switch-to-buffer-generic = (method)
 (save-excursion
   (let ((atom = (org-buffers-state-get :atom)) buffer)
=      (cond
=       ((eq atom 'heading) = (org-back-to-heading))
      (t = (beginning-of-line)))
     (setq buffer = (org-buffers-get-buffer-name))
     (if = (get-buffer buffer)
 (case method
=    ('org-open-at-point (org-open-at-point))
=    ('current-window (switch-to-buffer buffer))
=    ('other-window (switch-to-buffer-other-window = buffer)))
= (error "No such buffer: %s" buffer)))))

(defun = org-buffers-get-buffer-name ()
 "Get buffer-name for current = entry."
 (let ((headings-p (org-buffers-state-eq :atom = 'heading)))
   (or (and headings-p (org-entry-get nil = "buffer-name"))
(and (save-excursion
=       (if headings-p = (org-back-to-heading))
=       (re-search-forward = "\\[\\[buffer:\\([^\]]*\\)" (point-at-eol) t))
=     (org-link-unescape (match-string = 1))))))

;;; Setting tags and executing operations

(defun = org-buffers-tag-for-deletion ()
 "Mark buffer for = deletion.
If a region is selected, all buffers in the region are = marked for
deletion. Buffers marked for deletion can be deleted = using
`org-buffers-execute-pending-operations'."
=  (interactive)
 (org-buffers-set-tags = '("delete")))

(defun org-buffers-remove-tags ()
 "Remove = deletion marks from buffers.
If a region is selected, marks are = removed from all buffers in
the region."
 (interactive)
=  (org-buffers-set-tags nil))

(defun org-buffers-set-tags = (data)
 "Set tags to DATA at all non top-level headings in = region.
DATA should be a list of strings. If DATA is nil, remove all = tags
at such headings."
 (let* ((buffer-read-only = nil)
= (region-p (org-region-active-p))
(beg (if region-p = (region-beginning) (point)))
(end (if region-p (region-end) = (point)))
= (headings-p (org-buffers-state-eq :atom 'heading))beg-line = end-line)
   (save-excursion
=      (setq beg-line (progn (goto-char beg) = (org-current-line))
   end-line = (progn (goto-char end) (org-current-line)))
=      (if headings-p
=  (setq
=   end (if (and region-p (not (eq end-line beg-line)) = (not (eobp)))
= =   (progn (goto-char end) (org-back-to-heading) = (point))
= = (progn (outline-end-of-heading) (point)))
=   beg (progn (goto-char beg) (point-at-bol)))
= (org-buffers-toggle-headings) ;; doesn't alter line = numbers
= (setq beg (progn (org-goto-line beg-line) = (point-at-bol))
=      end (if (eq end-line beg-line) = (point-at-eol)
   (progn = (org-goto-line end-line) (point-at-bol)))))
=      (narrow-to-region beg end)
=      (goto-char (point-min))
=      (org-buffers-map-entries
=       (lambda ()
(when = (or (org-buffers-state-eq :by "NONE")
  (> = (org-outline-level) 1))
=   (org-set-tags-to
   (if data = (delete-duplicates (append data (org-get-tags)) :test = 'string-equal))))))
     (widen)
=      (org-content))
=    (unless region-p
=      (outline-next-heading)
=      (unless (or (> (org-outline-level) 1) = (org-buffers-state-eq :by "NONE"))
(outline-next-heading)))
=        (unless headings-p = (org-buffers-toggle-headings))))

(defun = org-buffers-execute-pending-operations ()
 "Execute all pending = operations.
Currently the only type of operation supported = is
deletion. Buffers are tagged for deletion = using
`org-buffers-tag-for-deletion'. Remove such tags from = buffers
using `org-buffers-remove-tags'."
 (interactive)
=  (let ((buffer-read-only nil)
(headings-p (org-buffers-state-eq = :atom 'heading)) buffer)
   (unless headings-p = (org-buffers-toggle-headings))
=    (org-buffers-delete-regions
=     (nreverse
=      (org-buffers-map-entries
=       (lambda ()
(if = (setq buffer (org-buffers-get-buffer-name))
=     (if (not (kill-buffer buffer))
(error = "Failed to kill buffer %s" buffer)
=       (if (and = (org-first-sibling-p)
(not (save-excursion = (org-goto-sibling))))
=   (org-up-heading-safe)) ;; Only child so delete parent = also
=       (cons (point) (1+ = (org-end-of-subtree))))))
=       "+delete")))
=    (unless headings-p = (org-buffers-toggle-headings))))

;;; Utilities

(defun = org-buffers-map-entries (func &optional match)
=  (org-scan-tags
  func (if match (cdr = (org-make-tags-matcher match)) t)))

(defun org-buffers-set-state = (state)
 "Add STATE to global state list.
New settings have = precedence over existing ones."
 (mapc
  (lambda = (pair) (unless (assoc (car pair) state)
   (add-to-list = 'state pair)))
  org-buffers-state)
 (setq = org-buffers-state state))

(defmacro org-buffers-delete-regions = (regions)
 "Delete regions in list.
REGIONS is a list of = (beg . end) cons cells specifying buffer
regions."
 `(mapc = (lambda (pair) (if pair (delete-region (car pair) (cdr pair))))
= ,regions))

(defmacro org-buffers-state-get (key)
 `(cdr = (assoc ,key org-buffers-state)))

(defmacro org-buffers-state-eq = (key val)
 `(equal (org-buffers-state-get ,key) = ,val))

(defmacro org-buffers-outline-level ()
=  '(save-excursion (beginning-of-line) = (org-outline-level)))

;;; Links to = buffers

(org-add-link-type "buffer" 'display-buffer)
(add-hook = 'org-store-link-functions 'org-buffers-store-link)

(defun = org-buffers-store-link (&optional force)
 "Store a link to = an Emacs buffer.
Returns nil by default, to avoid hijacking other = link types."
 (if force
     (let* = ((target (buffer-name))
    (desc = target) link)
= (org-store-link-props :type "buffer")
(setq = link (org-make-link "buffer:" target))
(org-add-link-props :link link = :description desc)
link)))

(provide = 'org-buffers)
;;; org-buffers.el ends = here
_______________________________________________
Emacs-orgmode = mailing list
Please use `Reply All' to send replies to the = list.
Emacs-orgmode@gnu.org
http://lists.gnu.org/mailman/listinfo/em= acs-orgmode

= --Apple-Mail-6-961327285-- --===============1622594151== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Emacs-orgmode mailing list Please use `Reply All' to send replies to the list. Emacs-orgmode@gnu.org http://lists.gnu.org/mailman/listinfo/emacs-orgmode --===============1622594151==-- From mboxrd@z Thu Jan 1 00:00:00 1970 From: Eric S Fraga Subject: Re: Using Org for browsing and managing buffers Date: Thu, 15 Apr 2010 13:18:51 +0100 Message-ID: <87tyrcnc2c.wl%ucecesf@ucl.ac.uk> References: <87aatda0gv.fsf@stats.ox.ac.uk> <87d3y1pyuz.wl%ucecesf@ucl.ac.uk> <87mxx5cpo0.fsf@stats.ox.ac.uk> Reply-To: Eric S Fraga Mime-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset=US-ASCII Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O2O2C-0007hx-Bx for emacs-orgmode@gnu.org; Thu, 15 Apr 2010 08:19:04 -0400 Received: from [140.186.70.92] (port=57010 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O2O2A-0007hp-F4 for emacs-orgmode@gnu.org; Thu, 15 Apr 2010 08:19:03 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O2O25-0007aL-7H for emacs-orgmode@gnu.org; Thu, 15 Apr 2010 08:19:02 -0400 Received: from vscane-c.ucl.ac.uk ([144.82.108.43]:34682) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O2O25-0007a7-17 for emacs-orgmode@gnu.org; Thu, 15 Apr 2010 08:18:57 -0400 In-Reply-To: <87mxx5cpo0.fsf@stats.ox.ac.uk> List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: Dan Davison Cc: emacs org-mode mailing list On Thu, 15 Apr 2010 00:20:31 -0400, Dan Davison wrote: [...] > This does also mean that various inappropriate speed commands become > exposed (but then pressing random keys is a strategy that should be > confined to gnus). ;-) > I've made them narrower by default, and introduced a customizable > variable org-buffers-columns-format. Excellent. > Noted. On the other hand o in Org speed commands is bound to > org-open-at-point. I've got rid of my binding and am allowing it to fall > through to the speed command default but I'd welcome any further > suggestions. Note that the variable org-buffers-follow-link-method can > be used so specify the behaviour of RET on a line with a buffer link. Some more comments: - I like the fact I can customise RET or, more to the point, that it be consistent with the rest of org-mode. I personally would set org-buffers-follow-link-method to 'current-window but then it would be nice to have SPC, say, open the buffer in another window, to behave consistently with org-agenda? - I would prefer some consistency or symmetry in the creation and burying of the buffer: given that (by default) org-buffers-list brings up a new window in the current frame, quitting that buffer should also delete the window; otherwise, I would like it to not split the frame. Does that make sense? - what's the point of orb-buffers-toggle-heading? I ask because I don't understand what functionality it adds and the default binding (h) conflicts with my speed keys (I use vi-like bindings for speed motion keys). - In column view mode (which I also have not figured out why it would be used...), the heading uses a different font size than the normal entries so the headings don't line up at all. This may be my fault, however. - if I bring up the buffers list a second time, having created a new buffer in the meantime, the new buffer does not appear until I hit 'g'. I think any invocation of org-buffers-list should do an automatic update of the list. - Lastly, it would be nice to either avoid the single blank line at the start of the buffer or have point be at the first heading. Having point at the first (empty) line seems to cause some problems with speed motion keys sometimes... it also wastes a line! Actually, I think it might be useful to have point be placed at the heading that corresponds to the buffer currently being visited when the org-buffers-list command is invoked. A thought. In any case, it's almost ready for me to replace my current C-xC-b binding... :) > I haven't used bs-show. It might be interesting to try to get some bs-show has a nice feature which allows different classes of buffers to be shown and to cycle through the different views easily. From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dan Davison Subject: Re: Using Org for browsing and managing buffers Date: Thu, 15 Apr 2010 17:21:41 -0400 Message-ID: <877ho8tnru.fsf@stats.ox.ac.uk> References: <87aatda0gv.fsf@stats.ox.ac.uk> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O2WVm-0005gp-Bz for emacs-orgmode@gnu.org; Thu, 15 Apr 2010 17:22:10 -0400 Received: from [140.186.70.92] (port=56506 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O2WVj-0005gh-O3 for emacs-orgmode@gnu.org; Thu, 15 Apr 2010 17:22:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O2WVW-0006do-Uz for emacs-orgmode@gnu.org; Thu, 15 Apr 2010 17:22:07 -0400 Received: from markov.stats.ox.ac.uk ([163.1.210.1]:33635) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O2WVW-0006dY-Gh for emacs-orgmode@gnu.org; Thu, 15 Apr 2010 17:21:54 -0400 In-Reply-To: (Livin Stephen Sharma's message of "Thu, 15 Apr 2010 15:41:43 +0530") List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: Livin Stephen Sharma Cc: emacs-org-mode-help gnu Livin Stephen Sharma writes: > Am I the only one encountering: > > org-buffers-list: Invalid function: org-buffers-state-get I haven't seen that error, but I may have been doing something incorrect (with macros). I've got rid of them now; let me know if you still get the error. Code file: http://github.com/dandavison/org-buffers/raw/master/org-buffers.el Git repo: http://github.com/dandavison/org-buffers Thanks, Dan > > > > I do see many people are using this successfully > :) > > Livin Stephen > > > > On Apr 09, 2010, at 06:47:20 , Dan Davison wrote: > > > I've been working on an Org tool to browse Emacs buffers. Emacs has the > function list-buffers (C-x C-b), where you can view a list of buffers, > delete buffers, etc. This is intended to be a replacement for > list-buffers, implemented in Org-mode. > > The code is attached, and there's a git repo at > http://github.com/dandavison/org-buffers > > After putting the code in your load-path and doing > (require 'org-buffers), use the function `org-buffers-list' to create > the listing buffer. This is a read-only Org-mode buffer populated with > links to open buffers. Information is stored for each buffer using > properties. By default, the buffers are grouped by major mode. Here's a > screenshot. > > http://www.princeton.edu/~ddavison/org-buffers/by-major-mode.png > > The buffer has some special key-bindings: > > +--------------------------------------------------------------+ > | ? | Show all keybindings | > |-----+--------------------------------------------------------| > | g | Update buffer (prefix arg does hard reset) | > |-----+--------------------------------------------------------| > | b | Select a different property to group by | > |-----+--------------------------------------------------------| > | RET | follow link to buffer on this line | > |-----+--------------------------------------------------------| > | d | Mark buffer for deletion | > |-----+--------------------------------------------------------| > | u | Remove mark | > |-----+--------------------------------------------------------| > | x | Delete marked buffers | > |-----+--------------------------------------------------------| > | o | Like RET (see variable org-buffers-follow-link-method) | > |-----+--------------------------------------------------------| > | . | Like RET but switch to buffer in same window | > |-----+--------------------------------------------------------| > | h | toggle between headings and plain entries for buffers | > |-----+--------------------------------------------------------| > | p | toggle in-buffer properties on/off | > |-----+--------------------------------------------------------| > | c | Switch to column-view | > +--------------------------------------------------------------+ > > If there's an active region, d and u operate on all buffers in the > region. > > Some variables that can be configured: > - org-buffers-buffer-properties > - org-buffers-excluded-modes > - org-buffers-excluded-buffers > - org-buffers-follow-link-method > - org-buffers-mode-hook > - org-buffers-buffer-name > > Some possible extensions: > - Browse recent files using recentf > - Allow several buffers to be marked for side-by-side display > - Maintain folding configuration across buffer updates > - Make faster > > As always, any feedback, suggestions and patches will be very welcome! > > Dan > > p.s. The column-view mode works for following links, but does need > further attention. > > ;;; org-buffers.el --- An Org-mode tool for buffer management > > ;; Copyright (C) 2010 Dan Davison > > ;; Author: Dan Davison > ;; Keywords: outlines, hypermedia, calendar, wp > ;; Homepage: http://orgmode.org > > ;;; License: > > ;; This program 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 3, or (at your option) > ;; any later version. > ;; > ;; This program 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 GNU Emacs; see the file COPYING. If not, write to the > ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, > ;; Boston, MA 02110-1301, USA. > > ;;; Commentary: > > ;;; Code: > > (require 'org) > (require 'cl) > > ;;; Variables > (defvar org-buffers-buffer-name > "*Buffers*" > "Name of buffer in which buffer list is displayed") > > (defvar org-buffers-state > '((:by . "major-mode") (:atom . heading) (:properties . nil)) > "Association list specifiying the current state of org-buffers.") > > (defvar org-buffers-follow-link-method 'org-open-at-point > "Method used to follow link with RET. Must be one of > > 'org-open-at-point :: use `org-open-at-point' to follow link. > 'current-window :: use switch-to-buffer > 'other-window :: use switch-to-buffer-other-window > > Setting this variable to 'current-window makes the behaviour more > consistent with that of `Buffer-menu-mode' and `dired-mode'") > > (defvar org-buffers-buffer-properties > '(("buffer-name" . (buffer-name)) > ("major-mode" . (let ((mode (symbol-name major-mode))) > (if (string-match "-mode$" mode) > (replace-match "" nil t mode) mode))) > ("buffer-file-name" . (buffer-file-name)) > ("default-directory" . default-directory) > ("buffer-modified-p" . (format "%s" (buffer-modified-p)))) > "Association list specifying properties to be stored for each > buffer. The car of each element is the name of the property, and > the cdr is an expression which, when evaluated in the buffer, > yields the property value.") > > (defcustom org-buffers-excluded-buffers > `("*Completions*" ,org-buffers-buffer-name) > "List of names of buffers that should not be listed by > org-buffers-list." > :group 'org-buffers) > > (defcustom org-buffers-excluded-modes nil > "List of names of major-modes (strings) that should not be listed > by org-buffers-list." > :group 'org-buffers) > > ;;; Mode > (defvar org-buffers-mode-map (make-sparse-keymap)) > > (defvar org-buffers-mode-hook nil > "Hook for functions to be called after buffer listing is > created. Note that the buffer is read-only, so if the hook > function is to modify the buffer it should use a let binding to > temporarily bind buffer-read-only to nil.") > > (define-minor-mode org-buffers-mode > "An Org-mode tool for buffer management. > \\{org-buffers-mode-map}" > nil " buffers" nil > (org-set-local 'org-tag-alist '(("delete" . ?d))) > (org-set-local'org-tags-column -50) > (org-set-local 'org-columns-default-format "%25buffer-name(Buffer) > %25major-mode(Mode) %25default-directory(Dir) %5buffer-modified-p(Modified) > ") > (add-hook 'kill-buffer-hook 'org-buffers-reset-state nil 'local)) > > (defun org-buffers-help () > (interactive) > (describe-function 'org-buffers-mode)) > > ;;; Keys > (define-key org-buffers-mode-map [(return)] 'org-buffers-follow-link) > (define-key org-buffers-mode-map "b" 'org-buffers-list:by) > (define-key org-buffers-mode-map "c" 'org-buffers-columns-view) > (define-key org-buffers-mode-map "d" 'org-buffers-tag-for-deletion) > (define-key org-buffers-mode-map "g" 'org-buffers-list:refresh) > (define-key org-buffers-mode-map "." 'org-buffers-switch-to-buffer) > (define-key org-buffers-mode-map "h" 'org-buffers-toggle-headings) > (define-key org-buffers-mode-map "o" > 'org-buffers-switch-to-buffer-other-window) > (define-key org-buffers-mode-map "p" 'org-buffers-toggle-properties) > (define-key org-buffers-mode-map "u" 'org-buffers-remove-tags) > (define-key org-buffers-mode-map "x" > 'org-buffers-execute-pending-operations) > (define-key org-buffers-mode-map "?" 'org-buffers-help) > ;;; Listing and view cycling > > (defun org-buffers-list (&optional refresh frame) > "Create an Org-mode listing of Emacs buffers. > By default, buffers are grouped by major mode. Optional > argument FRAME specifies the frame whose buffers should be > listed." > (interactive) > (pop-to-buffer > (or > (and (not refresh) (get-buffer org-buffers-buffer-name)) > (let ((org-buffers-p (equal (buffer-name) org-buffers-buffer-name)) > (by (or (org-buffers-state-get :by) "major-mode")) > (atom (org-buffers-state-get :atom)) target) > (when org-buffers-p > (if (and (org-before-first-heading-p) (not (org-on-heading-p))) > (outline-next-heading)) > (setq target > (condition-case nil (org-make-org-heading-search-string) (error > nil)))) > (with-current-buffer (get-buffer-create org-buffers-buffer-name) > (setq buffer-read-only nil) > (erase-buffer) > (org-mode) > (dolist > (buffer > (sort (remove-if 'org-buffers-exclude-p > (mapcar 'buffer-name (buffer-list frame))) 'string<)) > (org-insert-heading t) > (insert > (org-make-link-string (concat "buffer:" buffer) buffer) "\n") > (dolist (pair (org-buffers-get-buffer-props buffer)) > (org-set-property (car pair) (cdr pair)))) > (org-buffers-set-state '((:atom . heading))) > (goto-char (point-min)) > (unless (equal by "NONE") (org-buffers-group-by by)) > (if target (condition-case nil (org-link-search target) (error nil))) > (beginning-of-line) > (if (equal by "NONE") > (org-overview) > (case atom > ('heading (progn (org-overview) (org-content))) > ('line (progn (show-all) (org-buffers-toggle-headings))))) > (save-excursion > (mark-whole-buffer) > (indent-region (point-min) (point-max))) > (org-buffers-mode) > (setq buffer-read-only t) > (current-buffer)))))) > > (defun org-buffers-list:refresh (&optional arg) > "Refresh org-buffers listing." > (interactive "P") > (if arg (org-buffers-reset-state)) > (org-buffers-list 'refresh)) > > (defun org-buffers-list:by (&optional prop) > "Group buffers according to value of property PROP." > (interactive) > (let ((buffer-read-only nil) > (headings-p (org-buffers-state-eq :atom 'heading))) > (unless (org-buffers-state-get :properties) > (org-buffers-toggle-properties)) > (org-buffers-set-state > `((:by . > ,(or prop > (org-completing-read > "Property to group by: " > (cons "NONE" (mapcar 'car org-buffers-buffer-properties))))))) > (org-buffers-list 'refresh) > (unless headings-p (org-buffers-toggle-headings)))) > > (defun org-buffers-toggle-properties () > "Toggle entry properties in org-buffers listing buffer. > Removing properties may provide a less cluttered appearance for > browsing. However, in-buffer properties will be restored during > certain operations, such as `org-buffers-list:by'." > (interactive) > (if (org-buffers-state-get :properties) > (progn (org-buffers-delete-properties) > (show-all) > (org-buffers-set-state '((:properties . nil)))) > (org-buffers-set-state > '((:atom . heading) (:properties . t))) > (org-buffers-list 'refresh))) > > (defun org-buffers-toggle-headings () > "Toggle viewing of buffers as org headings. > Headings will be automatically restored during certain > operations, such as setting deletion tags." > (interactive) > (let ((buffer-read-only nil) > (headings-p (org-buffers-state-eq :atom 'heading)) > (flat-p (org-buffers-state-eq :by "NONE"))) > (if (and headings-p (org-buffers-state-get :properties)) > (org-buffers-toggle-properties)) > (save-excursion > (goto-char (point-min)) > (if (and (or headings-p (not flat-p)) > (not (outline-on-heading-p))) > (outline-next-heading)) > (if flat-p > (progn > (push-mark (point) 'nomsg 'activate) > (end-of-buffer) > (org-ctrl-c-star) > (pop-mark)) > (while (not (eobp)) > (push-mark > (save-excursion (forward-line 1) (point)) 'nomsg 'activate) > (org-forward-same-level 1) > (org-ctrl-c-star) > (pop-mark))) > (mark-whole-buffer) > (indent-region (point-min) (point-max))) > (org-buffers-set-state > `((:atom . ,(if headings-p 'line 'heading)))))) > > (defun org-buffers-delete-properties () > (let ((buffer-read-only nil)) > (save-excursion > (goto-char (point-min)) > (org-buffers-delete-regions > (nreverse > (org-buffers-map-entries 'org-buffers-get-property-block)))))) > > (defun org-buffers-get-property-block () > "Return the (beg . end) range of the property drawer. > Unlike the org version the limits include the keywords delimiting > the drawer." > (let ((beg (point)) > (end (progn (outline-next-heading) (point)))) > (goto-char beg) > (if (re-search-forward org-property-drawer-re end t) > (cons (match-beginning 1) (match-end 0))))) > > (defun org-buffers-group-by (property) > "Group top level headings according to the value of PROPERTY." > (let ((atom (org-buffers-state-get :atom))) > (save-excursion > (goto-char (point-min)) > (mapc (lambda (subtree) ;; Create subtree for each value of `property' > (org-insert-heading t) > (if (> (org-buffers-outline-level) 1) > (org-promote)) > (insert (car subtree) "\n") > (org-insert-subheading t) > (mapc 'org-buffers-insert-parsed-entry (cdr subtree))) > (prog1 > (mapcar (lambda (val) ;; Form list of parsed entries for each unique value > of `property' > (cons val (org-buffers-parse-selected-entries property val))) > (sort > (delete-dups (org-buffers-map-entries (lambda () (org-entry-get nil > property nil)))) > 'string<)) > (erase-buffer)))))) > > (defun org-buffers-exclude-p (buffer) > "Return non-nil if BUFFER should not be listed." > (or (member (with-current-buffer buffer major-mode) > org-buffers-excluded-modes) > (member buffer org-buffers-excluded-buffers) > (string= (substring buffer 0 1) " "))) > > (defun org-buffers-reset-state () > (org-buffers-set-state > '((:by . "major-mode") (:atom . heading) (:properties . nil)))) > > (defun org-buffers-columns-view () > "View buffers in Org-mode columns view. > This is currently experimental. RET can be used to follow links > in the first column, but certain other org-buffers keys conflict > with column-view or otherwise do not work correctly." > (interactive) > (let ((by (org-buffers-state-get :by)) > (buffer-read-only nil)) > (unless (equal by "NONE") (org-buffers-list:by "NONE")) > (unless (org-buffers-state-get :properties) > (org-buffers-toggle-properties)) > (unless (equal by "NONE") > (goto-char (point-min)) > (org-sort-entries-or-items nil ?r nil nil by) > (org-overview)) > (mark-whole-buffer) > (org-columns))) > > ;;; Parsing and inserting entries > (defun org-buffers-parse-selected-entries (prop val) > "Parse all entries with property PROP value VAL." > (delq nil > (org-buffers-map-entries > (lambda () (when (equal (org-entry-get nil prop) val) > (cons (org-get-heading) (org-get-entry))))))) > > (defun org-buffers-insert-parsed-entry (entry) > "Insert a parsed entry" > (unless (org-at-heading-p) (org-insert-heading)) > (insert (car entry) "\n") > (if (org-buffers-state-get :properties) > (insert (cdr entry)))) > > (defun org-buffers-get-buffer-props (buffer) > "Create alist of properties of BUFFER, as strings." > (with-current-buffer buffer > (mapcar > (lambda (pair) (cons (car pair) (eval (cdr pair)))) > org-buffers-buffer-properties))) > > ;;; Follow-link behaviour > > (defun org-buffers-follow-link () > "Follow link to buffer on this line. > The buffer-switching behaviour of this function is determined by > the variable `org-buffers-follow-link-method'. See also > `org-buffers-switch-to-buffer' and > `org-buffers-switch-to-buffer-other-window', whose behaviour is > hard-wired." > (interactive) > (org-buffers-switch-to-buffer-generic org-buffers-follow-link-method)) > > (defun org-buffers-switch-to-buffer () > "Switch to this entry's buffer in current window." > (interactive) > (org-buffers-switch-to-buffer-generic 'current-window)) > > (defun org-buffers-switch-to-buffer-other-window () > "Switch to this entry's buffer in other window." > (interactive) > (org-buffers-switch-to-buffer-generic 'other-window)) > > (defun org-buffers-switch-to-buffer-generic (method) > (save-excursion > (let ((atom (org-buffers-state-get :atom)) buffer) > (cond > ((eq atom 'heading) (org-back-to-heading)) > (t (beginning-of-line))) > (setq buffer (org-buffers-get-buffer-name)) > (if (get-buffer buffer) > (case method > ('org-open-at-point (org-open-at-point)) > ('current-window (switch-to-buffer buffer)) > ('other-window (switch-to-buffer-other-window buffer))) > (error "No such buffer: %s" buffer))))) > > (defun org-buffers-get-buffer-name () > "Get buffer-name for current entry." > (let ((headings-p (org-buffers-state-eq :atom 'heading))) > (or (and headings-p (org-entry-get nil "buffer-name")) > (and (save-excursion > (if headings-p (org-back-to-heading)) > (re-search-forward "\\[\\[buffer:\\([^\]]*\\)" (point-at-eol) t)) > (org-link-unescape (match-string 1)))))) > > ;;; Setting tags and executing operations > > (defun org-buffers-tag-for-deletion () > "Mark buffer for deletion. > If a region is selected, all buffers in the region are marked for > deletion. Buffers marked for deletion can be deleted using > `org-buffers-execute-pending-operations'." > (interactive) > (org-buffers-set-tags '("delete"))) > > (defun org-buffers-remove-tags () > "Remove deletion marks from buffers. > If a region is selected, marks are removed from all buffers in > the region." > (interactive) > (org-buffers-set-tags nil)) > > (defun org-buffers-set-tags (data) > "Set tags to DATA at all non top-level headings in region. > DATA should be a list of strings. If DATA is nil, remove all tags > at such headings." > (let* ((buffer-read-only nil) > (region-p (org-region-active-p)) > (beg (if region-p (region-beginning) (point))) > (end (if region-p (region-end) (point))) > (headings-p (org-buffers-state-eq :atom 'heading))beg-line end-line) > (save-excursion > (setq beg-line (progn (goto-char beg) (org-current-line)) > end-line (progn (goto-char end) (org-current-line))) > (if headings-p > (setq > end (if (and region-p (not (eq end-line beg-line)) (not (eobp))) > (progn (goto-char end) (org-back-to-heading) (point)) > (progn (outline-end-of-heading) (point))) > beg (progn (goto-char beg) (point-at-bol))) > (org-buffers-toggle-headings) ;; doesn't alter line numbers > (setq beg (progn (org-goto-line beg-line) (point-at-bol)) > end (if (eq end-line beg-line) (point-at-eol) > (progn (org-goto-line end-line) (point-at-bol))))) > (narrow-to-region beg end) > (goto-char (point-min)) > (org-buffers-map-entries > (lambda () > (when (or (org-buffers-state-eq :by "NONE") > (> (org-outline-level) 1)) > (org-set-tags-to > (if data (delete-duplicates (append data (org-get-tags)) :test > 'string-equal)))))) > (widen) > (org-content)) > (unless region-p > (outline-next-heading) > (unless (or (> (org-outline-level) 1) (org-buffers-state-eq :by > "NONE")) > (outline-next-heading))) > (unless headings-p (org-buffers-toggle-headings)))) > > (defun org-buffers-execute-pending-operations () > "Execute all pending operations. > Currently the only type of operation supported is > deletion. Buffers are tagged for deletion using > `org-buffers-tag-for-deletion'. Remove such tags from buffers > using `org-buffers-remove-tags'." > (interactive) > (let ((buffer-read-only nil) > (headings-p (org-buffers-state-eq :atom 'heading)) buffer) > (unless headings-p (org-buffers-toggle-headings)) > (org-buffers-delete-regions > (nreverse > (org-buffers-map-entries > (lambda () > (if (setq buffer (org-buffers-get-buffer-name)) > (if (not (kill-buffer buffer)) > (error "Failed to kill buffer %s" buffer) > (if (and (org-first-sibling-p) > (not (save-excursion (org-goto-sibling)))) > (org-up-heading-safe)) ;; Only child so delete parent also > (cons (point) (1+ (org-end-of-subtree)))))) > "+delete"))) > (unless headings-p (org-buffers-toggle-headings)))) > > ;;; Utilities > > (defun org-buffers-map-entries (func &optional match) > (org-scan-tags > func (if match (cdr (org-make-tags-matcher match)) t))) > > (defun org-buffers-set-state (state) > "Add STATE to global state list. > New settings have precedence over existing ones." > (mapc > (lambda (pair) (unless (assoc (car pair) state) > (add-to-list 'state pair))) > org-buffers-state) > (setq org-buffers-state state)) > > (defmacro org-buffers-delete-regions (regions) > "Delete regions in list. > REGIONS is a list of (beg . end) cons cells specifying buffer > regions." > `(mapc (lambda (pair) (if pair (delete-region (car pair) (cdr pair)))) > ,regions)) > > (defmacro org-buffers-state-get (key) > `(cdr (assoc ,key org-buffers-state))) > > (defmacro org-buffers-state-eq (key val) > `(equal (org-buffers-state-get ,key) ,val)) > > (defmacro org-buffers-outline-level () > '(save-excursion (beginning-of-line) (org-outline-level))) > > ;;; Links to buffers > > (org-add-link-type "buffer" 'display-buffer) > (add-hook 'org-store-link-functions 'org-buffers-store-link) > > (defun org-buffers-store-link (&optional force) > "Store a link to an Emacs buffer. > Returns nil by default, to avoid hijacking other link types." > (if force > (let* ((target (buffer-name)) > (desc target) link) > (org-store-link-props :type "buffer") > (setq link (org-make-link "buffer:" target)) > (org-add-link-props :link link :description desc) > link))) > > (provide 'org-buffers) > ;;; org-buffers.el ends here > _______________________________________________ > Emacs-orgmode mailing list > Please use `Reply All' to send replies to the list. > Emacs-orgmode@gnu.org > http://lists.gnu.org/mailman/listinfo/emacs-orgmode > > > _______________________________________________ > Emacs-orgmode mailing list > Please use `Reply All' to send replies to the list. > Emacs-orgmode@gnu.org > http://lists.gnu.org/mailman/listinfo/emacs-orgmode From mboxrd@z Thu Jan 1 00:00:00 1970 From: Livin Stephen Sharma Subject: Re: Using Org for browsing and managing buffers Date: Fri, 16 Apr 2010 12:41:08 +0530 Message-ID: References: <87aatda0gv.fsf@stats.ox.ac.uk> <877ho8tnru.fsf@stats.ox.ac.uk> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0348007293==" Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O2jax-0004UA-1U for emacs-orgmode@gnu.org; Fri, 16 Apr 2010 07:20:23 -0400 Received: from [140.186.70.92] (port=47522 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O2jar-0004Rk-TG for emacs-orgmode@gnu.org; Fri, 16 Apr 2010 07:20:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O2jah-0007sr-0C for emacs-orgmode@gnu.org; Fri, 16 Apr 2010 07:20:17 -0400 Received: from mail-pw0-f41.google.com ([209.85.160.41]:50437) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O2fi5-0004dN-Fx for emacs-orgmode@gnu.org; Fri, 16 Apr 2010 03:11:30 -0400 Received: by pwi2 with SMTP id 2so2280944pwi.0 for ; Fri, 16 Apr 2010 00:11:28 -0700 (PDT) In-Reply-To: <877ho8tnru.fsf@stats.ox.ac.uk> List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: Dan Davison Cc: emacs-org-mode-help gnu --===============0348007293== Content-Type: multipart/alternative; boundary=000e0cd5d184e888fe0484555178 --000e0cd5d184e888fe0484555178 Content-Type: text/plain; charset=ISO-8859-1 yep, now it works! Thanks About moving up/down: I was a bit surprised that 'p' was *not* a counterpart of 'n' (the latter works exactly like 'n' in Org-Agenda) Then I saw that in my setup (*no* customizations), there is some duplication in the functions mapped to 'p' and 'P': key binding --- ------- > SPC org-buffers-display-buffer . org-buffers-switch-to-buffer ? org-buffers-help B org-buffers-list:by H org-buffers-toggle-headings P org-buffers-toggle-properties T org-buffers-columns-view b org-buffers-list:by c org-buffers-columns-view d org-buffers-tag-for-deletion g org-buffers-list:refresh h org-buffers-toggle-headings o org-buffers-switch-to-buffer-other-window p org-buffers-toggle-properties q bury-buffer u org-buffers-remove-tags x org-buffers-execute-pending-operations org-buffers-follow-link On 16 April 2010 02:51, Dan Davison wrote: > Livin Stephen Sharma writes: > > > Am I the only one encountering: > > > > org-buffers-list: Invalid function: org-buffers-state-get > > I haven't seen that error, but I may have been doing something incorrect > (with macros). I've got rid of them now; let me know if you still get > the error. > > Code file: > http://github.com/dandavison/org-buffers/raw/master/org-buffers.el > Git repo: http://github.com/dandavison/org-buffers > > Thanks, > > Dan > > > > > > > > > > I do see many people are using this successfully > > :) > > > > Livin Stephen > > > > > > > > On Apr 09, 2010, at 06:47:20 , Dan Davison wrote: > > > > > > I've been working on an Org tool to browse Emacs buffers. Emacs has > the > > function list-buffers (C-x C-b), where you can view a list of > buffers, > > delete buffers, etc. This is intended to be a replacement for > > list-buffers, implemented in Org-mode. > > > > The code is attached, and there's a git repo at > > http://github.com/dandavison/org-buffers > > > > After putting the code in your load-path and doing > > (require 'org-buffers), use the function `org-buffers-list' to create > > the listing buffer. This is a read-only Org-mode buffer populated > with > > links to open buffers. Information is stored for each buffer using > > properties. By default, the buffers are grouped by major mode. Here's > a > > screenshot. > > > > http://www.princeton.edu/~ddavison/org-buffers/by-major-mode.png > > > > The buffer has some special key-bindings: > > > > +--------------------------------------------------------------+ > > | ? | Show all keybindings | > > |-----+--------------------------------------------------------| > > | g | Update buffer (prefix arg does hard reset) | > > |-----+--------------------------------------------------------| > > | b | Select a different property to group by | > > |-----+--------------------------------------------------------| > > | RET | follow link to buffer on this line | > > |-----+--------------------------------------------------------| > > | d | Mark buffer for deletion | > > |-----+--------------------------------------------------------| > > | u | Remove mark | > > |-----+--------------------------------------------------------| > > | x | Delete marked buffers | > > |-----+--------------------------------------------------------| > > | o | Like RET (see variable org-buffers-follow-link-method) | > > |-----+--------------------------------------------------------| > > | . | Like RET but switch to buffer in same window | > > |-----+--------------------------------------------------------| > > | h | toggle between headings and plain entries for buffers | > > |-----+--------------------------------------------------------| > > | p | toggle in-buffer properties on/off | > > |-----+--------------------------------------------------------| > > | c | Switch to column-view | > > +--------------------------------------------------------------+ > > > > If there's an active region, d and u operate on all buffers in the > > region. > > > > Some variables that can be configured: > > - org-buffers-buffer-properties > > - org-buffers-excluded-modes > > - org-buffers-excluded-buffers > > - org-buffers-follow-link-method > > - org-buffers-mode-hook > > - org-buffers-buffer-name > > > > Some possible extensions: > > - Browse recent files using recentf > > - Allow several buffers to be marked for side-by-side display > > - Maintain folding configuration across buffer updates > > - Make faster > > > > As always, any feedback, suggestions and patches will be very > welcome! > > > > Dan > > > > p.s. The column-view mode works for following links, but does need > > further attention. > > > > ;;; org-buffers.el --- An Org-mode tool for buffer management > > > > ;; Copyright (C) 2010 Dan Davison > > > > ;; Author: Dan Davison > > ;; Keywords: outlines, hypermedia, calendar, wp > > ;; Homepage: http://orgmode.org > > > > ;;; License: > > > > ;; This program 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 3, or (at your > option) > > ;; any later version. > > ;; > > ;; This program 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 GNU Emacs; see the file COPYING. If not, write to the > > ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, > > ;; Boston, MA 02110-1301, USA. > > > > ;;; Commentary: > > > > ;;; Code: > > > > (require 'org) > > (require 'cl) > > > > ;;; Variables > > (defvar org-buffers-buffer-name > > "*Buffers*" > > "Name of buffer in which buffer list is displayed") > > > > (defvar org-buffers-state > > '((:by . "major-mode") (:atom . heading) (:properties . nil)) > > "Association list specifiying the current state of org-buffers.") > > > > (defvar org-buffers-follow-link-method 'org-open-at-point > > "Method used to follow link with RET. Must be one of > > > > 'org-open-at-point :: use `org-open-at-point' to follow link. > > 'current-window :: use switch-to-buffer > > 'other-window :: use switch-to-buffer-other-window > > > > Setting this variable to 'current-window makes the behaviour more > > consistent with that of `Buffer-menu-mode' and `dired-mode'") > > > > (defvar org-buffers-buffer-properties > > '(("buffer-name" . (buffer-name)) > > ("major-mode" . (let ((mode (symbol-name major-mode))) > > (if (string-match "-mode$" mode) > > (replace-match "" nil t mode) mode))) > > ("buffer-file-name" . (buffer-file-name)) > > ("default-directory" . default-directory) > > ("buffer-modified-p" . (format "%s" (buffer-modified-p)))) > > "Association list specifying properties to be stored for each > > buffer. The car of each element is the name of the property, and > > the cdr is an expression which, when evaluated in the buffer, > > yields the property value.") > > > > (defcustom org-buffers-excluded-buffers > > `("*Completions*" ,org-buffers-buffer-name) > > "List of names of buffers that should not be listed by > > org-buffers-list." > > :group 'org-buffers) > > > > (defcustom org-buffers-excluded-modes nil > > "List of names of major-modes (strings) that should not be listed > > by org-buffers-list." > > :group 'org-buffers) > > > > ;;; Mode > > (defvar org-buffers-mode-map (make-sparse-keymap)) > > > > (defvar org-buffers-mode-hook nil > > "Hook for functions to be called after buffer listing is > > created. Note that the buffer is read-only, so if the hook > > function is to modify the buffer it should use a let binding to > > temporarily bind buffer-read-only to nil.") > > > > (define-minor-mode org-buffers-mode > > "An Org-mode tool for buffer management. > > \\{org-buffers-mode-map}" > > nil " buffers" nil > > (org-set-local 'org-tag-alist '(("delete" . ?d))) > > (org-set-local'org-tags-column -50) > > (org-set-local 'org-columns-default-format "%25buffer-name(Buffer) > > %25major-mode(Mode) %25default-directory(Dir) > %5buffer-modified-p(Modified) > > ") > > (add-hook 'kill-buffer-hook 'org-buffers-reset-state nil 'local)) > > > > (defun org-buffers-help () > > (interactive) > > (describe-function 'org-buffers-mode)) > > > > ;;; Keys > > (define-key org-buffers-mode-map [(return)] 'org-buffers-follow-link) > > (define-key org-buffers-mode-map "b" 'org-buffers-list:by) > > (define-key org-buffers-mode-map "c" 'org-buffers-columns-view) > > (define-key org-buffers-mode-map "d" 'org-buffers-tag-for-deletion) > > (define-key org-buffers-mode-map "g" 'org-buffers-list:refresh) > > (define-key org-buffers-mode-map "." 'org-buffers-switch-to-buffer) > > (define-key org-buffers-mode-map "h" 'org-buffers-toggle-headings) > > (define-key org-buffers-mode-map "o" > > 'org-buffers-switch-to-buffer-other-window) > > (define-key org-buffers-mode-map "p" 'org-buffers-toggle-properties) > > (define-key org-buffers-mode-map "u" 'org-buffers-remove-tags) > > (define-key org-buffers-mode-map "x" > > 'org-buffers-execute-pending-operations) > > (define-key org-buffers-mode-map "?" 'org-buffers-help) > > ;;; Listing and view cycling > > > > (defun org-buffers-list (&optional refresh frame) > > "Create an Org-mode listing of Emacs buffers. > > By default, buffers are grouped by major mode. Optional > > argument FRAME specifies the frame whose buffers should be > > listed." > > (interactive) > > (pop-to-buffer > > (or > > (and (not refresh) (get-buffer org-buffers-buffer-name)) > > (let ((org-buffers-p (equal (buffer-name) > org-buffers-buffer-name)) > > (by (or (org-buffers-state-get :by) "major-mode")) > > (atom (org-buffers-state-get :atom)) target) > > (when org-buffers-p > > (if (and (org-before-first-heading-p) (not (org-on-heading-p))) > > (outline-next-heading)) > > (setq target > > (condition-case nil (org-make-org-heading-search-string) (error > > nil)))) > > (with-current-buffer (get-buffer-create org-buffers-buffer-name) > > (setq buffer-read-only nil) > > (erase-buffer) > > (org-mode) > > (dolist > > (buffer > > (sort (remove-if 'org-buffers-exclude-p > > (mapcar 'buffer-name (buffer-list frame))) 'string<)) > > (org-insert-heading t) > > (insert > > (org-make-link-string (concat "buffer:" buffer) buffer) "\n") > > (dolist (pair (org-buffers-get-buffer-props buffer)) > > (org-set-property (car pair) (cdr pair)))) > > (org-buffers-set-state '((:atom . heading))) > > (goto-char (point-min)) > > (unless (equal by "NONE") (org-buffers-group-by by)) > > (if target (condition-case nil (org-link-search target) (error nil))) > > (beginning-of-line) > > (if (equal by "NONE") > > (org-overview) > > (case atom > > ('heading (progn (org-overview) (org-content))) > > ('line (progn (show-all) (org-buffers-toggle-headings))))) > > (save-excursion > > (mark-whole-buffer) > > (indent-region (point-min) (point-max))) > > (org-buffers-mode) > > (setq buffer-read-only t) > > (current-buffer)))))) > > > > (defun org-buffers-list:refresh (&optional arg) > > "Refresh org-buffers listing." > > (interactive "P") > > (if arg (org-buffers-reset-state)) > > (org-buffers-list 'refresh)) > > > > (defun org-buffers-list:by (&optional prop) > > "Group buffers according to value of property PROP." > > (interactive) > > (let ((buffer-read-only nil) > > (headings-p (org-buffers-state-eq :atom 'heading))) > > (unless (org-buffers-state-get :properties) > > (org-buffers-toggle-properties)) > > (org-buffers-set-state > > `((:by . > > ,(or prop > > (org-completing-read > > "Property to group by: " > > (cons "NONE" (mapcar 'car org-buffers-buffer-properties))))))) > > (org-buffers-list 'refresh) > > (unless headings-p (org-buffers-toggle-headings)))) > > > > (defun org-buffers-toggle-properties () > > "Toggle entry properties in org-buffers listing buffer. > > Removing properties may provide a less cluttered appearance for > > browsing. However, in-buffer properties will be restored during > > certain operations, such as `org-buffers-list:by'." > > (interactive) > > (if (org-buffers-state-get :properties) > > (progn (org-buffers-delete-properties) > > (show-all) > > (org-buffers-set-state '((:properties . nil)))) > > (org-buffers-set-state > > '((:atom . heading) (:properties . t))) > > (org-buffers-list 'refresh))) > > > > (defun org-buffers-toggle-headings () > > "Toggle viewing of buffers as org headings. > > Headings will be automatically restored during certain > > operations, such as setting deletion tags." > > (interactive) > > (let ((buffer-read-only nil) > > (headings-p (org-buffers-state-eq :atom 'heading)) > > (flat-p (org-buffers-state-eq :by "NONE"))) > > (if (and headings-p (org-buffers-state-get :properties)) > > (org-buffers-toggle-properties)) > > (save-excursion > > (goto-char (point-min)) > > (if (and (or headings-p (not flat-p)) > > (not (outline-on-heading-p))) > > (outline-next-heading)) > > (if flat-p > > (progn > > (push-mark (point) 'nomsg 'activate) > > (end-of-buffer) > > (org-ctrl-c-star) > > (pop-mark)) > > (while (not (eobp)) > > (push-mark > > (save-excursion (forward-line 1) (point)) 'nomsg 'activate) > > (org-forward-same-level 1) > > (org-ctrl-c-star) > > (pop-mark))) > > (mark-whole-buffer) > > (indent-region (point-min) (point-max))) > > (org-buffers-set-state > > `((:atom . ,(if headings-p 'line 'heading)))))) > > > > (defun org-buffers-delete-properties () > > (let ((buffer-read-only nil)) > > (save-excursion > > (goto-char (point-min)) > > (org-buffers-delete-regions > > (nreverse > > (org-buffers-map-entries 'org-buffers-get-property-block)))))) > > > > (defun org-buffers-get-property-block () > > "Return the (beg . end) range of the property drawer. > > Unlike the org version the limits include the keywords delimiting > > the drawer." > > (let ((beg (point)) > > (end (progn (outline-next-heading) (point)))) > > (goto-char beg) > > (if (re-search-forward org-property-drawer-re end t) > > (cons (match-beginning 1) (match-end 0))))) > > > > (defun org-buffers-group-by (property) > > "Group top level headings according to the value of PROPERTY." > > (let ((atom (org-buffers-state-get :atom))) > > (save-excursion > > (goto-char (point-min)) > > (mapc (lambda (subtree) ;; Create subtree for each value of > `property' > > (org-insert-heading t) > > (if (> (org-buffers-outline-level) 1) > > (org-promote)) > > (insert (car subtree) "\n") > > (org-insert-subheading t) > > (mapc 'org-buffers-insert-parsed-entry (cdr subtree))) > > (prog1 > > (mapcar (lambda (val) ;; Form list of parsed entries for each unique > value > > of `property' > > (cons val (org-buffers-parse-selected-entries property val))) > > (sort > > (delete-dups (org-buffers-map-entries (lambda () (org-entry-get nil > > property nil)))) > > 'string<)) > > (erase-buffer)))))) > > > > (defun org-buffers-exclude-p (buffer) > > "Return non-nil if BUFFER should not be listed." > > (or (member (with-current-buffer buffer major-mode) > > org-buffers-excluded-modes) > > (member buffer org-buffers-excluded-buffers) > > (string= (substring buffer 0 1) " "))) > > > > (defun org-buffers-reset-state () > > (org-buffers-set-state > > '((:by . "major-mode") (:atom . heading) (:properties . nil)))) > > > > (defun org-buffers-columns-view () > > "View buffers in Org-mode columns view. > > This is currently experimental. RET can be used to follow links > > in the first column, but certain other org-buffers keys conflict > > with column-view or otherwise do not work correctly." > > (interactive) > > (let ((by (org-buffers-state-get :by)) > > (buffer-read-only nil)) > > (unless (equal by "NONE") (org-buffers-list:by "NONE")) > > (unless (org-buffers-state-get :properties) > > (org-buffers-toggle-properties)) > > (unless (equal by "NONE") > > (goto-char (point-min)) > > (org-sort-entries-or-items nil ?r nil nil by) > > (org-overview)) > > (mark-whole-buffer) > > (org-columns))) > > > > ;;; Parsing and inserting entries > > (defun org-buffers-parse-selected-entries (prop val) > > "Parse all entries with property PROP value VAL." > > (delq nil > > (org-buffers-map-entries > > (lambda () (when (equal (org-entry-get nil prop) val) > > (cons (org-get-heading) (org-get-entry))))))) > > > > (defun org-buffers-insert-parsed-entry (entry) > > "Insert a parsed entry" > > (unless (org-at-heading-p) (org-insert-heading)) > > (insert (car entry) "\n") > > (if (org-buffers-state-get :properties) > > (insert (cdr entry)))) > > > > (defun org-buffers-get-buffer-props (buffer) > > "Create alist of properties of BUFFER, as strings." > > (with-current-buffer buffer > > (mapcar > > (lambda (pair) (cons (car pair) (eval (cdr pair)))) > > org-buffers-buffer-properties))) > > > > ;;; Follow-link behaviour > > > > (defun org-buffers-follow-link () > > "Follow link to buffer on this line. > > The buffer-switching behaviour of this function is determined by > > the variable `org-buffers-follow-link-method'. See also > > `org-buffers-switch-to-buffer' and > > `org-buffers-switch-to-buffer-other-window', whose behaviour is > > hard-wired." > > (interactive) > > (org-buffers-switch-to-buffer-generic > org-buffers-follow-link-method)) > > > > (defun org-buffers-switch-to-buffer () > > "Switch to this entry's buffer in current window." > > (interactive) > > (org-buffers-switch-to-buffer-generic 'current-window)) > > > > (defun org-buffers-switch-to-buffer-other-window () > > "Switch to this entry's buffer in other window." > > (interactive) > > (org-buffers-switch-to-buffer-generic 'other-window)) > > > > (defun org-buffers-switch-to-buffer-generic (method) > > (save-excursion > > (let ((atom (org-buffers-state-get :atom)) buffer) > > (cond > > ((eq atom 'heading) (org-back-to-heading)) > > (t (beginning-of-line))) > > (setq buffer (org-buffers-get-buffer-name)) > > (if (get-buffer buffer) > > (case method > > ('org-open-at-point (org-open-at-point)) > > ('current-window (switch-to-buffer buffer)) > > ('other-window (switch-to-buffer-other-window buffer))) > > (error "No such buffer: %s" buffer))))) > > > > (defun org-buffers-get-buffer-name () > > "Get buffer-name for current entry." > > (let ((headings-p (org-buffers-state-eq :atom 'heading))) > > (or (and headings-p (org-entry-get nil "buffer-name")) > > (and (save-excursion > > (if headings-p (org-back-to-heading)) > > (re-search-forward "\\[\\[buffer:\\([^\]]*\\)" (point-at-eol) > t)) > > (org-link-unescape (match-string 1)))))) > > > > ;;; Setting tags and executing operations > > > > (defun org-buffers-tag-for-deletion () > > "Mark buffer for deletion. > > If a region is selected, all buffers in the region are marked for > > deletion. Buffers marked for deletion can be deleted using > > `org-buffers-execute-pending-operations'." > > (interactive) > > (org-buffers-set-tags '("delete"))) > > > > (defun org-buffers-remove-tags () > > "Remove deletion marks from buffers. > > If a region is selected, marks are removed from all buffers in > > the region." > > (interactive) > > (org-buffers-set-tags nil)) > > > > (defun org-buffers-set-tags (data) > > "Set tags to DATA at all non top-level headings in region. > > DATA should be a list of strings. If DATA is nil, remove all tags > > at such headings." > > (let* ((buffer-read-only nil) > > (region-p (org-region-active-p)) > > (beg (if region-p (region-beginning) (point))) > > (end (if region-p (region-end) (point))) > > (headings-p (org-buffers-state-eq :atom 'heading))beg-line end-line) > > (save-excursion > > (setq beg-line (progn (goto-char beg) (org-current-line)) > > end-line (progn (goto-char end) (org-current-line))) > > (if headings-p > > (setq > > end (if (and region-p (not (eq end-line beg-line)) (not (eobp))) > > (progn (goto-char end) (org-back-to-heading) (point)) > > (progn (outline-end-of-heading) (point))) > > beg (progn (goto-char beg) (point-at-bol))) > > (org-buffers-toggle-headings) ;; doesn't alter line numbers > > (setq beg (progn (org-goto-line beg-line) (point-at-bol)) > > end (if (eq end-line beg-line) (point-at-eol) > > (progn (org-goto-line end-line) (point-at-bol))))) > > (narrow-to-region beg end) > > (goto-char (point-min)) > > (org-buffers-map-entries > > (lambda () > > (when (or (org-buffers-state-eq :by "NONE") > > (> (org-outline-level) 1)) > > (org-set-tags-to > > (if data (delete-duplicates (append data (org-get-tags)) :test > > 'string-equal)))))) > > (widen) > > (org-content)) > > (unless region-p > > (outline-next-heading) > > (unless (or (> (org-outline-level) 1) (org-buffers-state-eq :by > > "NONE")) > > (outline-next-heading))) > > (unless headings-p (org-buffers-toggle-headings)))) > > > > (defun org-buffers-execute-pending-operations () > > "Execute all pending operations. > > Currently the only type of operation supported is > > deletion. Buffers are tagged for deletion using > > `org-buffers-tag-for-deletion'. Remove such tags from buffers > > using `org-buffers-remove-tags'." > > (interactive) > > (let ((buffer-read-only nil) > > (headings-p (org-buffers-state-eq :atom 'heading)) buffer) > > (unless headings-p (org-buffers-toggle-headings)) > > (org-buffers-delete-regions > > (nreverse > > (org-buffers-map-entries > > (lambda () > > (if (setq buffer (org-buffers-get-buffer-name)) > > (if (not (kill-buffer buffer)) > > (error "Failed to kill buffer %s" buffer) > > (if (and (org-first-sibling-p) > > (not (save-excursion (org-goto-sibling)))) > > (org-up-heading-safe)) ;; Only child so delete parent also > > (cons (point) (1+ (org-end-of-subtree)))))) > > "+delete"))) > > (unless headings-p (org-buffers-toggle-headings)))) > > > > ;;; Utilities > > > > (defun org-buffers-map-entries (func &optional match) > > (org-scan-tags > > func (if match (cdr (org-make-tags-matcher match)) t))) > > > > (defun org-buffers-set-state (state) > > "Add STATE to global state list. > > New settings have precedence over existing ones." > > (mapc > > (lambda (pair) (unless (assoc (car pair) state) > > (add-to-list 'state pair))) > > org-buffers-state) > > (setq org-buffers-state state)) > > > > (defmacro org-buffers-delete-regions (regions) > > "Delete regions in list. > > REGIONS is a list of (beg . end) cons cells specifying buffer > > regions." > > `(mapc (lambda (pair) (if pair (delete-region (car pair) (cdr > pair)))) > > ,regions)) > > > > (defmacro org-buffers-state-get (key) > > `(cdr (assoc ,key org-buffers-state))) > > > > (defmacro org-buffers-state-eq (key val) > > `(equal (org-buffers-state-get ,key) ,val)) > > > > (defmacro org-buffers-outline-level () > > '(save-excursion (beginning-of-line) (org-outline-level))) > > > > ;;; Links to buffers > > > > (org-add-link-type "buffer" 'display-buffer) > > (add-hook 'org-store-link-functions 'org-buffers-store-link) > > > > (defun org-buffers-store-link (&optional force) > > "Store a link to an Emacs buffer. > > Returns nil by default, to avoid hijacking other link types." > > (if force > > (let* ((target (buffer-name)) > > (desc target) link) > > (org-store-link-props :type "buffer") > > (setq link (org-make-link "buffer:" target)) > > (org-add-link-props :link link :description desc) > > link))) > > > > (provide 'org-buffers) > > ;;; org-buffers.el ends here > > _______________________________________________ > > Emacs-orgmode mailing list > > Please use `Reply All' to send replies to the list. > > Emacs-orgmode@gnu.org > > http://lists.gnu.org/mailman/listinfo/emacs-orgmode > > > > > > _______________________________________________ > > Emacs-orgmode mailing list > > Please use `Reply All' to send replies to the list. > > Emacs-orgmode@gnu.org > > http://lists.gnu.org/mailman/listinfo/emacs-orgmode > --000e0cd5d184e888fe0484555178 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable yep, now it works!
Thanks

About moving up/down= :
=A0I was a bit surprised that 'p' was not a coun= terpart of 'n' (the latter works exactly like 'n' in Org-Ag= enda)

Then I saw that in my setup (*no* customizations), there is = some duplication in the functions mapped to 'p' and 'P':



key =A0 =A0 =A0 =A0 =A0 =A0 binding
--- =A0 =A0 =A0 =A0 =A0 =A0 -------

SPC org-= buffers-display-buffer
. org-bu= ffers-switch-to-buffer
? org-bu= ffers-help
B org-bu= ffers-list:by
H org-bu= ffers-toggle-headings
P = org-= buffers-toggle-properties
T org-bu= ffers-columns-view
b org-bu= ffers-list:by
c org-bu= ffers-columns-view
d org-bu= ffers-tag-for-deletion
g org-bu= ffers-list:refresh
h org-bu= ffers-toggle-headings
o org-bu= ffers-switch-to-buffer-other-window
p = org-= buffers-toggle-properties
q bury-b= uffer
u org-bu= ffers-remove-tags
x org-bu= ffers-execute-pending-operations
<return> org-buffers-follow-link



On 16 April 2010 02:51, Dan Davison <= span dir=3D"ltr"><davison@stat= s.ox.ac.uk> wrote:
Livin Stephen Sharma <= livin.stephen@gmail.com> = writes:

> Am I the only one encountering:
>
> =A0 =A0 org-buffers-list: Invalid function: org-buffers-state-get

I haven't seen that error, but I may have been doing something in= correct
(with macros). I've got rid of them now; let me know if you still get the error.

Code file: http://github.com/dandavison/org-buffers/r= aw/master/org-buffers.el
Git repo: =A0http://github.com/dandavison/org-buffers

Thanks,

Dan


>
>
>
> I do see many people are using this successfully
> :)
>
> Livin Stephen
>
>
>
> On Apr 09, 2010, at 06:47:20 , Dan Davison wrote:
>
>
> =A0 =A0 I've been working on an Org tool to browse Emacs buffers. = Emacs has the
> =A0 =A0 function list-buffers (C-x C-b), where you can view a list of = buffers,
> =A0 =A0 delete buffers, etc. This is intended to be a replacement for<= br> > =A0 =A0 list-buffers, implemented in Org-mode.
>
> =A0 =A0 The code is attached, and there's a git repo at
> =A0 =A0 http://github.com/dandavison/org-buffers
>
> =A0 =A0 After putting the code in your load-path and doing
> =A0 =A0 (require 'org-buffers), use the function `org-buffers-list= ' to create
> =A0 =A0 the listing buffer. This is a read-only Org-mode buffer popula= ted with
> =A0 =A0 links to open buffers. Information is stored for each buffer u= sing
> =A0 =A0 properties. By default, the buffers are grouped by major mode.= Here's a
> =A0 =A0 screenshot.
>
> =A0 =A0 http://www.princeton.edu/~ddavison/org-buf= fers/by-major-mode.png
>
> =A0 =A0 The buffer has some special key-bindings:
>
> =A0 =A0 +-------------------------------------------------------------= -+
> =A0 =A0 | ? =A0 | Show all keybindings =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0= =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 |
> =A0 =A0 |-----+-------------------------------------------------------= -|
> =A0 =A0 | g =A0 | Update buffer (prefix arg does hard reset) =A0 =A0 = =A0 =A0 =A0 =A0 |
> =A0 =A0 |-----+-------------------------------------------------------= -|
> =A0 =A0 | b =A0 | Select a different property to group by =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0|
> =A0 =A0 |-----+-------------------------------------------------------= -|
> =A0 =A0 | RET | follow link to buffer on this line =A0 =A0 =A0 =A0 =A0= =A0 =A0 =A0 =A0 =A0 |
> =A0 =A0 |-----+-------------------------------------------------------= -|
> =A0 =A0 | d =A0 | Mark buffer for deletion =A0 =A0 =A0 =A0 =A0 =A0 =A0= =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 |
> =A0 =A0 |-----+-------------------------------------------------------= -|
> =A0 =A0 | u =A0 | Remove mark =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0|
> =A0 =A0 |-----+-------------------------------------------------------= -|
> =A0 =A0 | x =A0 | Delete marked buffers =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0|
> =A0 =A0 |-----+-------------------------------------------------------= -|
> =A0 =A0 | o =A0 | Like RET (see variable org-buffers-follow-link-metho= d) |
> =A0 =A0 |-----+-------------------------------------------------------= -|
> =A0 =A0 | . =A0 | Like RET but switch to buffer in same window =A0 =A0= =A0 =A0 =A0 |
> =A0 =A0 |-----+-------------------------------------------------------= -|
> =A0 =A0 | h =A0 | toggle between headings and plain entries for buffer= s =A0|
> =A0 =A0 |-----+-------------------------------------------------------= -|
> =A0 =A0 | p =A0 | toggle in-buffer properties on/off =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 |
> =A0 =A0 |-----+-------------------------------------------------------= -|
> =A0 =A0 | c =A0 | Switch to column-view =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0|
> =A0 =A0 +-------------------------------------------------------------= -+
>
> =A0 =A0 If there's an active region, d and u operate on all buffer= s in the
> =A0 =A0 region.
>
> =A0 =A0 Some variables that can be configured:
> =A0 =A0 - org-buffers-buffer-properties
> =A0 =A0 - org-buffers-excluded-modes
> =A0 =A0 - org-buffers-excluded-buffers
> =A0 =A0 - org-buffers-follow-link-method
> =A0 =A0 - org-buffers-mode-hook
> =A0 =A0 - org-buffers-buffer-name
>
> =A0 =A0 Some possible extensions:
> =A0 =A0 - Browse recent files using recentf
> =A0 =A0 - Allow several buffers to be marked for side-by-side display<= br> > =A0 =A0 - Maintain folding configuration across buffer updates
> =A0 =A0 - Make faster
>
> =A0 =A0 As always, any feedback, suggestions and patches will be very = welcome!
>
> =A0 =A0 Dan
>
> =A0 =A0 p.s. The column-view mode works for following links, but does = need
> =A0 =A0 further attention.
>
> =A0 =A0 ;;; org-buffers.el --- An Org-mode tool for buffer management<= br> >
> =A0 =A0 ;; Copyright (C) 2010 =A0Dan Davison
>
> =A0 =A0 ;; Author: Dan Davison <dandavison0 at gmail dot com> > =A0 =A0 ;; Keywords: outlines, hypermedia, calendar, wp
> =A0 =A0 ;; Homepage: = http://orgmode.org
>
> =A0 =A0 ;;; License:
>
> =A0 =A0 ;; This program is free software; you can redistribute it and/= or modify
> =A0 =A0 ;; it under the terms of the GNU General Public License as pub= lished by
> =A0 =A0 ;; the Free Software Foundation; either version 3, or (at your= option)
> =A0 =A0 ;; any later version.
> =A0 =A0 ;;
> =A0 =A0 ;; This program is distributed in the hope that it will be use= ful,
> =A0 =A0 ;; but WITHOUT ANY WARRANTY; without even the implied warranty= of
> =A0 =A0 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. =A0See= the
> =A0 =A0 ;; GNU General Public License for more details.
> =A0 =A0 ;;
> =A0 =A0 ;; You should have received a copy of the GNU General Public L= icense
> =A0 =A0 ;; along with GNU Emacs; see the file COPYING. =A0If not, writ= e to the
> =A0 =A0 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth F= loor,
> =A0 =A0 ;; Boston, MA 02110-1301, USA.
>
> =A0 =A0 ;;; Commentary:
>
> =A0 =A0 ;;; Code:
>
> =A0 =A0 (require 'org)
> =A0 =A0 (require 'cl)
>
> =A0 =A0 ;;; Variables
> =A0 =A0 (defvar org-buffers-buffer-name
> =A0 =A0 =A0"*Buffers*"
> =A0 =A0 =A0"Name of buffer in which buffer list is displayed"= ;)
>
> =A0 =A0 (defvar org-buffers-state
> =A0 =A0 =A0'((:by . "major-mode") (:atom . heading) (:pr= operties . nil))
> =A0 =A0 =A0"Association list specifiying the current state of org= -buffers.")
>
> =A0 =A0 (defvar org-buffers-follow-link-method 'org-open-at-point<= br> > =A0 =A0 =A0"Method used to follow link with RET. Must be one of >
> =A0 =A0 'org-open-at-point :: use `org-open-at-point' to follo= w link.
> =A0 =A0 'current-window =A0 =A0:: use switch-to-buffer
> =A0 =A0 'other-window =A0 =A0 =A0:: use switch-to-buffer-other-win= dow
>
> =A0 =A0 Setting this variable to 'current-window makes the behavio= ur more
> =A0 =A0 consistent with that of `Buffer-menu-mode' and `dired-mode= '")
>
> =A0 =A0 (defvar org-buffers-buffer-properties
> =A0 =A0 =A0'(("buffer-name" . (buffer-name))
> =A0 =A0 =A0 =A0("major-mode" . (let ((mode (symbol-name majo= r-mode)))
> =A0 =A0 =A0 =A0 =A0(if (string-match "-mode$" mode)
> =A0 =A0 =A0(replace-match "" nil t mode) mode)))
> =A0 =A0 =A0 =A0("buffer-file-name" . (buffer-file-name))
> =A0 =A0 =A0 =A0("default-directory" . default-directory)
> =A0 =A0 =A0 =A0("buffer-modified-p" . (format "%s"= (buffer-modified-p))))
> =A0 =A0 =A0"Association list specifying properties to be stored f= or each
> =A0 =A0 buffer. The car of each element is the name of the property, a= nd
> =A0 =A0 the cdr is an expression which, when evaluated in the buffer,<= br> > =A0 =A0 yields the property value.")
>
> =A0 =A0 (defcustom org-buffers-excluded-buffers
> =A0 =A0 =A0`("*Completions*" ,org-buffers-buffer-name)
> =A0 =A0 =A0"List of names of buffers that should not be listed by=
> =A0 =A0 =A0org-buffers-list."
> =A0 =A0 =A0:group 'org-buffers)
>
> =A0 =A0 (defcustom org-buffers-excluded-modes nil
> =A0 =A0 =A0"List of names of major-modes (strings) that should no= t be listed
> =A0 =A0 =A0by org-buffers-list."
> =A0 =A0 =A0:group 'org-buffers)
>
> =A0 =A0 ;;; Mode
> =A0 =A0 (defvar org-buffers-mode-map (make-sparse-keymap))
>
> =A0 =A0 (defvar org-buffers-mode-hook nil
> =A0 =A0 =A0"Hook for functions to be called after buffer listing = is
> =A0 =A0 =A0created. Note that the buffer is read-only, so if the hook<= br> > =A0 =A0 =A0function is to modify the buffer it should use a let bindin= g to
> =A0 =A0 =A0temporarily bind buffer-read-only to nil.")
>
> =A0 =A0 (define-minor-mode org-buffers-mode
> =A0 =A0 =A0"An Org-mode tool for buffer management.
> =A0 =A0 \\{org-buffers-mode-map}"
> =A0 =A0 =A0nil " buffers" nil
> =A0 =A0 =A0(org-set-local 'org-tag-alist '(("delete"= . ?d)))
> =A0 =A0 =A0(org-set-local'org-tags-column -50)
> =A0 =A0 =A0(org-set-local 'org-columns-default-format "%25buf= fer-name(Buffer)
> =A0 =A0 %25major-mode(Mode) %25default-directory(Dir) %5buffer-modifie= d-p(Modified)
> =A0 =A0 ")
> =A0 =A0 =A0(add-hook 'kill-buffer-hook 'org-buffers-reset-stat= e nil 'local))
>
> =A0 =A0 (defun org-buffers-help ()
> =A0 =A0 =A0(interactive)
> =A0 =A0 =A0(describe-function 'org-buffers-mode))
>
> =A0 =A0 ;;; Keys
> =A0 =A0 (define-key org-buffers-mode-map [(return)] 'org-buffers-f= ollow-link)
> =A0 =A0 (define-key org-buffers-mode-map "b" 'org-buffer= s-list:by)
> =A0 =A0 (define-key org-buffers-mode-map "c" 'org-buffer= s-columns-view)
> =A0 =A0 (define-key org-buffers-mode-map "d" 'org-buffer= s-tag-for-deletion)
> =A0 =A0 (define-key org-buffers-mode-map "g" 'org-buffer= s-list:refresh)
> =A0 =A0 (define-key org-buffers-mode-map "." 'org-buffer= s-switch-to-buffer)
> =A0 =A0 (define-key org-buffers-mode-map "h" 'org-buffer= s-toggle-headings)
> =A0 =A0 (define-key org-buffers-mode-map "o"
> =A0 =A0 'org-buffers-switch-to-buffer-other-window)
> =A0 =A0 (define-key org-buffers-mode-map "p" 'org-buffer= s-toggle-properties)
> =A0 =A0 (define-key org-buffers-mode-map "u" 'org-buffer= s-remove-tags)
> =A0 =A0 (define-key org-buffers-mode-map "x"
> =A0 =A0 'org-buffers-execute-pending-operations)
> =A0 =A0 (define-key org-buffers-mode-map "?" 'org-buffer= s-help)
> =A0 =A0 ;;; Listing and view cycling
>
> =A0 =A0 (defun org-buffers-list (&optional refresh frame)
> =A0 =A0 =A0"Create an Org-mode listing of Emacs buffers.
> =A0 =A0 By default, buffers are grouped by major mode. Optional
> =A0 =A0 argument FRAME specifies the frame whose buffers should be
> =A0 =A0 listed."
> =A0 =A0 =A0(interactive)
> =A0 =A0 =A0(pop-to-buffer
> =A0 =A0 =A0 (or
> =A0 =A0 =A0 =A0(and (not refresh) (get-buffer org-buffers-buffer-name)= )
> =A0 =A0 =A0 =A0(let ((org-buffers-p (equal (buffer-name) org-buffers-b= uffer-name))
> =A0 =A0 =A0(by (or (org-buffers-state-get :by) "major-mode")= )
> =A0 =A0 =A0(atom (org-buffers-state-get :atom)) target)
> =A0 =A0 =A0 =A0 =A0(when org-buffers-p
> =A0 =A0 (if (and (org-before-first-heading-p) (not (org-on-heading-p))= )
> =A0 =A0 =A0 =A0(outline-next-heading))
> =A0 =A0 (setq target
> =A0 =A0 =A0 =A0 =A0(condition-case nil (org-make-org-heading-search-st= ring) (error
> =A0 =A0 nil))))
> =A0 =A0 =A0 =A0 =A0(with-current-buffer (get-buffer-create org-buffers= -buffer-name)
> =A0 =A0 (setq buffer-read-only nil)
> =A0 =A0 (erase-buffer)
> =A0 =A0 (org-mode)
> =A0 =A0 (dolist
> =A0 =A0 =A0 =A0(buffer
> =A0 =A0 =A0 =A0 (sort (remove-if 'org-buffers-exclude-p
> =A0 =A0 =A0 =A0 =A0(mapcar 'buffer-name (buffer-list frame))) '= ;string<))
> =A0 =A0 =A0(org-insert-heading t)
> =A0 =A0 =A0(insert
> =A0 =A0 =A0 (org-make-link-string (concat "buffer:" buffer) = buffer) "\n")
> =A0 =A0 =A0(dolist (pair (org-buffers-get-buffer-props buffer))
> =A0 =A0 =A0 =A0(org-set-property (car pair) (cdr pair))))
> =A0 =A0 (org-buffers-set-state '((:atom . heading)))
> =A0 =A0 (goto-char (point-min))
> =A0 =A0 (unless (equal by "NONE") (org-buffers-group-by by))=
> =A0 =A0 (if target (condition-case nil (org-link-search target) (error= nil)))
> =A0 =A0 (beginning-of-line)
> =A0 =A0 (if (equal by "NONE")
> =A0 =A0 =A0 =A0(org-overview)
> =A0 =A0 =A0(case atom
> =A0 =A0 =A0 =A0('heading (progn (org-overview) (org-content)))
> =A0 =A0 =A0 =A0('line (progn (show-all) (org-buffers-toggle-headin= gs)))))
> =A0 =A0 (save-excursion
> =A0 =A0 =A0(mark-whole-buffer)
> =A0 =A0 =A0(indent-region (point-min) (point-max)))
> =A0 =A0 (org-buffers-mode)
> =A0 =A0 (setq buffer-read-only t)
> =A0 =A0 (current-buffer))))))
>
> =A0 =A0 (defun org-buffers-list:refresh (&optional arg)
> =A0 =A0 =A0"Refresh org-buffers listing."
> =A0 =A0 =A0(interactive "P")
> =A0 =A0 =A0(if arg (org-buffers-reset-state))
> =A0 =A0 =A0(org-buffers-list 'refresh))
>
> =A0 =A0 (defun org-buffers-list:by (&optional prop)
> =A0 =A0 =A0"Group buffers according to value of property PROP.&qu= ot;
> =A0 =A0 =A0(interactive)
> =A0 =A0 =A0(let ((buffer-read-only nil)
> =A0 =A0 (headings-p (org-buffers-state-eq :atom 'heading)))
> =A0 =A0 =A0 =A0(unless (org-buffers-state-get :properties)
> =A0 =A0 =A0 =A0 =A0(org-buffers-toggle-properties))
> =A0 =A0 =A0 =A0(org-buffers-set-state
> =A0 =A0 =A0 =A0 `((:by .
> =A0 =A0 =A0 =A0,(or prop
> =A0 =A0 (org-completing-read
> =A0 =A0 =A0"Property to group by: "
> =A0 =A0 =A0(cons "NONE" (mapcar 'car org-buffers-buffer-= properties)))))))
> =A0 =A0 =A0 =A0(org-buffers-list 'refresh)
> =A0 =A0 =A0 =A0(unless headings-p (org-buffers-toggle-headings))))
>
> =A0 =A0 (defun org-buffers-toggle-properties ()
> =A0 =A0 =A0"Toggle entry properties in org-buffers listing buffer= .
> =A0 =A0 Removing properties may provide a less cluttered appearance fo= r
> =A0 =A0 browsing. However, in-buffer properties will be restored durin= g
> =A0 =A0 certain operations, such as `org-buffers-list:by'." > =A0 =A0 =A0(interactive)
> =A0 =A0 =A0(if (org-buffers-state-get :properties)
> =A0 =A0 =A0 =A0 =A0(progn (org-buffers-delete-properties)
> =A0 =A0 =A0 =A0 (show-all)
> =A0 =A0 =A0 =A0 (org-buffers-set-state '((:properties . nil)))) > =A0 =A0 =A0 =A0(org-buffers-set-state
> =A0 =A0 =A0 =A0 '((:atom . heading) (:properties . t)))
> =A0 =A0 =A0 =A0(org-buffers-list 'refresh)))
>
> =A0 =A0 (defun org-buffers-toggle-headings ()
> =A0 =A0 =A0"Toggle viewing of buffers as org headings.
> =A0 =A0 Headings will be automatically restored during certain
> =A0 =A0 operations, such as setting deletion tags."
> =A0 =A0 =A0(interactive)
> =A0 =A0 =A0(let ((buffer-read-only nil)
> =A0 =A0 (headings-p (org-buffers-state-eq :atom 'heading))
> =A0 =A0 (flat-p (org-buffers-state-eq :by "NONE")))
> =A0 =A0 =A0 =A0(if (and headings-p (org-buffers-state-get :properties)= )
> =A0 =A0 (org-buffers-toggle-properties))
> =A0 =A0 =A0 =A0(save-excursion
> =A0 =A0 =A0 =A0 =A0(goto-char (point-min))
> =A0 =A0 =A0 =A0 =A0(if (and (or headings-p (not flat-p))
> =A0 =A0 =A0 =A0 =A0 (not (outline-on-heading-p)))
> =A0 =A0 =A0(outline-next-heading))
> =A0 =A0 =A0 =A0 =A0(if flat-p
> =A0 =A0 =A0(progn
> =A0 =A0 =A0 =A0(push-mark (point) 'nomsg 'activate)
> =A0 =A0 =A0 =A0(end-of-buffer)
> =A0 =A0 =A0 =A0(org-ctrl-c-star)
> =A0 =A0 =A0 =A0(pop-mark))
> =A0 =A0 (while (not (eobp))
> =A0 =A0 =A0(push-mark
> =A0 =A0 =A0 (save-excursion (forward-line 1) (point)) 'nomsg '= activate)
> =A0 =A0 =A0(org-forward-same-level 1)
> =A0 =A0 =A0(org-ctrl-c-star)
> =A0 =A0 =A0(pop-mark)))
> =A0 =A0 =A0 =A0 =A0(mark-whole-buffer)
> =A0 =A0 =A0 =A0 =A0(indent-region (point-min) (point-max)))
> =A0 =A0 =A0 =A0(org-buffers-set-state
> =A0 =A0 =A0 =A0 `((:atom . ,(if headings-p 'line 'heading)))))= )
>
> =A0 =A0 (defun org-buffers-delete-properties ()
> =A0 =A0 =A0(let ((buffer-read-only nil))
> =A0 =A0 =A0 =A0(save-excursion
> =A0 =A0 =A0 =A0 =A0(goto-char (point-min))
> =A0 =A0 =A0 =A0 =A0(org-buffers-delete-regions
> =A0 =A0 =A0 =A0 =A0 (nreverse
> =A0 =A0 (org-buffers-map-entries 'org-buffers-get-property-block))= ))))
>
> =A0 =A0 (defun org-buffers-get-property-block ()
> =A0 =A0 =A0"Return the (beg . end) range of the property drawer.<= br> > =A0 =A0 Unlike the org version the limits include the keywords delimit= ing
> =A0 =A0 the drawer."
> =A0 =A0 =A0(let ((beg (point))
> =A0 =A0 (end (progn (outline-next-heading) (point))))
> =A0 =A0 =A0 =A0(goto-char beg)
> =A0 =A0 =A0 =A0(if (re-search-forward org-property-drawer-re end t) > =A0 =A0 (cons (match-beginning 1) (match-end 0)))))
>
> =A0 =A0 (defun org-buffers-group-by (property)
> =A0 =A0 =A0"Group top level headings according to the value of PR= OPERTY."
> =A0 =A0 =A0(let ((atom (org-buffers-state-get :atom)))
> =A0 =A0 =A0 =A0(save-excursion
> =A0 =A0 =A0 =A0 =A0(goto-char (point-min))
> =A0 =A0 =A0 =A0 =A0(mapc (lambda (subtree) ;; Create subtree for each = value of `property'
> =A0 =A0 =A0 =A0 =A0(org-insert-heading t)
> =A0 =A0 =A0 =A0 =A0(if (> (org-buffers-outline-level) 1)
> =A0 =A0 =A0(org-promote))
> =A0 =A0 =A0 =A0 =A0(insert (car subtree) "\n")
> =A0 =A0 =A0 =A0 =A0(org-insert-subheading t)
> =A0 =A0 =A0 =A0 =A0(mapc 'org-buffers-insert-parsed-entry (cdr sub= tree)))
> =A0 =A0 =A0 =A0(prog1
> =A0 =A0 (mapcar (lambda (val) ;; Form list of parsed entries for each = unique value
> =A0 =A0 of `property'
> =A0 =A0 =A0(cons val (org-buffers-parse-selected-entries property val)= ))
> =A0 =A0 (sort
> =A0 =A0 (delete-dups (org-buffers-map-entries (lambda () (org-entry-ge= t nil
> =A0 =A0 property nil))))
> =A0 =A0 'string<))
> =A0 =A0 =A0 =A0 =A0(erase-buffer))))))
>
> =A0 =A0 (defun org-buffers-exclude-p (buffer)
> =A0 =A0 =A0"Return non-nil if BUFFER should not be listed."<= br> > =A0 =A0 =A0(or (member (with-current-buffer buffer major-mode)
> =A0 =A0 =A0 =A0 =A0org-buffers-excluded-modes)
> =A0 =A0 =A0 =A0 =A0(member buffer org-buffers-excluded-buffers)
> =A0 =A0 =A0 =A0 =A0(string=3D (substring buffer 0 1) " ")))<= br> >
> =A0 =A0 (defun org-buffers-reset-state ()
> =A0 =A0 =A0(org-buffers-set-state
> =A0 =A0 =A0 '((:by . "major-mode") (:atom . heading) (:p= roperties . nil))))
>
> =A0 =A0 (defun org-buffers-columns-view ()
> =A0 =A0 =A0"View buffers in Org-mode columns view.
> =A0 =A0 This is currently experimental. RET can be used to follow link= s
> =A0 =A0 in the first column, but certain other org-buffers keys confli= ct
> =A0 =A0 with column-view or otherwise do not work correctly."
> =A0 =A0 =A0(interactive)
> =A0 =A0 =A0(let ((by (org-buffers-state-get :by))
> =A0 =A0 (buffer-read-only nil))
> =A0 =A0 =A0 =A0(unless (equal by "NONE") (org-buffers-list:b= y "NONE"))
> =A0 =A0 =A0 =A0(unless (org-buffers-state-get :properties)
> =A0 =A0 =A0 =A0 =A0(org-buffers-toggle-properties))
> =A0 =A0 =A0 =A0(unless (equal by "NONE")
> =A0 =A0 =A0 =A0 =A0(goto-char (point-min))
> =A0 =A0 =A0 =A0 =A0(org-sort-entries-or-items nil ?r nil nil by)
> =A0 =A0 =A0 =A0 =A0(org-overview))
> =A0 =A0 =A0 =A0(mark-whole-buffer)
> =A0 =A0 =A0 =A0(org-columns)))
>
> =A0 =A0 ;;; Parsing and inserting entries
> =A0 =A0 (defun org-buffers-parse-selected-entries (prop val)
> =A0 =A0 =A0"Parse all entries with property PROP value VAL."=
> =A0 =A0 =A0(delq nil
> =A0 =A0 (org-buffers-map-entries
> =A0 =A0 (lambda () (when (equal (org-entry-get nil prop) val)
> =A0 =A0 =A0 =A0 =A0(cons (org-get-heading) (org-get-entry)))))))
>
> =A0 =A0 (defun org-buffers-insert-parsed-entry (entry)
> =A0 =A0 =A0"Insert a parsed entry"
> =A0 =A0 =A0(unless (org-at-heading-p) (org-insert-heading))
> =A0 =A0 =A0(insert (car entry) "\n")
> =A0 =A0 =A0(if (org-buffers-state-get :properties)
> =A0 =A0 =A0 =A0 =A0(insert (cdr entry))))
>
> =A0 =A0 (defun org-buffers-get-buffer-props (buffer)
> =A0 =A0 =A0"Create alist of properties of BUFFER, as strings.&quo= t;
> =A0 =A0 =A0(with-current-buffer buffer
> =A0 =A0 =A0 =A0(mapcar
> =A0 =A0 =A0 =A0 (lambda (pair) (cons (car pair) (eval (cdr pair)))) > =A0 =A0 =A0 =A0 org-buffers-buffer-properties)))
>
> =A0 =A0 ;;; Follow-link behaviour
>
> =A0 =A0 (defun org-buffers-follow-link ()
> =A0 =A0 =A0"Follow link to buffer on this line.
> =A0 =A0 The buffer-switching behaviour of this function is determined = by
> =A0 =A0 the variable `org-buffers-follow-link-method'. See also > =A0 =A0 `org-buffers-switch-to-buffer' and
> =A0 =A0 `org-buffers-switch-to-buffer-other-window', whose behavio= ur is
> =A0 =A0 hard-wired."
> =A0 =A0 =A0(interactive)
> =A0 =A0 =A0(org-buffers-switch-to-buffer-generic org-buffers-follow-li= nk-method))
>
> =A0 =A0 (defun org-buffers-switch-to-buffer ()
> =A0 =A0 "Switch to this entry's buffer in current window.&quo= t;
> =A0 =A0 =A0(interactive)
> =A0 =A0 =A0(org-buffers-switch-to-buffer-generic 'current-window))=
>
> =A0 =A0 (defun org-buffers-switch-to-buffer-other-window ()
> =A0 =A0 =A0"Switch to this entry's buffer in other window.&qu= ot;
> =A0 =A0 =A0(interactive)
> =A0 =A0 =A0(org-buffers-switch-to-buffer-generic 'other-window)) >
> =A0 =A0 (defun org-buffers-switch-to-buffer-generic (method)
> =A0 =A0 =A0(save-excursion
> =A0 =A0 =A0 =A0(let ((atom (org-buffers-state-get :atom)) buffer)
> =A0 =A0 =A0 =A0 =A0(cond
> =A0 =A0 =A0 =A0 =A0 ((eq atom 'heading) (org-back-to-heading))
> =A0 =A0 =A0 =A0 =A0 (t (beginning-of-line)))
> =A0 =A0 =A0 =A0 =A0(setq buffer (org-buffers-get-buffer-name))
> =A0 =A0 =A0 =A0 =A0(if (get-buffer buffer)
> =A0 =A0 =A0(case method
> =A0 =A0 =A0 =A0('org-open-at-point (org-open-at-point))
> =A0 =A0 =A0 =A0('current-window (switch-to-buffer buffer))
> =A0 =A0 =A0 =A0('other-window (switch-to-buffer-other-window buffe= r)))
> =A0 =A0 (error "No such buffer: %s" buffer)))))
>
> =A0 =A0 (defun org-buffers-get-buffer-name ()
> =A0 =A0 =A0"Get buffer-name for current entry."
> =A0 =A0 =A0(let ((headings-p (org-buffers-state-eq :atom 'heading)= ))
> =A0 =A0 =A0 =A0(or (and headings-p (org-entry-get nil "buffer-nam= e"))
> =A0 =A0 (and (save-excursion
> =A0 =A0 =A0 =A0 =A0 (if headings-p (org-back-to-heading))
> =A0 =A0 =A0 =A0 =A0 (re-search-forward "\\[\\[buffer:\\([^\]]*\\)= " (point-at-eol) t))
> =A0 =A0 =A0 =A0 (org-link-unescape (match-string 1))))))
>
> =A0 =A0 ;;; Setting tags and executing operations
>
> =A0 =A0 (defun org-buffers-tag-for-deletion ()
> =A0 =A0 =A0"Mark buffer for deletion.
> =A0 =A0 If a region is selected, all buffers in the region are marked = for
> =A0 =A0 deletion. Buffers marked for deletion can be deleted using
> =A0 =A0 `org-buffers-execute-pending-operations'."
> =A0 =A0 =A0(interactive)
> =A0 =A0 =A0(org-buffers-set-tags '("delete")))
>
> =A0 =A0 (defun org-buffers-remove-tags ()
> =A0 =A0 =A0"Remove deletion marks from buffers.
> =A0 =A0 If a region is selected, marks are removed from all buffers in=
> =A0 =A0 the region."
> =A0 =A0 =A0(interactive)
> =A0 =A0 =A0(org-buffers-set-tags nil))
>
> =A0 =A0 (defun org-buffers-set-tags (data)
> =A0 =A0 =A0"Set tags to DATA at all non top-level headings in reg= ion.
> =A0 =A0 DATA should be a list of strings. If DATA is nil, remove all t= ags
> =A0 =A0 at such headings."
> =A0 =A0 =A0(let* ((buffer-read-only nil)
> =A0 =A0 (region-p (org-region-active-p))
> =A0 =A0 (beg (if region-p (region-beginning) (point)))
> =A0 =A0 (end (if region-p (region-end) (point)))
> =A0 =A0 (headings-p (org-buffers-state-eq :atom 'heading))beg-line= end-line)
> =A0 =A0 =A0 =A0(save-excursion
> =A0 =A0 =A0 =A0 =A0(setq beg-line (progn (goto-char beg) (org-current-= line))
> =A0 =A0 =A0 =A0end-line (progn (goto-char end) (org-current-line))) > =A0 =A0 =A0 =A0 =A0(if headings-p
> =A0 =A0 =A0(setq
> =A0 =A0 =A0 end (if (and region-p (not (eq end-line beg-line)) (not (e= obp)))
> =A0 =A0 =A0 (progn (goto-char end) (org-back-to-heading) (point))
> =A0 =A0 (progn (outline-end-of-heading) (point)))
> =A0 =A0 =A0 beg (progn (goto-char beg) (point-at-bol)))
> =A0 =A0 (org-buffers-toggle-headings) ;; doesn't alter line number= s
> =A0 =A0 (setq beg (progn (org-goto-line beg-line) (point-at-bol))
> =A0 =A0 =A0 =A0 =A0end (if (eq end-line beg-line) (point-at-eol)
> =A0 =A0 =A0 =A0(progn (org-goto-line end-line) (point-at-bol)))))
> =A0 =A0 =A0 =A0 =A0(narrow-to-region beg end)
> =A0 =A0 =A0 =A0 =A0(goto-char (point-min))
> =A0 =A0 =A0 =A0 =A0(org-buffers-map-entries
> =A0 =A0 =A0 =A0 =A0 (lambda ()
> =A0 =A0 (when (or (org-buffers-state-eq :by "NONE")
> =A0 =A0 =A0 (> (org-outline-level) 1))
> =A0 =A0 =A0 (org-set-tags-to
> =A0 =A0 =A0 =A0(if data (delete-duplicates (append data (org-get-tags)= ) :test
> =A0 =A0 'string-equal))))))
> =A0 =A0 =A0 =A0 =A0(widen)
> =A0 =A0 =A0 =A0 =A0(org-content))
> =A0 =A0 =A0 =A0(unless region-p
> =A0 =A0 =A0 =A0 =A0(outline-next-heading)
> =A0 =A0 =A0 =A0 =A0(unless (or (> (org-outline-level) 1) (org-buffe= rs-state-eq :by
> =A0 =A0 "NONE"))
> =A0 =A0 (outline-next-heading)))
> =A0 =A0 =A0 =A0 =A0 =A0(unless headings-p (org-buffers-toggle-headings= ))))
>
> =A0 =A0 (defun org-buffers-execute-pending-operations ()
> =A0 =A0 =A0"Execute all pending operations.
> =A0 =A0 Currently the only type of operation supported is
> =A0 =A0 deletion. Buffers are tagged for deletion using
> =A0 =A0 `org-buffers-tag-for-deletion'. Remove such tags from buff= ers
> =A0 =A0 using `org-buffers-remove-tags'."
> =A0 =A0 =A0(interactive)
> =A0 =A0 =A0(let ((buffer-read-only nil)
> =A0 =A0 (headings-p (org-buffers-state-eq :atom 'heading)) buffer)=
> =A0 =A0 =A0 =A0(unless headings-p (org-buffers-toggle-headings))
> =A0 =A0 =A0 =A0(org-buffers-delete-regions
> =A0 =A0 =A0 =A0 (nreverse
> =A0 =A0 =A0 =A0 =A0(org-buffers-map-entries
> =A0 =A0 =A0 =A0 =A0 (lambda ()
> =A0 =A0 (if (setq buffer (org-buffers-get-buffer-name))
> =A0 =A0 =A0 =A0 (if (not (kill-buffer buffer))
> =A0 =A0 (error "Failed to kill buffer %s" buffer)
> =A0 =A0 =A0 =A0 =A0 (if (and (org-first-sibling-p)
> =A0 =A0 (not (save-excursion (org-goto-sibling))))
> =A0 =A0 =A0 (org-up-heading-safe)) ;; Only child so delete parent also=
> =A0 =A0 =A0 =A0 =A0 (cons (point) (1+ (org-end-of-subtree))))))
> =A0 =A0 =A0 =A0 =A0 "+delete")))
> =A0 =A0 =A0 =A0(unless headings-p (org-buffers-toggle-headings))))
>
> =A0 =A0 ;;; Utilities
>
> =A0 =A0 (defun org-buffers-map-entries (func &optional match)
> =A0 =A0 =A0(org-scan-tags
> =A0 =A0 =A0 func (if match (cdr (org-make-tags-matcher match)) t))) >
> =A0 =A0 (defun org-buffers-set-state (state)
> =A0 =A0 =A0"Add STATE to global state list.
> =A0 =A0 New settings have precedence over existing ones."
> =A0 =A0 =A0(mapc
> =A0 =A0 =A0 (lambda (pair) (unless (assoc (car pair) state)
> =A0 =A0 =A0 =A0(add-to-list 'state pair)))
> =A0 =A0 =A0 org-buffers-state)
> =A0 =A0 =A0(setq org-buffers-state state))
>
> =A0 =A0 (defmacro org-buffers-delete-regions (regions)
> =A0 =A0 =A0"Delete regions in list.
> =A0 =A0 REGIONS is a list of (beg . end) cons cells specifying buffer<= br> > =A0 =A0 regions."
> =A0 =A0 =A0`(mapc (lambda (pair) (if pair (delete-region (car pair) (c= dr pair))))
> =A0 =A0 ,regions))
>
> =A0 =A0 (defmacro org-buffers-state-get (key)
> =A0 =A0 =A0`(cdr (assoc ,key org-buffers-state)))
>
> =A0 =A0 (defmacro org-buffers-state-eq (key val)
> =A0 =A0 =A0`(equal (org-buffers-state-get ,key) ,val))
>
> =A0 =A0 (defmacro org-buffers-outline-level ()
> =A0 =A0 =A0'(save-excursion (beginning-of-line) (org-outline-level= )))
>
> =A0 =A0 ;;; Links to buffers
>
> =A0 =A0 (org-add-link-type "buffer" 'display-buffer)
> =A0 =A0 (add-hook 'org-store-link-functions 'org-buffers-store= -link)
>
> =A0 =A0 (defun org-buffers-store-link (&optional force)
> =A0 =A0 =A0"Store a link to an Emacs buffer.
> =A0 =A0 Returns nil by default, to avoid hijacking other link types.&q= uot;
> =A0 =A0 =A0(if force
> =A0 =A0 =A0 =A0 =A0(let* ((target (buffer-name))
> =A0 =A0 =A0 =A0 (desc target) link)
> =A0 =A0 (org-store-link-props :type "buffer")
> =A0 =A0 (setq link (org-make-link "buffer:" target))
> =A0 =A0 (org-add-link-props :link link :description desc)
> =A0 =A0 link)))
>
> =A0 =A0 (provide 'org-buffers)
> =A0 =A0 ;;; org-buffers.el ends here
> =A0 =A0 _______________________________________________
> =A0 =A0 Emacs-orgmode mailing list
> =A0 =A0 Please use `Reply All' to send replies to the list.
> =A0 =A0 Emacs-orgmode@gnu.org=
> =A0 =A0 http://lists.gnu.org/mailman/listinfo/emacs-orgmode=
>
>
> _______________________________________________
> Emacs-orgmode mailing list
> Please use `Reply All' to send replies to the list.
> Emacs-orgmode@gnu.org
> http://lists.gnu.org/mailman/listinfo/emacs-orgmode

--000e0cd5d184e888fe0484555178-- --===============0348007293== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Emacs-orgmode mailing list Please use `Reply All' to send replies to the list. Emacs-orgmode@gnu.org http://lists.gnu.org/mailman/listinfo/emacs-orgmode --===============0348007293==-- From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dan Davison Subject: Re: Using Org for browsing and managing buffers Date: Fri, 16 Apr 2010 10:22:18 -0400 Message-ID: <87wrw7pjdx.fsf@stats.ox.ac.uk> References: <87aatda0gv.fsf@stats.ox.ac.uk> <877ho8tnru.fsf@stats.ox.ac.uk> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O2mRK-0002ci-3w for emacs-orgmode@gnu.org; Fri, 16 Apr 2010 10:22:38 -0400 Received: from [140.186.70.92] (port=45135 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O2mRH-0002b9-7b for emacs-orgmode@gnu.org; Fri, 16 Apr 2010 10:22:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O2mRC-0008JK-Ct for emacs-orgmode@gnu.org; Fri, 16 Apr 2010 10:22:34 -0400 Received: from markov.stats.ox.ac.uk ([163.1.210.1]:64177) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O2mR7-0008IH-Hj for emacs-orgmode@gnu.org; Fri, 16 Apr 2010 10:22:30 -0400 In-Reply-To: (Livin Stephen Sharma's message of "Fri, 16 Apr 2010 12:41:08 +0530") List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: Livin Stephen Sharma Cc: emacs-org-mode-help gnu Livin Stephen Sharma writes: > yep, now it works! > Thanks > > About moving up/down: > =C2=A0I was a bit surprised that 'p' was not a counterpart of 'n' (the la= tter works > exactly like 'n' in Org-Agenda) > > Then I saw that in my setup (*no* customizations), there is some duplicat= ion in > the functions mapped to 'p' and 'P': Hi, I've been working on improving the key bindings, in discussion with Eric Fraga. It looks like you have loaded the new code into a system already running the old code, and the keymap has ended up as a hybrid between the two. The simplest thing would be to restart emacs. I don't know of another way to reliably make sure that all the necessary variables get reset. With the new bindings you will have p and n for movement as well as a bunch of other bindings from `org-speed-commands-default'. Thanks for trying it out! Dan > > > > > key =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 binding > > --- =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ------- > > > > SPC org-buffers-display-buffer > > . org-buffers-switch-to-buffer > > ? org-buffers-help > > B org-buffers-list:by > > H org-buffers-toggle-headings > > P org-buffers-toggle-properties > > T org-buffers-columns-view > > b org-buffers-list:by > > c org-buffers-columns-view > > d org-buffers-tag-for-deletion > > g org-buffers-list:refresh > > h org-buffers-toggle-headings > > o org-buffers-switch-to-buffer-other-window > > p org-buffers-toggle-properties > > q bury-buffer > > u org-buffers-remove-tags > > x org-buffers-execute-pending-operations > > org-buffers-follow-link > > > > > On 16 April 2010 02:51, Dan Davison wrote: > > Livin Stephen Sharma writes: > > > Am I the only one encountering: > > > > =C2=A0 =C2=A0 org-buffers-list: Invalid function: org-buffers-state= -get > > I haven't seen that error, but I may have been doing something incorr= ect > (with macros). I've got rid of them now; let me know if you still get > the error. > > Code file: http://github.com/dandavison/org-buffers/raw/master/ > org-buffers.el > Git repo: =C2=A0http://github.com/dandavison/org-buffers > > Thanks, > > Dan > > > > > > > > > > I do see many people are using this successfully > > :) > > > > Livin Stephen > > > > > > > > On Apr 09, 2010, at 06:47:20 , Dan Davison wrote: > > > > > > =C2=A0 =C2=A0 I've been working on an Org tool to browse Emacs buff= ers. Emacs has > the > > =C2=A0 =C2=A0 function list-buffers (C-x C-b), where you can view a= list of > buffers, > > =C2=A0 =C2=A0 delete buffers, etc. This is intended to be a replace= ment for > > =C2=A0 =C2=A0 list-buffers, implemented in Org-mode. > > > > =C2=A0 =C2=A0 The code is attached, and there's a git repo at > > =C2=A0 =C2=A0 http://github.com/dandavison/org-buffers > > > > =C2=A0 =C2=A0 After putting the code in your load-path and doing > > =C2=A0 =C2=A0 (require 'org-buffers), use the function `org-buffers= -list' to create > > =C2=A0 =C2=A0 the listing buffer. This is a read-only Org-mode buff= er populated > with > > =C2=A0 =C2=A0 links to open buffers. Information is stored for each= buffer using > > =C2=A0 =C2=A0 properties. By default, the buffers are grouped by ma= jor mode. Here's > a > > =C2=A0 =C2=A0 screenshot. > > > > =C2=A0 =C2=A0 http://www.princeton.edu/~ddavison/org-buffers/by-maj= or-mode.png > > > > =C2=A0 =C2=A0 The buffer has some special key-bindings: > > > > =C2=A0 =C2=A0 +----------------------------------------------------= ----------+ > > =C2=A0 =C2=A0 | ? =C2=A0 | Show all keybindings =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 | > > =C2=A0 =C2=A0 |-----+----------------------------------------------= ----------| > > =C2=A0 =C2=A0 | g =C2=A0 | Update buffer (prefix arg does hard rese= t) =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 | > > =C2=A0 =C2=A0 |-----+----------------------------------------------= ----------| > > =C2=A0 =C2=A0 | b =C2=A0 | Select a different property to group by = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0| > > =C2=A0 =C2=A0 |-----+----------------------------------------------= ----------| > > =C2=A0 =C2=A0 | RET | follow link to buffer on this line =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 | > > =C2=A0 =C2=A0 |-----+----------------------------------------------= ----------| > > =C2=A0 =C2=A0 | d =C2=A0 | Mark buffer for deletion =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 | > > =C2=A0 =C2=A0 |-----+----------------------------------------------= ----------| > > =C2=A0 =C2=A0 | u =C2=A0 | Remove mark =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0| > > =C2=A0 =C2=A0 |-----+----------------------------------------------= ----------| > > =C2=A0 =C2=A0 | x =C2=A0 | Delete marked buffers =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0| > > =C2=A0 =C2=A0 |-----+----------------------------------------------= ----------| > > =C2=A0 =C2=A0 | o =C2=A0 | Like RET (see variable org-buffers-follo= w-link-method) | > > =C2=A0 =C2=A0 |-----+----------------------------------------------= ----------| > > =C2=A0 =C2=A0 | . =C2=A0 | Like RET but switch to buffer in same wi= ndow =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 | > > =C2=A0 =C2=A0 |-----+----------------------------------------------= ----------| > > =C2=A0 =C2=A0 | h =C2=A0 | toggle between headings and plain entrie= s for buffers =C2=A0| > > =C2=A0 =C2=A0 |-----+----------------------------------------------= ----------| > > =C2=A0 =C2=A0 | p =C2=A0 | toggle in-buffer properties on/off =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 | > > =C2=A0 =C2=A0 |-----+----------------------------------------------= ----------| > > =C2=A0 =C2=A0 | c =C2=A0 | Switch to column-view =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0| > > =C2=A0 =C2=A0 +----------------------------------------------------= ----------+ > > > > =C2=A0 =C2=A0 If there's an active region, d and u operate on all b= uffers in the > > =C2=A0 =C2=A0 region. > > > > =C2=A0 =C2=A0 Some variables that can be configured: > > =C2=A0 =C2=A0 - org-buffers-buffer-properties > > =C2=A0 =C2=A0 - org-buffers-excluded-modes > > =C2=A0 =C2=A0 - org-buffers-excluded-buffers > > =C2=A0 =C2=A0 - org-buffers-follow-link-method > > =C2=A0 =C2=A0 - org-buffers-mode-hook > > =C2=A0 =C2=A0 - org-buffers-buffer-name > > > > =C2=A0 =C2=A0 Some possible extensions: > > =C2=A0 =C2=A0 - Browse recent files using recentf > > =C2=A0 =C2=A0 - Allow several buffers to be marked for side-by-side= display > > =C2=A0 =C2=A0 - Maintain folding configuration across buffer updates > > =C2=A0 =C2=A0 - Make faster > > > > =C2=A0 =C2=A0 As always, any feedback, suggestions and patches will= be very > welcome! > > > > =C2=A0 =C2=A0 Dan > > > > =C2=A0 =C2=A0 p.s. The column-view mode works for following links, = but does need > > =C2=A0 =C2=A0 further attention. > > > > =C2=A0 =C2=A0 ;;; org-buffers.el --- An Org-mode tool for buffer ma= nagement > > > > =C2=A0 =C2=A0 ;; Copyright (C) 2010 =C2=A0Dan Davison > > > > =C2=A0 =C2=A0 ;; Author: Dan Davison > > =C2=A0 =C2=A0 ;; Keywords: outlines, hypermedia, calendar, wp > > =C2=A0 =C2=A0 ;; Homepage: http://orgmode.org > > > > =C2=A0 =C2=A0 ;;; License: > > > > =C2=A0 =C2=A0 ;; This program is free software; you can redistribut= e it and/or > modify > > =C2=A0 =C2=A0 ;; it under the terms of the GNU General Public Licen= se as published > by > > =C2=A0 =C2=A0 ;; the Free Software Foundation; either version 3, or= (at your > option) > > =C2=A0 =C2=A0 ;; any later version. > > =C2=A0 =C2=A0 ;; > > =C2=A0 =C2=A0 ;; This program is distributed in the hope that it wi= ll be useful, > > =C2=A0 =C2=A0 ;; but WITHOUT ANY WARRANTY; without even the implied= warranty of > > =C2=A0 =C2=A0 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOS= E. =C2=A0See the > > =C2=A0 =C2=A0 ;; GNU General Public License for more details. > > =C2=A0 =C2=A0 ;; > > =C2=A0 =C2=A0 ;; You should have received a copy of the GNU General= Public License > > =C2=A0 =C2=A0 ;; along with GNU Emacs; see the file COPYING. =C2=A0= If not, write to the > > =C2=A0 =C2=A0 ;; Free Software Foundation, Inc., 51 Franklin Street= , Fifth Floor, > > =C2=A0 =C2=A0 ;; Boston, MA 02110-1301, USA. > > > > =C2=A0 =C2=A0 ;;; Commentary: > > > > =C2=A0 =C2=A0 ;;; Code: > > > > =C2=A0 =C2=A0 (require 'org) > > =C2=A0 =C2=A0 (require 'cl) > > > > =C2=A0 =C2=A0 ;;; Variables > > =C2=A0 =C2=A0 (defvar org-buffers-buffer-name > > =C2=A0 =C2=A0 =C2=A0"*Buffers*" > > =C2=A0 =C2=A0 =C2=A0"Name of buffer in which buffer list is display= ed") > > > > =C2=A0 =C2=A0 (defvar org-buffers-state > > =C2=A0 =C2=A0 =C2=A0'((:by . "major-mode") (:atom . heading) (:prop= erties . nil)) > > =C2=A0 =C2=A0 =C2=A0"Association list specifiying the current state= of org-buffers.") > > > > =C2=A0 =C2=A0 (defvar org-buffers-follow-link-method 'org-open-at-p= oint > > =C2=A0 =C2=A0 =C2=A0"Method used to follow link with RET. Must be o= ne of > > > > =C2=A0 =C2=A0 'org-open-at-point :: use `org-open-at-point' to foll= ow link. > > =C2=A0 =C2=A0 'current-window =C2=A0 =C2=A0:: use switch-to-buffer > > =C2=A0 =C2=A0 'other-window =C2=A0 =C2=A0 =C2=A0:: use switch-to-bu= ffer-other-window > > > > =C2=A0 =C2=A0 Setting this variable to 'current-window makes the be= haviour more > > =C2=A0 =C2=A0 consistent with that of `Buffer-menu-mode' and `dired= -mode'") > > > > =C2=A0 =C2=A0 (defvar org-buffers-buffer-properties > > =C2=A0 =C2=A0 =C2=A0'(("buffer-name" . (buffer-name)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0("major-mode" . (let ((mode (symbol-name= major-mode))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(if (string-match "-mode$" mode) > > =C2=A0 =C2=A0 =C2=A0(replace-match "" nil t mode) mode))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0("buffer-file-name" . (buffer-file-name)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0("default-directory" . default-directory) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0("buffer-modified-p" . (format "%s" (buf= fer-modified-p)))) > > =C2=A0 =C2=A0 =C2=A0"Association list specifying properties to be s= tored for each > > =C2=A0 =C2=A0 buffer. The car of each element is the name of the pr= operty, and > > =C2=A0 =C2=A0 the cdr is an expression which, when evaluated in the= buffer, > > =C2=A0 =C2=A0 yields the property value.") > > > > =C2=A0 =C2=A0 (defcustom org-buffers-excluded-buffers > > =C2=A0 =C2=A0 =C2=A0`("*Completions*" ,org-buffers-buffer-name) > > =C2=A0 =C2=A0 =C2=A0"List of names of buffers that should not be li= sted by > > =C2=A0 =C2=A0 =C2=A0org-buffers-list." > > =C2=A0 =C2=A0 =C2=A0:group 'org-buffers) > > > > =C2=A0 =C2=A0 (defcustom org-buffers-excluded-modes nil > > =C2=A0 =C2=A0 =C2=A0"List of names of major-modes (strings) that sh= ould not be listed > > =C2=A0 =C2=A0 =C2=A0by org-buffers-list." > > =C2=A0 =C2=A0 =C2=A0:group 'org-buffers) > > > > =C2=A0 =C2=A0 ;;; Mode > > =C2=A0 =C2=A0 (defvar org-buffers-mode-map (make-sparse-keymap)) > > > > =C2=A0 =C2=A0 (defvar org-buffers-mode-hook nil > > =C2=A0 =C2=A0 =C2=A0"Hook for functions to be called after buffer l= isting is > > =C2=A0 =C2=A0 =C2=A0created. Note that the buffer is read-only, so = if the hook > > =C2=A0 =C2=A0 =C2=A0function is to modify the buffer it should use = a let binding to > > =C2=A0 =C2=A0 =C2=A0temporarily bind buffer-read-only to nil.") > > > > =C2=A0 =C2=A0 (define-minor-mode org-buffers-mode > > =C2=A0 =C2=A0 =C2=A0"An Org-mode tool for buffer management. > > =C2=A0 =C2=A0 \\{org-buffers-mode-map}" > > =C2=A0 =C2=A0 =C2=A0nil " buffers" nil > > =C2=A0 =C2=A0 =C2=A0(org-set-local 'org-tag-alist '(("delete" . ?d)= )) > > =C2=A0 =C2=A0 =C2=A0(org-set-local'org-tags-column -50) > > =C2=A0 =C2=A0 =C2=A0(org-set-local 'org-columns-default-format "%25= buffer-name(Buffer) > > =C2=A0 =C2=A0 %25major-mode(Mode) %25default-directory(Dir) %5buffe= r-modified-p > (Modified) > > =C2=A0 =C2=A0 ") > > =C2=A0 =C2=A0 =C2=A0(add-hook 'kill-buffer-hook 'org-buffers-reset-= state nil 'local)) > > > > =C2=A0 =C2=A0 (defun org-buffers-help () > > =C2=A0 =C2=A0 =C2=A0(interactive) > > =C2=A0 =C2=A0 =C2=A0(describe-function 'org-buffers-mode)) > > > > =C2=A0 =C2=A0 ;;; Keys > > =C2=A0 =C2=A0 (define-key org-buffers-mode-map [(return)] 'org-buff= ers-follow-link) > > =C2=A0 =C2=A0 (define-key org-buffers-mode-map "b" 'org-buffers-lis= t:by) > > =C2=A0 =C2=A0 (define-key org-buffers-mode-map "c" 'org-buffers-col= umns-view) > > =C2=A0 =C2=A0 (define-key org-buffers-mode-map "d" 'org-buffers-tag= -for-deletion) > > =C2=A0 =C2=A0 (define-key org-buffers-mode-map "g" 'org-buffers-lis= t:refresh) > > =C2=A0 =C2=A0 (define-key org-buffers-mode-map "." 'org-buffers-swi= tch-to-buffer) > > =C2=A0 =C2=A0 (define-key org-buffers-mode-map "h" 'org-buffers-tog= gle-headings) > > =C2=A0 =C2=A0 (define-key org-buffers-mode-map "o" > > =C2=A0 =C2=A0 'org-buffers-switch-to-buffer-other-window) > > =C2=A0 =C2=A0 (define-key org-buffers-mode-map "p" 'org-buffers-tog= gle-properties) > > =C2=A0 =C2=A0 (define-key org-buffers-mode-map "u" 'org-buffers-rem= ove-tags) > > =C2=A0 =C2=A0 (define-key org-buffers-mode-map "x" > > =C2=A0 =C2=A0 'org-buffers-execute-pending-operations) > > =C2=A0 =C2=A0 (define-key org-buffers-mode-map "?" 'org-buffers-hel= p) > > =C2=A0 =C2=A0 ;;; Listing and view cycling > > > > =C2=A0 =C2=A0 (defun org-buffers-list (&optional refresh frame) > > =C2=A0 =C2=A0 =C2=A0"Create an Org-mode listing of Emacs buffers. > > =C2=A0 =C2=A0 By default, buffers are grouped by major mode. Option= al > > =C2=A0 =C2=A0 argument FRAME specifies the frame whose buffers shou= ld be > > =C2=A0 =C2=A0 listed." > > =C2=A0 =C2=A0 =C2=A0(interactive) > > =C2=A0 =C2=A0 =C2=A0(pop-to-buffer > > =C2=A0 =C2=A0 =C2=A0 (or > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(and (not refresh) (get-buffer org-buffe= rs-buffer-name)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(let ((org-buffers-p (equal (buffer-name) > org-buffers-buffer-name)) > > =C2=A0 =C2=A0 =C2=A0(by (or (org-buffers-state-get :by) "major-mode= ")) > > =C2=A0 =C2=A0 =C2=A0(atom (org-buffers-state-get :atom)) target) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(when org-buffers-p > > =C2=A0 =C2=A0 (if (and (org-before-first-heading-p) (not (org-on-he= ading-p))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(outline-next-heading)) > > =C2=A0 =C2=A0 (setq target > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(condition-case nil (org-make-org= -heading-search-string) (error > > =C2=A0 =C2=A0 nil)))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(with-current-buffer (get-buffer-= create org-buffers-buffer-name) > > =C2=A0 =C2=A0 (setq buffer-read-only nil) > > =C2=A0 =C2=A0 (erase-buffer) > > =C2=A0 =C2=A0 (org-mode) > > =C2=A0 =C2=A0 (dolist > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(buffer > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 (sort (remove-if 'org-buffers-exclude-p > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(mapcar 'buffer-name (buffer-list= frame))) 'string<)) > > =C2=A0 =C2=A0 =C2=A0(org-insert-heading t) > > =C2=A0 =C2=A0 =C2=A0(insert > > =C2=A0 =C2=A0 =C2=A0 (org-make-link-string (concat "buffer:" buffer= ) buffer) "\n") > > =C2=A0 =C2=A0 =C2=A0(dolist (pair (org-buffers-get-buffer-props buf= fer)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-set-property (car pair) (cdr pair))= )) > > =C2=A0 =C2=A0 (org-buffers-set-state '((:atom . heading))) > > =C2=A0 =C2=A0 (goto-char (point-min)) > > =C2=A0 =C2=A0 (unless (equal by "NONE") (org-buffers-group-by by)) > > =C2=A0 =C2=A0 (if target (condition-case nil (org-link-search targe= t) (error nil))) > > =C2=A0 =C2=A0 (beginning-of-line) > > =C2=A0 =C2=A0 (if (equal by "NONE") > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-overview) > > =C2=A0 =C2=A0 =C2=A0(case atom > > =C2=A0 =C2=A0 =C2=A0 =C2=A0('heading (progn (org-overview) (org-con= tent))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0('line (progn (show-all) (org-buffers-to= ggle-headings))))) > > =C2=A0 =C2=A0 (save-excursion > > =C2=A0 =C2=A0 =C2=A0(mark-whole-buffer) > > =C2=A0 =C2=A0 =C2=A0(indent-region (point-min) (point-max))) > > =C2=A0 =C2=A0 (org-buffers-mode) > > =C2=A0 =C2=A0 (setq buffer-read-only t) > > =C2=A0 =C2=A0 (current-buffer)))))) > > > > =C2=A0 =C2=A0 (defun org-buffers-list:refresh (&optional arg) > > =C2=A0 =C2=A0 =C2=A0"Refresh org-buffers listing." > > =C2=A0 =C2=A0 =C2=A0(interactive "P") > > =C2=A0 =C2=A0 =C2=A0(if arg (org-buffers-reset-state)) > > =C2=A0 =C2=A0 =C2=A0(org-buffers-list 'refresh)) > > > > =C2=A0 =C2=A0 (defun org-buffers-list:by (&optional prop) > > =C2=A0 =C2=A0 =C2=A0"Group buffers according to value of property P= ROP." > > =C2=A0 =C2=A0 =C2=A0(interactive) > > =C2=A0 =C2=A0 =C2=A0(let ((buffer-read-only nil) > > =C2=A0 =C2=A0 (headings-p (org-buffers-state-eq :atom 'heading))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(unless (org-buffers-state-get :properti= es) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-buffers-toggle-properties)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-buffers-set-state > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 `((:by . > > =C2=A0 =C2=A0 =C2=A0 =C2=A0,(or prop > > =C2=A0 =C2=A0 (org-completing-read > > =C2=A0 =C2=A0 =C2=A0"Property to group by: " > > =C2=A0 =C2=A0 =C2=A0(cons "NONE" (mapcar 'car org-buffers-buffer-pr= operties))))))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-buffers-list 'refresh) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(unless headings-p (org-buffers-toggle-h= eadings)))) > > > > =C2=A0 =C2=A0 (defun org-buffers-toggle-properties () > > =C2=A0 =C2=A0 =C2=A0"Toggle entry properties in org-buffers listing= buffer. > > =C2=A0 =C2=A0 Removing properties may provide a less cluttered appe= arance for > > =C2=A0 =C2=A0 browsing. However, in-buffer properties will be resto= red during > > =C2=A0 =C2=A0 certain operations, such as `org-buffers-list:by'." > > =C2=A0 =C2=A0 =C2=A0(interactive) > > =C2=A0 =C2=A0 =C2=A0(if (org-buffers-state-get :properties) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(progn (org-buffers-delete-proper= ties) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 (show-all) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 (org-buffers-set-state '((:properties .= nil)))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-buffers-set-state > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 '((:atom . heading) (:properties . t))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-buffers-list 'refresh))) > > > > =C2=A0 =C2=A0 (defun org-buffers-toggle-headings () > > =C2=A0 =C2=A0 =C2=A0"Toggle viewing of buffers as org headings. > > =C2=A0 =C2=A0 Headings will be automatically restored during certain > > =C2=A0 =C2=A0 operations, such as setting deletion tags." > > =C2=A0 =C2=A0 =C2=A0(interactive) > > =C2=A0 =C2=A0 =C2=A0(let ((buffer-read-only nil) > > =C2=A0 =C2=A0 (headings-p (org-buffers-state-eq :atom 'heading)) > > =C2=A0 =C2=A0 (flat-p (org-buffers-state-eq :by "NONE"))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(if (and headings-p (org-buffers-state-g= et :properties)) > > =C2=A0 =C2=A0 (org-buffers-toggle-properties)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(save-excursion > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(goto-char (point-min)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(if (and (or headings-p (not flat= -p)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (not (outline-on-heading-p))) > > =C2=A0 =C2=A0 =C2=A0(outline-next-heading)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(if flat-p > > =C2=A0 =C2=A0 =C2=A0(progn > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(push-mark (point) 'nomsg 'activate) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(end-of-buffer) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-ctrl-c-star) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(pop-mark)) > > =C2=A0 =C2=A0 (while (not (eobp)) > > =C2=A0 =C2=A0 =C2=A0(push-mark > > =C2=A0 =C2=A0 =C2=A0 (save-excursion (forward-line 1) (point)) 'nom= sg 'activate) > > =C2=A0 =C2=A0 =C2=A0(org-forward-same-level 1) > > =C2=A0 =C2=A0 =C2=A0(org-ctrl-c-star) > > =C2=A0 =C2=A0 =C2=A0(pop-mark))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(mark-whole-buffer) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(indent-region (point-min) (point= -max))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-buffers-set-state > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 `((:atom . ,(if headings-p 'line 'headi= ng)))))) > > > > =C2=A0 =C2=A0 (defun org-buffers-delete-properties () > > =C2=A0 =C2=A0 =C2=A0(let ((buffer-read-only nil)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(save-excursion > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(goto-char (point-min)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-buffers-delete-regions > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (nreverse > > =C2=A0 =C2=A0 (org-buffers-map-entries 'org-buffers-get-property-bl= ock)))))) > > > > =C2=A0 =C2=A0 (defun org-buffers-get-property-block () > > =C2=A0 =C2=A0 =C2=A0"Return the (beg . end) range of the property d= rawer. > > =C2=A0 =C2=A0 Unlike the org version the limits include the keyword= s delimiting > > =C2=A0 =C2=A0 the drawer." > > =C2=A0 =C2=A0 =C2=A0(let ((beg (point)) > > =C2=A0 =C2=A0 (end (progn (outline-next-heading) (point)))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(goto-char beg) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(if (re-search-forward org-property-draw= er-re end t) > > =C2=A0 =C2=A0 (cons (match-beginning 1) (match-end 0))))) > > > > =C2=A0 =C2=A0 (defun org-buffers-group-by (property) > > =C2=A0 =C2=A0 =C2=A0"Group top level headings according to the valu= e of PROPERTY." > > =C2=A0 =C2=A0 =C2=A0(let ((atom (org-buffers-state-get :atom))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(save-excursion > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(goto-char (point-min)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(mapc (lambda (subtree) ;; Create= subtree for each value of > `property' > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-insert-heading t) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(if (> (org-buffers-outline-level= ) 1) > > =C2=A0 =C2=A0 =C2=A0(org-promote)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(insert (car subtree) "\n") > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-insert-subheading t) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(mapc 'org-buffers-insert-parsed-= entry (cdr subtree))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(prog1 > > =C2=A0 =C2=A0 (mapcar (lambda (val) ;; Form list of parsed entries = for each unique > value > > =C2=A0 =C2=A0 of `property' > > =C2=A0 =C2=A0 =C2=A0(cons val (org-buffers-parse-selected-entries p= roperty val))) > > =C2=A0 =C2=A0 (sort > > =C2=A0 =C2=A0 (delete-dups (org-buffers-map-entries (lambda () (org= -entry-get nil > > =C2=A0 =C2=A0 property nil)))) > > =C2=A0 =C2=A0 'string<)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(erase-buffer)))))) > > > > =C2=A0 =C2=A0 (defun org-buffers-exclude-p (buffer) > > =C2=A0 =C2=A0 =C2=A0"Return non-nil if BUFFER should not be listed." > > =C2=A0 =C2=A0 =C2=A0(or (member (with-current-buffer buffer major-m= ode) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0org-buffers-excluded-modes) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(member buffer org-buffers-exclud= ed-buffers) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(string=3D (substring buffer 0 1)= " "))) > > > > =C2=A0 =C2=A0 (defun org-buffers-reset-state () > > =C2=A0 =C2=A0 =C2=A0(org-buffers-set-state > > =C2=A0 =C2=A0 =C2=A0 '((:by . "major-mode") (:atom . heading) (:pro= perties . nil)))) > > > > =C2=A0 =C2=A0 (defun org-buffers-columns-view () > > =C2=A0 =C2=A0 =C2=A0"View buffers in Org-mode columns view. > > =C2=A0 =C2=A0 This is currently experimental. RET can be used to fo= llow links > > =C2=A0 =C2=A0 in the first column, but certain other org-buffers ke= ys conflict > > =C2=A0 =C2=A0 with column-view or otherwise do not work correctly." > > =C2=A0 =C2=A0 =C2=A0(interactive) > > =C2=A0 =C2=A0 =C2=A0(let ((by (org-buffers-state-get :by)) > > =C2=A0 =C2=A0 (buffer-read-only nil)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(unless (equal by "NONE") (org-buffers-l= ist:by "NONE")) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(unless (org-buffers-state-get :properti= es) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-buffers-toggle-properties)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(unless (equal by "NONE") > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(goto-char (point-min)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-sort-entries-or-items nil ?r= nil nil by) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-overview)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(mark-whole-buffer) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-columns))) > > > > =C2=A0 =C2=A0 ;;; Parsing and inserting entries > > =C2=A0 =C2=A0 (defun org-buffers-parse-selected-entries (prop val) > > =C2=A0 =C2=A0 =C2=A0"Parse all entries with property PROP value VAL= ." > > =C2=A0 =C2=A0 =C2=A0(delq nil > > =C2=A0 =C2=A0 (org-buffers-map-entries > > =C2=A0 =C2=A0 (lambda () (when (equal (org-entry-get nil prop) val) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(cons (org-get-heading) (org-get-= entry))))))) > > > > =C2=A0 =C2=A0 (defun org-buffers-insert-parsed-entry (entry) > > =C2=A0 =C2=A0 =C2=A0"Insert a parsed entry" > > =C2=A0 =C2=A0 =C2=A0(unless (org-at-heading-p) (org-insert-heading)) > > =C2=A0 =C2=A0 =C2=A0(insert (car entry) "\n") > > =C2=A0 =C2=A0 =C2=A0(if (org-buffers-state-get :properties) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(insert (cdr entry)))) > > > > =C2=A0 =C2=A0 (defun org-buffers-get-buffer-props (buffer) > > =C2=A0 =C2=A0 =C2=A0"Create alist of properties of BUFFER, as strin= gs." > > =C2=A0 =C2=A0 =C2=A0(with-current-buffer buffer > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(mapcar > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 (lambda (pair) (cons (car pair) (eval (= cdr pair)))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 org-buffers-buffer-properties))) > > > > =C2=A0 =C2=A0 ;;; Follow-link behaviour > > > > =C2=A0 =C2=A0 (defun org-buffers-follow-link () > > =C2=A0 =C2=A0 =C2=A0"Follow link to buffer on this line. > > =C2=A0 =C2=A0 The buffer-switching behaviour of this function is de= termined by > > =C2=A0 =C2=A0 the variable `org-buffers-follow-link-method'. See al= so > > =C2=A0 =C2=A0 `org-buffers-switch-to-buffer' and > > =C2=A0 =C2=A0 `org-buffers-switch-to-buffer-other-window', whose be= haviour is > > =C2=A0 =C2=A0 hard-wired." > > =C2=A0 =C2=A0 =C2=A0(interactive) > > =C2=A0 =C2=A0 =C2=A0(org-buffers-switch-to-buffer-generic > org-buffers-follow-link-method)) > > > > =C2=A0 =C2=A0 (defun org-buffers-switch-to-buffer () > > =C2=A0 =C2=A0 "Switch to this entry's buffer in current window." > > =C2=A0 =C2=A0 =C2=A0(interactive) > > =C2=A0 =C2=A0 =C2=A0(org-buffers-switch-to-buffer-generic 'current-= window)) > > > > =C2=A0 =C2=A0 (defun org-buffers-switch-to-buffer-other-window () > > =C2=A0 =C2=A0 =C2=A0"Switch to this entry's buffer in other window." > > =C2=A0 =C2=A0 =C2=A0(interactive) > > =C2=A0 =C2=A0 =C2=A0(org-buffers-switch-to-buffer-generic 'other-wi= ndow)) > > > > =C2=A0 =C2=A0 (defun org-buffers-switch-to-buffer-generic (method) > > =C2=A0 =C2=A0 =C2=A0(save-excursion > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(let ((atom (org-buffers-state-get :atom= )) buffer) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(cond > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ((eq atom 'heading) (org-back-to= -heading)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (t (beginning-of-line))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setq buffer (org-buffers-get-buf= fer-name)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(if (get-buffer buffer) > > =C2=A0 =C2=A0 =C2=A0(case method > > =C2=A0 =C2=A0 =C2=A0 =C2=A0('org-open-at-point (org-open-at-point)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0('current-window (switch-to-buffer buffe= r)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0('other-window (switch-to-buffer-other-w= indow buffer))) > > =C2=A0 =C2=A0 (error "No such buffer: %s" buffer))))) > > > > =C2=A0 =C2=A0 (defun org-buffers-get-buffer-name () > > =C2=A0 =C2=A0 =C2=A0"Get buffer-name for current entry." > > =C2=A0 =C2=A0 =C2=A0(let ((headings-p (org-buffers-state-eq :atom '= heading))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(or (and headings-p (org-entry-get nil "= buffer-name")) > > =C2=A0 =C2=A0 (and (save-excursion > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (if headings-p (org-back-to-head= ing)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (re-search-forward "\\[\\[buffer= :\\([^\]]*\\)" (point-at-eol) > t)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 (org-link-unescape (match-string 1)))))) > > > > =C2=A0 =C2=A0 ;;; Setting tags and executing operations > > > > =C2=A0 =C2=A0 (defun org-buffers-tag-for-deletion () > > =C2=A0 =C2=A0 =C2=A0"Mark buffer for deletion. > > =C2=A0 =C2=A0 If a region is selected, all buffers in the region ar= e marked for > > =C2=A0 =C2=A0 deletion. Buffers marked for deletion can be deleted = using > > =C2=A0 =C2=A0 `org-buffers-execute-pending-operations'." > > =C2=A0 =C2=A0 =C2=A0(interactive) > > =C2=A0 =C2=A0 =C2=A0(org-buffers-set-tags '("delete"))) > > > > =C2=A0 =C2=A0 (defun org-buffers-remove-tags () > > =C2=A0 =C2=A0 =C2=A0"Remove deletion marks from buffers. > > =C2=A0 =C2=A0 If a region is selected, marks are removed from all b= uffers in > > =C2=A0 =C2=A0 the region." > > =C2=A0 =C2=A0 =C2=A0(interactive) > > =C2=A0 =C2=A0 =C2=A0(org-buffers-set-tags nil)) > > > > =C2=A0 =C2=A0 (defun org-buffers-set-tags (data) > > =C2=A0 =C2=A0 =C2=A0"Set tags to DATA at all non top-level headings= in region. > > =C2=A0 =C2=A0 DATA should be a list of strings. If DATA is nil, rem= ove all tags > > =C2=A0 =C2=A0 at such headings." > > =C2=A0 =C2=A0 =C2=A0(let* ((buffer-read-only nil) > > =C2=A0 =C2=A0 (region-p (org-region-active-p)) > > =C2=A0 =C2=A0 (beg (if region-p (region-beginning) (point))) > > =C2=A0 =C2=A0 (end (if region-p (region-end) (point))) > > =C2=A0 =C2=A0 (headings-p (org-buffers-state-eq :atom 'heading))beg= -line end-line) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(save-excursion > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setq beg-line (progn (goto-char = beg) (org-current-line)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0end-line (progn (goto-char end) (org-cur= rent-line))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(if headings-p > > =C2=A0 =C2=A0 =C2=A0(setq > > =C2=A0 =C2=A0 =C2=A0 end (if (and region-p (not (eq end-line beg-li= ne)) (not (eobp))) > > =C2=A0 =C2=A0 =C2=A0 (progn (goto-char end) (org-back-to-heading) (= point)) > > =C2=A0 =C2=A0 (progn (outline-end-of-heading) (point))) > > =C2=A0 =C2=A0 =C2=A0 beg (progn (goto-char beg) (point-at-bol))) > > =C2=A0 =C2=A0 (org-buffers-toggle-headings) ;; doesn't alter line n= umbers > > =C2=A0 =C2=A0 (setq beg (progn (org-goto-line beg-line) (point-at-b= ol)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0end (if (eq end-line beg-line) (p= oint-at-eol) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(progn (org-goto-line end-line) (point-a= t-bol))))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(narrow-to-region beg end) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(goto-char (point-min)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-buffers-map-entries > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (lambda () > > =C2=A0 =C2=A0 (when (or (org-buffers-state-eq :by "NONE") > > =C2=A0 =C2=A0 =C2=A0 (> (org-outline-level) 1)) > > =C2=A0 =C2=A0 =C2=A0 (org-set-tags-to > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(if data (delete-duplicates (append data= (org-get-tags)) :test > > =C2=A0 =C2=A0 'string-equal)))))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(widen) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-content)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(unless region-p > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(outline-next-heading) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(unless (or (> (org-outline-level= ) 1) (org-buffers-state-eq :by > > =C2=A0 =C2=A0 "NONE")) > > =C2=A0 =C2=A0 (outline-next-heading))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(unless headings-p (org-bu= ffers-toggle-headings)))) > > > > =C2=A0 =C2=A0 (defun org-buffers-execute-pending-operations () > > =C2=A0 =C2=A0 =C2=A0"Execute all pending operations. > > =C2=A0 =C2=A0 Currently the only type of operation supported is > > =C2=A0 =C2=A0 deletion. Buffers are tagged for deletion using > > =C2=A0 =C2=A0 `org-buffers-tag-for-deletion'. Remove such tags from= buffers > > =C2=A0 =C2=A0 using `org-buffers-remove-tags'." > > =C2=A0 =C2=A0 =C2=A0(interactive) > > =C2=A0 =C2=A0 =C2=A0(let ((buffer-read-only nil) > > =C2=A0 =C2=A0 (headings-p (org-buffers-state-eq :atom 'heading)) bu= ffer) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(unless headings-p (org-buffers-toggle-h= eadings)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-buffers-delete-regions > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 (nreverse > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(org-buffers-map-entries > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (lambda () > > =C2=A0 =C2=A0 (if (setq buffer (org-buffers-get-buffer-name)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 (if (not (kill-buffer buffer)) > > =C2=A0 =C2=A0 (error "Failed to kill buffer %s" buffer) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (if (and (org-first-sibling-p) > > =C2=A0 =C2=A0 (not (save-excursion (org-goto-sibling)))) > > =C2=A0 =C2=A0 =C2=A0 (org-up-heading-safe)) ;; Only child so delete= parent also > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (cons (point) (1+ (org-end-of-su= btree)))))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "+delete"))) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(unless headings-p (org-buffers-toggle-h= eadings)))) > > > > =C2=A0 =C2=A0 ;;; Utilities > > > > =C2=A0 =C2=A0 (defun org-buffers-map-entries (func &optional match) > > =C2=A0 =C2=A0 =C2=A0(org-scan-tags > > =C2=A0 =C2=A0 =C2=A0 func (if match (cdr (org-make-tags-matcher mat= ch)) t))) > > > > =C2=A0 =C2=A0 (defun org-buffers-set-state (state) > > =C2=A0 =C2=A0 =C2=A0"Add STATE to global state list. > > =C2=A0 =C2=A0 New settings have precedence over existing ones." > > =C2=A0 =C2=A0 =C2=A0(mapc > > =C2=A0 =C2=A0 =C2=A0 (lambda (pair) (unless (assoc (car pair) state) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0(add-to-list 'state pair))) > > =C2=A0 =C2=A0 =C2=A0 org-buffers-state) > > =C2=A0 =C2=A0 =C2=A0(setq org-buffers-state state)) > > > > =C2=A0 =C2=A0 (defmacro org-buffers-delete-regions (regions) > > =C2=A0 =C2=A0 =C2=A0"Delete regions in list. > > =C2=A0 =C2=A0 REGIONS is a list of (beg . end) cons cells specifyin= g buffer > > =C2=A0 =C2=A0 regions." > > =C2=A0 =C2=A0 =C2=A0`(mapc (lambda (pair) (if pair (delete-region (= car pair) (cdr > pair)))) > > =C2=A0 =C2=A0 ,regions)) > > > > =C2=A0 =C2=A0 (defmacro org-buffers-state-get (key) > > =C2=A0 =C2=A0 =C2=A0`(cdr (assoc ,key org-buffers-state))) > > > > =C2=A0 =C2=A0 (defmacro org-buffers-state-eq (key val) > > =C2=A0 =C2=A0 =C2=A0`(equal (org-buffers-state-get ,key) ,val)) > > > > =C2=A0 =C2=A0 (defmacro org-buffers-outline-level () > > =C2=A0 =C2=A0 =C2=A0'(save-excursion (beginning-of-line) (org-outli= ne-level))) > > > > =C2=A0 =C2=A0 ;;; Links to buffers > > > > =C2=A0 =C2=A0 (org-add-link-type "buffer" 'display-buffer) > > =C2=A0 =C2=A0 (add-hook 'org-store-link-functions 'org-buffers-stor= e-link) > > > > =C2=A0 =C2=A0 (defun org-buffers-store-link (&optional force) > > =C2=A0 =C2=A0 =C2=A0"Store a link to an Emacs buffer. > > =C2=A0 =C2=A0 Returns nil by default, to avoid hijacking other link= types." > > =C2=A0 =C2=A0 =C2=A0(if force > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(let* ((target (buffer-name)) > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 (desc target) link) > > =C2=A0 =C2=A0 (org-store-link-props :type "buffer") > > =C2=A0 =C2=A0 (setq link (org-make-link "buffer:" target)) > > =C2=A0 =C2=A0 (org-add-link-props :link link :description desc) > > =C2=A0 =C2=A0 link))) > > > > =C2=A0 =C2=A0 (provide 'org-buffers) > > =C2=A0 =C2=A0 ;;; org-buffers.el ends here > > =C2=A0 =C2=A0 _______________________________________________ > > =C2=A0 =C2=A0 Emacs-orgmode mailing list > > =C2=A0 =C2=A0 Please use `Reply All' to send replies to the list. > > =C2=A0 =C2=A0 Emacs-orgmode@gnu.org > > =C2=A0 =C2=A0 http://lists.gnu.org/mailman/listinfo/emacs-orgmode > > > > > > _______________________________________________ > > Emacs-orgmode mailing list > > Please use `Reply All' to send replies to the list. > > Emacs-orgmode@gnu.org > > http://lists.gnu.org/mailman/listinfo/emacs-orgmode > > > _______________________________________________ > Emacs-orgmode mailing list > Please use `Reply All' to send replies to the list. > Emacs-orgmode@gnu.org > http://lists.gnu.org/mailman/listinfo/emacs-orgmode From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dan Davison Subject: Re: Using Org for browsing and managing buffers Date: Sun, 18 Apr 2010 23:47:11 -0400 Message-ID: <87bpdghznk.fsf@stats.ox.ac.uk> References: <87aatda0gv.fsf@stats.ox.ac.uk> <87d3y1pyuz.wl%ucecesf@ucl.ac.uk> <87mxx5cpo0.fsf@stats.ox.ac.uk> <87tyrcnc2c.wl%ucecesf@ucl.ac.uk> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O3hxC-0003eG-PR for emacs-orgmode@gnu.org; Sun, 18 Apr 2010 23:47:22 -0400 Received: from [140.186.70.92] (port=46233 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O3hxA-0003e7-4N for emacs-orgmode@gnu.org; Sun, 18 Apr 2010 23:47:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O3hx7-0001g8-0T for emacs-orgmode@gnu.org; Sun, 18 Apr 2010 23:47:19 -0400 Received: from markov.stats.ox.ac.uk ([163.1.210.1]:34634) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O3hx6-0001fU-OZ for emacs-orgmode@gnu.org; Sun, 18 Apr 2010 23:47:16 -0400 In-Reply-To: <87tyrcnc2c.wl%ucecesf@ucl.ac.uk> (Eric S. Fraga's message of "Thu, 15 Apr 2010 13:18:51 +0100") List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: Eric S Fraga Cc: emacs org-mode mailing list --=-=-= http://github.com/dandavison/org-buffers http://github.com/dandavison/org-buffers/raw/master/org-buffers.el Hi Eric, Eric S Fraga writes: [...] > - I like the fact I can customise RET or, more to the point, that it > be consistent with the rest of org-mode. I personally would set > org-buffers-follow-link-method to 'current-window but then it would > be nice to have SPC, say, open the buffer in another window, to > behave consistently with org-agenda? I've added the SPACE binding you suggest. And, although it would be out-of-keeping with other org-mode links, it looks like there's a good argument for making RET switch to the buffer in the same window, like dired et al. I've done that. I've put a table at the end comparing these bindings across a few different major modes. > - I would prefer some consistency or symmetry in the creation and > burying of the buffer: given that (by default) org-buffers-list > brings up a new window in the current frame, quitting that buffer > should also delete the window; otherwise, I would like it to not > split the frame. Does that make sense? Yes. This is all to do with pop-to-buffer versus switch-to-buffer, my understanding of which was shaky. I have now changed to using switch-to-buffer by default, and I think this gives behaviour consistent with what you requested. I've also introduced a variable org-buffers-switch-to-buffer-function which can be set to 'pop-to-buffer, in which case the variables pop-up-windows and pop-up-frames, amongst others, become relevant. > - what's the point of orb-buffers-toggle-heading? Cleaner (less starry) appearance, seeing as many buffers are named *Like This*. > I ask because I > don't understand what functionality it adds and the default binding > (h) conflicts with my speed keys (I use vi-like bindings for speed > motion keys). I overlooked that before. I've moved it to H. > - In column view mode (which I also have not figured out why it would > be used...), the heading uses a different font size than the normal > entries so the headings don't line up at all. This may be my fault, > however. I don't see this. I've changed the column view binding to T ("tabular") so that the standard speed commands c and C are available. As for the point, it kind of comes full circle to the list-buffers / ibuffers appearance, thus showing that most things are a subset of org. > - if I bring up the buffers list a second time, having created a new > buffer in the meantime, the new buffer does not appear until I hit > 'g'. I think any invocation of org-buffers-list should do an > automatic update of the list. A C-u prefix to org-buffers-list now forces update. I don't think I agree that it should be default. Speed is my concern -- I'd like it to show the listing immediately when possible. I believe we're both using "atom"-powered netbooks, and mine at least is a little sluggish at generating the listing. I notice dired says "The directory has changed on disk, use g to update" so maybe I could do the same. > > - Lastly, it would be nice to either avoid the single blank line at > the start of the buffer or have point be at the first heading. > Having point at the first (empty) line seems to cause some problems > with speed motion keys sometimes... it also wastes a line! I've made point go to the first heading when the listing is created. However, I am wary about getting rid of that initial line, as I believe Carsten has said that Org/outline.el isn't always happy with first heading on first line. Certainly, I'm not inserting that newline character explicitly -- it appears via my (ab)use of Carsten's functions. > Actually, I think it might be useful to have point be placed at the > heading that corresponds to the buffer currently being visited when > the org-buffers-list command is invoked. A thought. Yes I like that and I've done it. It will only happen with a fresh listing though (first time, or C-u prefix), Otherwise buffer point is maintained. Along similar lines, I've made it so that if you invoke C-x f (find-file) or C-x d (dired), the minibuffer prompt will start from the directory of the buffer on the current line, rather than whatever directory is associated with the listings buffer. I've found this useful (only works for the keybindings currently, not for M-x or from menu). Also you can now flag buffers for reversion (i.e. revert-buffer) using "r"[6], and a few other changes. Thanks, your suggestions have been really helpful. Dan This table is with (setq pop-up-windows t), which is default in emacs23. --=-=-= Content-Type: multipart/alternative; boundary="==-=-=" --==-=-= | | switch | switch | display other-window | | | | same window | other window | without switch | next item | | | | (pop-to-buffer) | | | |--------------+--------------+-----------------+----------------------+-----------| | dired | RET | o | unavailable? | SPACE | | org links | unavailable? | RET | unavailable? [3] | | | org agenda | RET | TAB | SPACE [1] | | | magit log | unavailable? | RET | SPACE | | | gnus summary | unavailable? | unavailable? | RET, SPACE [2] | | | ibuffer | RET | o | C-o | SPACE | | list-buffers | RET | o | C-o | SPACE | |--------------+--------------+-----------------+----------------------+-----------| | org-buffers | RET | [5] | SPACE[4] | | [1] scrolls but does not advance to next automatically [2] scrolls and space advances to next entry on reaching end; RET doesn't advance [3] for org-mode links, SPACE could be bound to display-in-other-window-without-switching-and-scroll (?) [4] scrolls and advances [5] Customize variable org-buffers-switch-to-buffer-function, or bind function org-buffers-switch-to-buffer-other-window. --==-=-= Content-Type: text/html
switchswitchdisplay other-window
same windowother windowwithout switchnext item
(pop-to-buffer)
diredRETounavailable?SPACE
org linksunavailable?RETunavailable? 1
org agendaRETTABSPACE 2
magit logunavailable?RETSPACE
gnus summaryunavailable?unavailable?RET, SPACE 3
ibufferREToC-oSPACE
list-buffersREToC-oSPACE
org-buffersRET4SPACE5

Footnotes:

1 for org-mode links, SPACE could be bound to
display-in-other-window-without-switching-and-scroll (?)

2 scrolls but does not advance to next automatically

3 scrolls and space advances to next entry on reaching end; RET doesn't advance

4 Customize variable org-buffers-switch-to-buffer-function, or bind
function org-buffers-switch-to-buffer-other-window.

5 scrolls and advances

--==-=-=-- --=-=-= [6] Helpful if you switch branches in version control. --=-=-= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Emacs-orgmode mailing list Please use `Reply All' to send replies to the list. Emacs-orgmode@gnu.org http://lists.gnu.org/mailman/listinfo/emacs-orgmode --=-=-=-- From mboxrd@z Thu Jan 1 00:00:00 1970 From: Eric S Fraga Subject: Re: Using Org for browsing and managing buffers Date: Mon, 19 Apr 2010 09:27:12 +0100 Message-ID: <87hbn7etjz.wl%ucecesf@ucl.ac.uk> References: <87aatda0gv.fsf@stats.ox.ac.uk> <87d3y1pyuz.wl%ucecesf@ucl.ac.uk> <87mxx5cpo0.fsf@stats.ox.ac.uk> <87tyrcnc2c.wl%ucecesf@ucl.ac.uk> <87bpdghznk.fsf@stats.ox.ac.uk> Reply-To: e.fraga@ucl.ac.uk Mime-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset=US-ASCII Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O3mv6-0002lC-Jc for emacs-orgmode@gnu.org; Mon, 19 Apr 2010 05:05:32 -0400 Received: from [140.186.70.92] (port=46514 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O3mv4-0002k6-OC for emacs-orgmode@gnu.org; Mon, 19 Apr 2010 05:05:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O3muy-0007ON-Hr for emacs-orgmode@gnu.org; Mon, 19 Apr 2010 05:05:28 -0400 Received: from vscane-b.ucl.ac.uk ([144.82.108.141]:49638) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O3muy-0007O5-8U for emacs-orgmode@gnu.org; Mon, 19 Apr 2010 05:05:24 -0400 In-Reply-To: <87bpdghznk.fsf@stats.ox.ac.uk> List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: Dan Davison Cc: emacs org-mode mailing list On Sun, 18 Apr 2010 23:47:11 -0400, Dan Davison wrote: > > Hi Eric, > > Eric S Fraga writes: > [...] > > - I like the fact I can customise RET or, more to the point, that it > > be consistent with the rest of org-mode. I personally would set > > org-buffers-follow-link-method to 'current-window but then it would > > be nice to have SPC, say, open the buffer in another window, to > > behave consistently with org-agenda? > > I've added the SPACE binding you suggest. And, although it would be > out-of-keeping with other org-mode links, it looks like there's a good > argument for making RET switch to the buffer in the same window, like > dired et al. I've done that. I've put a table at the end comparing > these bindings across a few different major modes. Very nice summary! Shows that there is significant inconsistency in behaviour across typical/popular emacs modes. Probably too late to increase that consistency overall but I like the choices you have made for org-buffers. > > - what's the point of orb-buffers-toggle-heading? > > Cleaner (less starry) appearance, seeing as many buffers are named > *Like This*. Ah, true! On this topic, one suggestion (which might be difficult to implement, however): the best thing is about org is the hierarchical nature of headlines. This would seem to map well to the hierarchical nature of modes. For instance, org mode is also a text mode. Would it make sense to have all text mode buffers grouped with sub-modes (for want of a better word) as subheadings? On the other hand, I'm not sure what this would add so probably ignore this... :-) > > I ask because I > > don't understand what functionality it adds and the default binding > > (h) conflicts with my speed keys (I use vi-like bindings for speed > > motion keys). > > I overlooked that before. I've moved it to H. Doesn't seem to work for me (pulled from git this morning, 8am BST): ,---- | Debugger entered--Lisp error: (wrong-type-argument integer-or-marker-p nil) | delete-region(nil nil) | (lambda (pair) (delete-region (car pair) (cdr pair)))(nil) | mapc((lambda (pair) (delete-region (car pair) (cdr pair))) (nil nil (4614 . 4748) nil (4407 . 4572) nil (4204 . 4360) nil (3953 . 4169) (3695 . 3911) (3441 . 3653) (3193 . 3403) (2947 . 3157) (2693 . 2911) (2441 . 2649) (2197 . 2405) (1953 . 2163) nil (1767 . 1911) nil (1561 . 1712) nil (1300 . 1524) (1131 . 1270) (942 . 1091) (734 . 884) (555 . 696) nil (260 . 499) nil (50 . 201) nil)) | org-buffers-delete-regions((nil nil (4614 . 4748) nil (4407 . 4572) nil (4204 . 4360) nil (3953 . 4169) (3695 . 3911) (3441 . 3653) (3193 . 3403) (2947 . 3157) (2693 . 2911) (2441 . 2649) (2197 . 2405) (1953 . 2163) nil (1767 . 1911) nil (1561 . 1712) nil (1300 . 1524) (1131 . 1270) (942 . 1091) (734 . 884) (555 . 696) nil (260 . 499) nil (50 . 201) nil)) | (save-excursion (goto-char (point-min)) (org-buffers-delete-regions (nreverse ...))) | (let ((inhibit-read-only t)) (save-excursion (goto-char ...) (org-buffers-delete-regions ...))) | org-buffers-delete-properties() | (progn (org-buffers-delete-properties) (show-all) (org-buffers-set-state (quote ...))) | (if (org-buffers-state-get :properties) (progn (org-buffers-delete-properties) (show-all) (org-buffers-set-state ...)) (org-buffers-set-state (quote ...)) (org-buffers-list (quote refresh))) | org-buffers-toggle-properties() | (if (and headings-p (org-buffers-state-get :properties)) (org-buffers-toggle-properties)) | (let ((inhibit-read-only t) (headings-p ...) (flat-p ...)) (if (and headings-p ...) (org-buffers-toggle-properties)) (save-excursion (goto-char ...) (if ... ...) (if flat-p ... ...) (mark-whole-buffer) (indent-region ... ...)) (org-buffers-set-state (\` ...))) | org-buffers-toggle-headings() | call-interactively(org-buffers-toggle-headings nil nil) `---- > > - In column view mode (which I also have not figured out why it would > > be used...), the heading uses a different font size than the normal > > entries so the headings don't line up at all. This may be my fault, > > however. > > I don't see this. doesn't seem to happen to me now. I may have imagined it... > > - if I bring up the buffers list a second time, having created a new > > buffer in the meantime, the new buffer does not appear until I hit > > 'g'. I think any invocation of org-buffers-list should do an > > automatic update of the list. > > A C-u prefix to org-buffers-list now forces update. I don't think I > agree that it should be default. Speed is my concern -- I'd like it Okay. I understand the motivation. It comes down to the difference in behaviour between the default buffers listing approach in emacs and the way dired works. As long as I remember that it's more like dired, I'm happy! > > - Lastly, it would be nice to either avoid the single blank line at > > the start of the buffer or have point be at the first heading. > > Having point at the first (empty) line seems to cause some problems > > with speed motion keys sometimes... it also wastes a line! > > I've made point go to the first heading when the listing is > created. However, I am wary about getting rid of that initial line, as I > believe Carsten has said that Org/outline.el isn't always happy with > first heading on first line. Certainly, I'm not inserting that newline > character explicitly -- it appears via my (ab)use of Carsten's > functions. Okay. > > Actually, I think it might be useful to have point be placed at the > > heading that corresponds to the buffer currently being visited when > > the org-buffers-list command is invoked. A thought. > > Yes I like that and I've done it. It will only happen with a fresh > listing though (first time, or C-u prefix), Otherwise buffer point is > maintained. Okay, again like dired as opposed to list-buffers. Fine. > Along similar lines, I've made it so that if you invoke C-x f > (find-file) or C-x d (dired), the minibuffer prompt will start from the > directory of the buffer on the current line, rather than whatever > directory is associated with the listings buffer. I've found this useful > (only works for the keybindings currently, not for M-x or from > menu). This sounds very reasonable. > Also you can now flag buffers for reversion (i.e. revert-buffer) using > "r"[6], and a few other changes. I have auto-revert-mode set on most buffers so this is not of great use to me but I can see it being useful to others. > Thanks, your suggestions have been really helpful. You're very welcome! Suggestions are easy; implementation is the tricky bit. :-) From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dan Davison Subject: Re: Using Org for browsing and managing buffers Date: Mon, 19 Apr 2010 09:18:41 -0400 Message-ID: <87633noa1a.fsf@stats.ox.ac.uk> References: <87aatda0gv.fsf@stats.ox.ac.uk> <87d3y1pyuz.wl%ucecesf@ucl.ac.uk> <87mxx5cpo0.fsf@stats.ox.ac.uk> <87tyrcnc2c.wl%ucecesf@ucl.ac.uk> <87bpdghznk.fsf@stats.ox.ac.uk> <87hbn7etjz.wl%ucecesf@ucl.ac.uk> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O3qtx-0001rb-Ct for emacs-orgmode@gnu.org; Mon, 19 Apr 2010 09:20:37 -0400 Received: from [140.186.70.92] (port=33003 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O3qtn-0001oA-W2 for emacs-orgmode@gnu.org; Mon, 19 Apr 2010 09:20:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O3qs9-0005Co-Kd for emacs-orgmode@gnu.org; Mon, 19 Apr 2010 09:18:47 -0400 Received: from markov.stats.ox.ac.uk ([163.1.210.1]:36933) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O3qs9-0005CD-DD for emacs-orgmode@gnu.org; Mon, 19 Apr 2010 09:18:45 -0400 In-Reply-To: <87hbn7etjz.wl%ucecesf@ucl.ac.uk> (Eric S. Fraga's message of "Mon, 19 Apr 2010 09:27:12 +0100") List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: e.fraga@ucl.ac.uk Cc: emacs org-mode mailing list > On this topic, one suggestion (which might be difficult to implement, > however): the best thing is about org is the hierarchical nature of > headlines. This would seem to map well to the hierarchical nature of > modes. For instance, org mode is also a text mode. Would it make > sense to have all text mode buffers grouped with sub-modes (for want > of a better word) as subheadings? On the other hand, I'm not sure > what this would add so probably ignore this... :-) Other groupings might be good too. E.g. the comint process buffer for a language grouped with the code files; all magit buffers in a magit tree; all gnus buffers (summary, group, article) in a gnus tree. It seems that the best thing might be to have a flexible way of specifying the tree structure. E.g some way to specify "projects" for which all buffers should be grouped together. Not sure how to implement that though. I've also been wondering about adding recentf files (buffers you might want, in addition to buffers you have). Then it might make sense to present them in a hierarchy based on the filesystem location. That's also true when grouping buffers by their directory (B def RET). So making it work with > 2 levels of hierarchy is definitely something worth thinking about, especially if someone has a good idea how to specify the desired tree structure a priori. A year or two ago someone posted code to preserve folding state of an org buffer using an auxiliary file. Don't think it's in contrib. But I might try to dig that out also. Anyone know where it is? > >> > I ask because I >> > don't understand what functionality it adds and the default binding >> > (h) conflicts with my speed keys (I use vi-like bindings for speed >> > motion keys). >> >> I overlooked that before. I've moved it to H. > > Doesn't seem to work for me (pulled from git this morning, 8am BST): Fixed, thanks! Dan