| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 | ;;; org-indent.el --- Dynamic indentation for  Org-mode;; Copyright (C) 2008 Free Software Foundation, Inc.;;;; Author: Carsten Dominik <carsten at orgmode dot org>;; Keywords: outlines, hypermedia, calendar, wp;; Homepage: http://orgmode.org;; Version: 0.07;;;; This file is not part of GNU Emacs.;;;; This file 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.;; GNU Emacs 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:;; This is an experimental implementation of dynamic virtual indentation.;; It works by adding overlays to a buffer to make sure lines are;; indented according to outline structure.  While this works, there are;; problems with the implementation:  It uses overlays, which use markers,;; and for large files, this is using too much resources.  It might be;; possible to com up with an implementation using text properties,;; I believe this is less resource intensive.  However, it does not work;; to put the text property onto the newline, because that interferes with;; outline visibility.  Maybe this is a bug in outline?;;; Indentation(defcustom org-startup-indented nil  "Non-nil means, turn on `org-indent-mode' on startup.This can also be configured on a per-file basis by adding one ofthe following lines anywhere in the buffer:   #+STARTUP: localindent   #+STARTUP: indent   #+STARTUP: noindent"  :group 'org-structure  :type '(choice	  (const :tag "Not" nil)	  (const :tag "Locally" local)	  (const :tag "Globally (slow on startup in large files)" t)))(defconst org-indent-max 80  "Maximum indentation in characters")(defconst org-indent-strings nil  "Vector with all indentation strings.It is a const because it will be set only once in `org-indent-initialize'.")(defvar org-indent-inhibit-after-change nil  "Inhibit the action of the indentation after-change-hook.This variable should be scoped dynamically.")(defcustom org-indent-boundary-char ?\   ; comment to protect space char  "The end of the virtual indentation strings, a single-character string.The default is just a space, but if you wish, you can use \"|\" or so."  :group 'org-structure  :set (lambda (var val)	 (set var val)	 (and org-indent-strings (org-indent-initialize)))  :type 'character)(defun org-indent-initialize ()  "Initialize the indentation strings and set the idle times."  (unless org-indent-strings;    (run-with-idle-timer 10   t 'org-indent-indent-buffer)    (run-with-idle-timer  0.5  t 'org-indent-refresh-section)    )  (setq org-indent-strings (make-vector (1+ org-indent-max) nil))  ;; Initialize the indentation strings  (aset org-indent-strings 0 "")  (loop for i from 1 to org-indent-max do	(aset org-indent-strings i	      (org-add-props 		  (concat (make-string (1- i) ?\ )			  (char-to-string org-indent-boundary-char))		  nil 'face 'org-indent))))(define-minor-mode org-indent-mode  "Toggle the minor more `org-indent-mode'."  nil " Ind" nil  (if (org-bound-and-true-p org-inhibit-startup)      (setq org-indent-mode nil)    (if org-indent-mode	(progn	  (or org-indent-strings (org-indent-initialize))	  (org-set-local 'org-adapt-indentation nil)	  (org-add-hook 'after-change-functions			'org-indent-after-change-function nil t)	  (org-restart-font-lock)	  (org-indent-indent-buffer))      (save-excursion	(save-restriction	  (org-indent-remove-overlays (point-min) (point-max))	  (remove-hook 'after-change-functions		       'org-indent-after-change-function 'local)	  (kill-local-variable 'org-adapt-indentation))))))(defface org-indent  (org-compatible-face nil    '((((class color) (min-colors 16) (background dark)	(:underline nil :strike-through nil :foreground "grey10")))      (((class color) (min-colors 16) (background light))       (:underline nil :strike-through nil :foreground "grey90"))      (t (:underline nil :strike-through nil))))  "Face for outline indentation.The default is to make it look like whitespace.  But you may find ituseful to make it, for example, look like the fringes."  :group 'org-faces)(defun org-indent-indent-buffer ()  "Add indentation overlays for the whole buffer."  (interactive)  (when org-indent-mode    (save-excursion      (save-restriction	(org-indent-remove-overlays (point-min) (point-max))	(org-indent-add-overlays (point-min) (point-max))))))(defun org-indent-remove-overlays (beg end)  "Remove indentations between BEG and END."  (mapc (lambda (o)	  (and (org-overlay-get o 'org-indent)	       (org-delete-overlay o)))	(org-overlays-in beg end)))(defun org-indent-add-overlays (beg end &optional n)  "Add indentation overlays between BEG and END.Assumes that BEG is at the beginning of a line."  (when org-indent-mode    (let (o)      (save-excursion	(goto-char beg)	(while (and (<= (point) end) (not (eobp)))	  (cond	   ((not (bolp)))	   ((looking-at outline-regexp)	    (setq n (- (match-end 0) (match-beginning 0)))	    (org-indent-remove-overlays (max (point-min) (1- (point))) (point)))	   (n	    (org-indent-indent-line n)))	  (beginning-of-line 2))))))(defun org-indent-indent-line (n)  "Add an indentation overlay with width N to the current line.Point is assumed to be at the beginning of the line for this."  (let (ov)    (setq ov (org-make-overlay (1- (point)) (point)))    (org-overlay-put ov 'after-string (aref org-indent-strings n))    (org-overlay-put ov 'evaporate t)    (org-overlay-put ov 'org-indent n)    (org-unmodified     (put-text-property (max (point-min) (1- (point)))			(point-at-eol) 'org-indent-level n))))(defun org-indent-after-change-function (beg end ndel)  (if (or (not org-indent-mode) (= beg end)	  org-indent-inhibit-after-change)      () ; not in the mood to do anything here....    (let ((inhibit-quit t) n)      (save-match-data	(save-excursion	  (save-restriction	    (widen)	    (goto-char beg)	    (when (search-forward "\n" end t)	      ;; a newline was inserted	      (setq n (or (get-text-property beg 'org-indent-level)			  (get-text-property			   (or (save-excursion (previous-single-property-change						beg 'org-indent-level))			       (point-min))			   'org-indent-level)			  0))	      (org-indent-local-refresh beg end n))))))))(defun org-indent-local-refresh (beg end n)  "Refresh indentation locally from BEG to END, starting with indentation N."  (goto-char end)  (setq end (min (point-max) (1+ (point-at-eol))))  (goto-char beg)  (beginning-of-line 0)  (org-indent-remove-overlays (max (point-min) (1- (point))) end)  (org-indent-add-overlays (point) end n))(defun org-indent-refresh-section ()  "Refresh indentation overlays in the current outline subtree."  (when org-indent-mode    (save-excursion      (let ((org-indent-inhibit-after-change t)	    beg end)	(condition-case nil	    (progn	      (outline-back-to-heading t)	      (setq beg (point)))	  (error (progn		   (goto-char (point-min))		   (setq beg (point)))))	(outline-next-heading)	(setq end (point))	(org-indent-remove-overlays beg end)	(org-indent-add-overlays beg end)))))(defun org-indent-refresh-subtree ()  "Refresh indentation overlays in the current outline subtree."  (when org-indent-mode    (save-excursion      (let ((org-indent-inhibit-after-change t)	    beg end)	(setq beg (point))	(setq end (save-excursion (org-end-of-subtree t t)))	(org-indent-remove-overlays beg end)	(org-indent-add-overlays beg end)))))(provide 'org-indent);;; org-indent.el ends here
 |