summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Dominik <carsten.dominik@gmail.com>2009-06-30 07:24:57 +0200
committerCarsten Dominik <carsten.dominik@gmail.com>2009-08-03 06:24:24 +0200
commit31ceed47ffd3070418dd34316fef8869d2434c26 (patch)
tree1eb1e3537f52ab47304e2272a5db8151b3e63c06
parent7cb52cfb7ed8493b44ad749d5d6888ade8115fe8 (diff)
downloadorg-mode-31ceed47ffd3070418dd34316fef8869d2434c26.tar.gz
New minor mode org-indent-mode
This mode implements outline indentation similar to clean view, but in a dynamic and virtual way, at display time.
-rw-r--r--ChangeLog6
-rw-r--r--Makefile2
-rwxr-xr-xUTILITIES/mansplit.pl5
-rw-r--r--contrib/ChangeLog4
-rw-r--r--contrib/lisp/org-indent.el226
-rw-r--r--doc/ChangeLog4
-rw-r--r--doc/org.texi90
-rwxr-xr-xlisp/ChangeLog22
-rw-r--r--lisp/org-agenda.el1
-rw-r--r--lisp/org-compat.el5
-rw-r--r--lisp/org-exp.el2
-rw-r--r--lisp/org-id.el2
-rw-r--r--lisp/org-indent.el273
-rw-r--r--lisp/org-mouse.el2
-rw-r--r--lisp/org-table.el10
-rw-r--r--lisp/org-w3m.el2
-rw-r--r--lisp/org.el49
17 files changed, 436 insertions, 269 deletions
diff --git a/ChangeLog b/ChangeLog
index 00d4f65..dd70384 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2009-08-03 Carsten Dominik <carsten.dominik@gmail.com>
+
+ * UTILITIES/mansplit.pl: Fix short contents.
+
+ * Makefile (LISPF): Add org-indent.el.
+
2009-07-07 Tassilo Horn <tassilo@member.fsf.org>
* org-gnus.el (org-gnus-store-link): Skip mbox specific first line
diff --git a/Makefile b/Makefile
index 6971f9e..2093f29 100644
--- a/Makefile
+++ b/Makefile
@@ -79,6 +79,7 @@ LISPF = org.el \
org-html.el \
org-icalendar.el \
org-id.el \
+ org-indent.el \
org-info.el \
org-inlinetask.el \
org-jsinfo.el \
@@ -349,6 +350,7 @@ lisp/org-gnus.elc: lisp/org.el
lisp/org-html.elc: lisp/org-exp.el
lisp/org-icalendar.elc: lisp/org-exp.el
lisp/org-id.elc: lisp/org.el
+lisp/org-indent.elc: lisp/org.el lisp/org-macs.el lisp/org-compat.el
lisp/org-info.elc: lisp/org.el
lisp/org-inlinetask.elc:
lisp/org-irc.elc: lisp/org.el
diff --git a/UTILITIES/mansplit.pl b/UTILITIES/mansplit.pl
index 49ea848..f459ea4 100755
--- a/UTILITIES/mansplit.pl
+++ b/UTILITIES/mansplit.pl
@@ -28,9 +28,8 @@ $contents = <<EOF;
<li><a name="toc_Exporting" href="Exporting.html#Exporting">12 Exporting</a>
<li><a name="toc_Publishing" href="Publishing.html#Publishing">13 Publishing</a>
<li><a name="toc_Miscellaneous" href="Miscellaneous.html#Miscellaneous">14 Miscellaneous</a>
-<li><a name="toc_Extensions" href="Extensions.html#Extensions">A Extensions</a>
-<li><a name="toc_Hacking" href="Hacking.html#Hacking">B Hacking</a>
-<li><a name="toc_History-and-Acknowledgments" href="History-and-Acknowledgments.html#History-and-Acknowledgments">C History and Acknowledgments</a>
+<li><a name="toc_Hacking" href="Hacking.html#Hacking">A Hacking</a>
+<li><a name="toc_History-and-Acknowledgments" href="History-and-Acknowledgments.html#History-and-Acknowledgments">B History and Acknowledgments</a>
<li><a name="toc_Main-Index" href="Main-Index.html#Main-Index">Main Index</a>
<li><a name="toc_Key-Index" href="Key-Index.html#Key-Index">Key Index</a>
</li></ul>
diff --git a/contrib/ChangeLog b/contrib/ChangeLog
index dd79560..4f4e050 100644
--- a/contrib/ChangeLog
+++ b/contrib/ChangeLog
@@ -1,3 +1,7 @@
+2009-08-03 Carsten Dominik <carsten.dominik@gmail.com>
+
+ * lisp/org-indent.el: File removed.
+
2009-07-21 Wes Hardaker <wjhns209@hardakers.net> (tiny change)
* lisp/org-export-generic.el (org-export-generic-format): Fix
diff --git a/contrib/lisp/org-indent.el b/contrib/lisp/org-indent.el
deleted file mode 100644
index b50b113..0000000
--- a/contrib/lisp/org-indent.el
+++ /dev/null
@@ -1,226 +0,0 @@
-;;; 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 of
-the 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 it
-useful 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
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 00bd23e..3ebda99 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,7 @@
+2009-08-03 Carsten Dominik <carsten.dominik@gmail.com>
+
+ * org.texi (Clean view): Document `org-indent-mode'.
+
2009-07-26 Bastien Guerry <bzg@altern.org>
* org.texi (Clocking work time): Add documentation for the
diff --git a/doc/org.texi b/doc/org.texi
index edf6b64..0e5fd96 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -871,6 +871,10 @@ the previously used indirect buffer.
@end table
@vindex org-startup-folded
+@cindex @code{overview}, STARTUP keyword
+@cindex @code{content}, STARTUP keyword
+@cindex @code{showall}, STARTUP keyword
+
When Emacs first visits an Org file, the global state is set to
OVERVIEW, @ie only the top level headlines are visible. This can be
configured through the variable @code{org-startup-folded}, or on a
@@ -10054,12 +10058,14 @@ any other Org mode file with internal setup. You can visit the file the
cursor is in the line with @kbd{C-c '}.
@item #+STARTUP:
@cindex #+STARTUP:
-@vindex org-startup-folded
This line sets options to be used at startup of Org mode, when an
-Org file is being visited. The first set of options deals with the
-initial visibility of the outline tree. The corresponding variable for
-global default settings is @code{org-startup-folded}, with a default
-value @code{t}, which means @code{overview}.
+Org file is being visited.
+
+The first set of options deals with the initial visibility of the outline
+tree. The corresponding variable for global default settings is
+@code{org-startup-folded}, with a default value @code{t}, which means
+@code{overview}.
+@vindex org-startup-folded
@cindex @code{overview}, STARTUP keyword
@cindex @code{content}, STARTUP keyword
@cindex @code{showall}, STARTUP keyword
@@ -10068,6 +10074,17 @@ overview @r{top-level headlines only}
content @r{all headlines}
showall @r{no folding at all, show everything}
@end example
+
+@vindex org-startup-indented
+@cindex @code{indent}, STARTUP keyword
+@cindex @code{noindent}, STARTUP keyword
+Dynamic virtual indentation is controlled by the variable
+@code{org-startup-indented}@footnote{Emacs 23 and Org-mode 6.29 are required}
+@example
+indent @r{start with @code{org-indent-mode} turned on}
+noindent @r{start with @code{org-indent-mode} turned off}
+@end example
+
@vindex org-startup-align-all-tables
Then there are options for aligning tables upon visiting a file. This
is useful in files containing narrowed table columns. The corresponding
@@ -10254,13 +10271,11 @@ block is updated.
@cindex odd-levels-only outlines
@cindex clean outline view
-Some people find it noisy and distracting that the Org headlines start
-with a potentially large number of stars, and that text below the headlines
-is not indented. This is not really a problem when you are writing a book
-where the outline headings are really section headlines. However, in a more
-list-oriented outline, it is clear that an indented structure is a lot
-cleaner, as can be seen by comparing the two columns in the following
-example:
+Some people find it noisy and distracting that the Org headlines start with a
+potentially large number of stars, and that text below the headlines is not
+indented. While this is no problem when writing a book where the outline
+headings are really section headlines, in a more list-oriented outline,
+indented structure is a lot cleaner:
@example
@group
@@ -10275,8 +10290,28 @@ more text | more text
@end example
@noindent
-It is non-trivial to make such a look work in Emacs, but Org contains three
-separate features that, combined, achieve just that.
+If you are using Emacs 23 and at least version 6.29 of Org, this kind of view
+can be achieved dynamically at display time using @code{org-indent-mode}. In
+this minor mode, all lines are prefixed for display with the necessary amount
+of space. Also headlines are prefixed with additional stars, so that the
+amount of indentation shifts by two@footnote{See the variable
+@code{org-indent-indentation-per-level}.} spaces per level. All headline
+stars but the last one are made invisible using the @code{org-hide}
+face@footnote{Turning on @code{org-indent-mode} sets
+@code{org-hide-leading-stars} to @code{t} and @code{org-adapt-indentation} to
+@code{nil}.} - see below under @samp{2.} for more information on how this
+works. You can turn on @code{org-indent-mode} for all files by customizing
+the variable @code{org-startup-indented}, or you can turn it on for
+individual files using
+
+@example
+#+STARTUP: indent
+@end example
+
+If you want a similar effect in earlier version of Emacs and/or Org, or if
+you want the indentation to be hard space characters so that the plain text
+file looks as similar as possible to the Emacs display, Org supports you in
+the following way:
@enumerate
@item
@@ -10290,13 +10325,9 @@ with the headline, like
@end example
@vindex org-adapt-indentation
-A good way to get this indentation is by hand, and Org supports this with
-paragraph filling, line wrapping, and structure editing@footnote{See also the
-variable @code{org-adapt-indentation}.} preserving or adapting the
-indentation as appropriate. A different approach would be to have a way to
-automatically indent lines according to outline structure by adding overlays
-or text properties. But I have not yet found a robust and efficient way to
-do this in large files.
+Org supports this with paragraph filling, line wrapping, and structure
+editing@footnote{See also the variable @code{org-adapt-indentation}.},
+preserving or adapting the indentation as appropriate.
@item
@vindex org-hide-leading-stars
@@ -10307,11 +10338,9 @@ with
@example
#+STARTUP: hidestars
+#+STARTUP: showstars
@end example
-@noindent
-Note that the opposite behavior is selected with @code{showstars}.
-
With hidden stars, the tree becomes:
@example
@@ -10325,13 +10354,12 @@ With hidden stars, the tree becomes:
@noindent
@vindex org-hide @r{(face)}
-Note that the leading stars are not truly replaced by whitespace, they
-are only fontified with the face @code{org-hide} that uses the
-background color as font color. If you are not using either white or
-black background, you may have to customize this face to get the wanted
-effect. Another possibility is to set this font such that the extra
-stars are @i{almost} invisible, for example using the color
-@code{grey90} on a white background.
+The leading stars are not truly replaced by whitespace, they are only
+fontified with the face @code{org-hide} that uses the background color as
+font color. If you are not using either white or black background, you may
+have to customize this face to get the wanted effect. Another possibility is
+to set this font such that the extra stars are @i{almost} invisible, for
+example using the color @code{grey90} on a white background.
@item
@vindex org-odd-levels-only
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 7a28106..7002522 100755
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,25 @@
+2009-08-03 Carsten Dominik <carsten.dominik@gmail.com>
+
+ * org.el (org-startup-indented): New option.
+ (org-startup-options): Add new options indent and noindent.
+ (org-unfontify-region): Remove line-prefix and wrap-prefix
+ properties.
+ (org-after-demote-entry-hook, org-after-promote-entry-hook): New
+ hooks.
+ (org-promote, org-demote): Run the new hooks.
+
+ * org-table.el (org-table-align): Replace leading \n as well.
+
+ * org-exp.el (org-export-push-to-kill-ring): Remove `line-prefix'
+ and `line-wrap' text properties.
+
+ * org-compat.el (org-kill-new): New function.
+
+ * org-agenda.el (org-format-agenda-item): Remove `line-prefix' and
+ `line-wrap' text properties.
+
+ * org-indent.el: New file.
+
2009-08-02 Carsten Dominik <carsten.dominik@gmail.com>
* org.el (org-provide-todo-statistics): Tweak docstring.
diff --git a/lisp/org-agenda.el b/lisp/org-agenda.el
index 5c56e0a..6e26e1c 100644
--- a/lisp/org-agenda.el
+++ b/lisp/org-agenda.el
@@ -4292,6 +4292,7 @@ Any match of REMOVE-RE will be removed from TXT."
(setq rtn (concat (eval org-prefix-format-compiled) txt)))
;; And finally add the text properties
+ (remove-text-properties 0 (length rtn) '(line-prefix t wrap-prefix t) rtn)
(org-add-props rtn nil
'org-category (downcase category)
'tags (mapcar 'org-downcase-keep-props tags)
diff --git a/lisp/org-compat.el b/lisp/org-compat.el
index c76ffed..8f4613d 100644
--- a/lisp/org-compat.el
+++ b/lisp/org-compat.el
@@ -327,6 +327,11 @@ that can be added."
(setq n (1- n)))
n))
+(defun org-kill-new (string &rest args)
+ (remove-text-properties 0 (length string) '(line-prefix t wrap-prefix t)
+ string)
+ (apply 'kill-new string args))
+
(provide 'org-compat)
;; arch-tag: a0a0579f-e68c-4bdf-9e55-93768b846bbe
diff --git a/lisp/org-exp.el b/lisp/org-exp.el
index f87da2c..85256db 100644
--- a/lisp/org-exp.el
+++ b/lisp/org-exp.el
@@ -2778,7 +2778,7 @@ stacked delimiters is N. Escaping delimiters is not possible."
"Push buffer content to kill ring.
The depends on the variable `org-export-copy-to-kill'."
(when org-export-copy-to-kill-ring
- (kill-new (buffer-string))
+ (org-kill-new (buffer-string))
(when (fboundp 'x-set-selection)
(ignore-errors (x-set-selection 'PRIMARY (buffer-string)))
(ignore-errors (x-set-selection 'CLIPBOARD (buffer-string))))
diff --git a/lisp/org-id.el b/lisp/org-id.el
index 4fe6e60..baf69f0 100644
--- a/lisp/org-id.el
+++ b/lisp/org-id.el
@@ -202,7 +202,7 @@ With optional argument FORCE, force the creation of a new ID."
"Copy the ID of the entry at point to the kill ring.
Create an ID if necessary."
(interactive)
- (kill-new (org-id-get nil 'create)))
+ (org-kill-new (org-id-get nil 'create)))
;;;###autoload
(defun org-id-get (&optional pom create prefix)
diff --git a/lisp/org-indent.el b/lisp/org-indent.el
new file mode 100644
index 0000000..caeb65d
--- /dev/null
+++ b/lisp/org-indent.el
@@ -0,0 +1,273 @@
+;;; 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: 6.28trans
+;;
+;; This file is 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 implementation of dynamic virtual indentation. It works
+;; by adding text properties to a buffer to make sure lines are
+;; indented according to outline structure.
+
+(require 'org-macs)
+(require 'org-compat)
+(require 'org)
+(eval-when-compile
+ (require 'cl))
+
+
+(defgroup org-indent nil
+ "Options concerning dynamic virtual outline indentation."
+ :tag "Org Structure"
+ :group 'org)
+
+(defconst org-indent-max 40
+ "Maximum indentation in characters")
+(defconst org-indent-max-levels 40
+ "Maximum indentation in characters")
+
+(defvar org-indent-strings nil
+ "Vector with all indentation strings.
+It will be set in `org-indent-initialize'.")
+(defvar org-indent-stars nil
+ "Vector with all indentation star strings.
+It will be set in `org-indent-initialize'.")
+
+(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.
+This can be useful on a terminal window - under a windowing system,
+it may be prettier to customize the org-indent face."
+ :group 'org-indent
+ :set (lambda (var val)
+ (set var val)
+ (and org-indent-strings (org-indent-initialize)))
+ :type 'character)
+
+(defcustom org-indent-mode-turns-off-org-adapt-indentation t
+ "Non-nil means, turning on org-indent-mode turns off indentation adaptation.
+For details see the variable `org-adapt-indentation'."
+ :group 'org-indent
+ :type 'boolean)
+
+(defcustom org-indent-mode-turns-on-hiding-stars t
+ "Non-nil means, turning on org-indent-mode turns on `org-hide-leading-stars'."
+ :group 'org-indent
+ :type 'boolean)
+
+(defcustom org-indent-indentation-per-level 2
+ "Indentation per level in number of characters."
+ :group 'org-indent
+ :type 'integer)
+
+(defcustom org-indent-fix-section-after-idle-time 0.2
+ "Seconds of idle time before fixing virtual indentation of section.
+The hooking-in of virtual indentation is not yet perfect. Occasionally,
+a change does not trigger to proper change of indentation. For this we
+have a timer action that fixes indentation in the current section after
+a short amount idle time. If we ever get the integration to work perfectly,
+this variable can be set to nil to get rid of the timer."
+ :group 'org-indent
+ :type '(choice
+ (const "Do not install idle timer" nil)
+ (number :tag "Idle time")))
+
+(defun org-indent-initialize ()
+ "Initialize the indentation strings and set the idle timer."
+ ;; We use an idle timer to "repair" the current section, because the
+ ;; redisplay seems to have some problems.
+ (unless org-indent-strings
+ (when org-indent-fix-section-after-idle-time
+ (run-with-idle-timer
+ org-indent-fix-section-after-idle-time
+ t 'org-indent-refresh-section)))
+ ;; Initialize the indentation and star vectors
+ (setq org-indent-strings (make-vector (1+ org-indent-max) nil))
+ (setq org-indent-stars (make-vector (1+ org-indent-max) nil))
+ (aset org-indent-strings 0 "")
+ (aset org-indent-stars 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)))
+ (loop for i from 1 to org-indent-max-levels do
+ (aset org-indent-stars i
+ (org-add-props (make-string i ?*)
+ nil 'face 'org-hide))))
+
+;;;###autoload
+(define-minor-mode org-indent-mode
+ "When active, indent text according to outline structure.
+
+Internally this works by adding `line-prefix' properties to all non-headlines.
+These properties are updated locally in idle time.
+FIXME: How to update when broken?"
+ 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))
+ (when org-indent-mode-turns-off-org-adapt-indentation
+ (org-set-local 'org-adapt-indentation nil))
+ (when org-indent-mode-turns-on-hiding-stars
+ (org-set-local 'org-hide-leading-stars t))
+ (make-local-variable 'buffer-substring-filters)
+ (add-to-list 'buffer-substring-filters
+ 'org-indent-remove-properties-from-string)
+ (org-add-hook 'org-after-demote-entry-hook
+ 'org-indent-refresh-section nil 'local)
+ (org-add-hook 'org-after-promote-entry-hook
+ 'org-indent-refresh-section nil 'local)
+ (org-add-hook 'org-font-lock-hook
+ 'org-indent-refresh-to nil 'local)
+ (and font-lock-mode (org-restart-font-lock))
+ )
+ (save-excursion
+ (save-restriction
+ (org-indent-remove-properties (point-min) (point-max))
+ (kill-local-variable 'org-adapt-indentation)
+ (setq buffer-substring-filters
+ (delq 'org-indent-remove-properties-from-string
+ buffer-substring-filters))
+ (remove-hook 'org-after-promote-entry-hook
+ 'org-indent-refresh-section 'local)
+ (remove-hook 'org-after-demote-entry-hook
+ 'org-indent-refresh-section 'local)
+ (and font-lock-mode (org-restart-font-lock))
+ (redraw-display))))))
+
+
+(defface org-indent
+ (org-compatible-face nil nil)
+ "Face for outline indentation.
+The default is to make it look like whitespace. But you may find it
+useful to make it evver so slightly different."
+ :group 'org-faces)
+
+(defun org-indent-indent-buffer ()
+ "Add indentation properties for the whole buffer."
+ (interactive)
+ (when org-indent-mode
+ (save-excursion
+ (save-restriction
+ (widen)
+ (org-indent-remove-properties (point-min) (point-max))
+ (org-indent-add-properties (point-min) (point-max))))))
+
+(defun org-indent-remove-properties (beg end)
+ "Remove indentations between BEG and END."
+ (org-unmodified
+ (remove-text-properties beg end '(line-prefix nil wrap-prefix nil))))
+
+(defun org-indent-remove-properties-from-string (string)
+ "Remove indentations between BEG and END."
+ (remove-text-properties 0 (length string)
+ '(line-prefix nil wrap-prefix nil) string)
+ string)
+
+(defun org-indent-add-properties (beg end)
+ "Add indentation properties between BEG and END.
+Assumes that BEG is at the beginning of a line."
+ (when (or t org-indent-mode)
+ (let (ov b e n level exit nstars)
+ (org-unmodified
+ (save-excursion
+ (goto-char beg)
+ (while (not exit)
+ (setq e end)
+ (if (not (re-search-forward org-outline-regexp nil t))
+ (setq e (point-max) exit t)
+ (setq e (match-beginning 0))
+ (if (>= e end) (setq exit t))
+ (setq level (- (match-end 0) (match-beginning 0) 1))
+ (setq nstars (- (* (1- level) org-indent-indentation-per-level)
+ (1- level)))
+ (add-text-properties
+ (point-at-bol) (point-at-eol)
+ (list 'line-prefix
+ (aref org-indent-stars nstars)
+ 'wrap-prefix
+ (aref org-indent-strings
+ (* level org-indent-indentation-per-level)))))
+ (when (and b (> e b))
+ (add-text-properties
+ b e (list 'line-prefix (aref org-indent-strings n)
+ 'wrap-prefix (aref org-indent-strings n))))
+ (setq b (1+ (point-at-eol))
+ n (* level org-indent-indentation-per-level))))))))
+
+(defun org-indent-refresh-section ()
+ "Refresh indentation properties in the current outline section.
+Point is assumed to be at the beginning of a headline."
+ (interactive)
+ (when org-indent-mode
+ (let (beg end)
+ (save-excursion
+ (when (ignore-errors (org-back-to-heading))
+ (setq beg (point))
+ (setq end (or (save-excursion (or (outline-next-heading) (point)))))
+ (org-indent-remove-properties beg end)
+ (org-indent-add-properties beg end))))))
+
+(defun org-indent-refresh-to (limit)
+ "Refresh indentation properties in the current outline section.
+Point is assumed to be at the beginning of a headline."
+ (interactive)
+ (when org-indent-mode
+ (let ((beg (point)) (end limit))
+ (save-excursion
+ (and (ignore-errors (org-back-to-heading t))
+ (setq beg (point))))
+ (org-indent-remove-properties beg end)
+ (org-indent-add-properties beg end)))
+ (goto-char limit))
+
+(defun org-indent-refresh-subtree ()
+ "Refresh indentation properties in the current outline subtree.
+Point is assumed to be at the beginning of a headline."
+ (interactive)
+ (when org-indent-mode
+ (save-excursion
+ (let (beg end)
+ (setq beg (point))
+ (setq end (save-excursion (org-end-of-subtree t t)))
+ (org-indent-remove-properties beg end)
+ (org-indent-add-properties beg end)))))
+
+(defun org-indent-refresh-buffer ()
+ "Refresh indentation properties in the current outline subtree.
+Point is assumed to be at the beginning of a headline."
+ (interactive)
+ (when org-indent-mode
+ (org-indent-mode -1)
+ (org-indent-mode 1)))
+
+(provide 'org-indent)
+
+;;; org-indent.el ends here
+
+
diff --git a/lisp/org-mouse.el b/lisp/org-mouse.el
index 7f90c23..9a986f3 100644
--- a/lisp/org-mouse.el
+++ b/lisp/org-mouse.el
@@ -724,7 +724,7 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"
["Open" org-open-at-point t]
["Open in Emacs" (org-open-at-point t) t]
"--"
- ["Copy link" (kill-new (match-string 0))]
+ ["Copy link" (org-kill-new (match-string 0))]
["Cut link"
(progn
(kill-region (match-beginning 0) (match-end 0))
diff --git a/lisp/org-table.el b/lisp/org-table.el
index 5b4c1aa..49445d8 100644
--- a/lisp/org-table.el
+++ b/lisp/org-table.el
@@ -721,6 +721,16 @@ When nil, simply write \"#ERROR\" in corrupted fields.")
;; Replace the old one
(delete-region beg end)
(move-marker end nil)
+ (if (equal (char-before) ?\n)
+ ;; This hack is for org-indent, to force redisplay of the
+ ;; line prefix of the first line. Apparently the redisplay
+ ;; is tied to the newline, which is, I think, a bug.
+ ;; To force this redisplay, we remove and re-insert the
+ ;; newline, so that the redisplay engine thinks it belongs
+ ;; to the changed text.
+ (progn
+ (backward-delete-char 1)
+ (insert "\n")))
(move-marker org-table-aligned-begin-marker (point))
(insert new)
(move-marker org-table-aligned-end-marker (point))
diff --git a/lisp/org-w3m.el b/lisp/org-w3m.el
index 7334a53..0befe27 100644
--- a/lisp/org-w3m.el
+++ b/lisp/org-w3m.el
@@ -93,7 +93,7 @@ so that it can be yanked into an Org-mode buffer with links working correctly."
(setq return-content
(concat return-content
(buffer-substring (point) transform-end))))
- (kill-new return-content)
+ (org-kill-new return-content)
(message "Transforming links...done, use C-y to insert text into Org-mode file")
(message "Copy with link transformation complete."))))
diff --git a/lisp/org.el b/lisp/org.el
index 14d55ef..cd6eb3c 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -277,6 +277,18 @@ uninteresting. Also tables look terrible when wrapped."
:group 'org-startup
:type 'boolean)
+(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 of
+the following lines anywhere in the buffer:
+
+ #+STARTUP: indent
+ #+STARTUP: noindent"
+ :group 'org-structure
+ :type '(choice
+ (const :tag "Not" nil)
+ (const :tag "Globally (slow on startup in large files)" t)))
+
(defcustom org-startup-align-all-tables nil
"Non-nil means, align all tables when visiting a file.
This is useful when the column width in tables is forced with <N> cookies
@@ -702,8 +714,8 @@ The following issues are influenced by this variable:
will be indented when this variable is set.
Note that this is all about true indentation, by adding and removing
-spaces. See also `org-indent.el' which does level-dependent indentation
-in a virtual way, i.e. only for display in Emacs."
+space characters. See also `org-indent.el' which does level-dependent
+indentation in a virtual way, i.e. at display time in Emacs."
:group 'org-edit-structure
:type 'boolean)
@@ -2882,6 +2894,7 @@ Normal means, no org-mode-specific context."
(declare-function org-agenda-check-for-timestamp-as-reason-to-ignore-todo-item
"org-agenda" (&optional end))
(declare-function org-inlinetask-remove-END-maybe "org-inlinetask" ())
+(declare-function org-indent-mode "org-indent" (arg))
(declare-function parse-time-string "parse-time" (string))
(declare-function remember "remember" (&optional initial))
(declare-function remember-buffer-desc "remember" ())
@@ -3154,6 +3167,13 @@ If yes, offer to stop it and to save the buffer with the changes."
'(org-feed-update org-feed-update-all org-feed-goto-inbox)))
+;; Autoload org-indent.el
+
+(eval-and-compile
+ (org-autoload
+ "org-indent"
+ '(org-indent-mode)))
+
;; Autoload archiving code
;; The stuff that is needed for cycling and tags has to be defined here.
@@ -3435,6 +3455,8 @@ After a match, the following groups carry important information:
("nofold" org-startup-folded nil)
("showall" org-startup-folded nil)
("content" org-startup-folded content)
+ ("indent" org-startup-indented t)
+ ("noindent" org-startup-indented nil)
("hidestars" org-hide-leading-stars t)
("showstars" org-hide-leading-stars nil)
("odd" org-odd-levels-only t)
@@ -3981,6 +4003,9 @@ The following commands are available:
(let ((bmp (buffer-modified-p)))
(org-table-map-tables 'org-table-align)
(set-buffer-modified-p bmp)))
+ (when org-startup-indented
+ (require 'org-indent)
+ (org-indent-mode 1))
(org-set-startup-visibility)))
(put 'org-mode 'flyspell-mode-predicate 'org-mode-flyspell-verify)
@@ -4624,6 +4649,7 @@ between words."
;; Description list items
'("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +\\(.*? ::\\)"
2 'bold prepend)
+ ;; ARCHIVEd headings
(list (concat "^\\*+ \\(.*:" org-archive-tag ":.*\\)")
'(1 'org-archived prepend))
;; Specials
@@ -4711,6 +4737,7 @@ If KWD is a number, get the corresponding match group."
(remove-text-properties beg end
'(mouse-face t keymap t org-linked-text t
invisible t intangible t
+ line-prefix t wrap-prefix t
org-no-flyspell t))))
;;;; Visibility cycling, including org-goto and indirect buffer
@@ -5787,6 +5814,16 @@ Works for outline headings and for plain lists alike."
;;; Promotion and Demotion
+(defvar org-after-demote-entry-hook nil
+ "Hook run after an entry has been demoted.
+The cursor will be at the beginning of the entry.
+When a subtree is being demoted, the hook will be called for each node.")
+
+(defvar org-after-promote-entry-hook nil
+ "Hook run after an entry has been promoted.
+The cursor will be at the beginning of the entry.
+When a subtree is being promoted, the hook will be called for each node.")
+
(defun org-promote-subtree ()
"Promote the entire subtree.
See also `org-promote'."
@@ -5872,7 +5909,8 @@ in the region."
(replace-match up-head nil t)
;; Fixup tag positioning
(and org-auto-align-tags (org-set-tags nil t))
- (if org-adapt-indentation (org-fixup-indentation (- diff)))))
+ (if org-adapt-indentation (org-fixup-indentation (- diff)))
+ (run-hooks 'org-after-promote-entry-hook)))
(defun org-demote ()
"Demote the current heading lower down the tree.
@@ -5885,7 +5923,8 @@ in the region."
(replace-match down-head nil t)
;; Fixup tag positioning
(and org-auto-align-tags (org-set-tags nil t))
- (if org-adapt-indentation (org-fixup-indentation diff))))
+ (if org-adapt-indentation (org-fixup-indentation diff))
+ (run-hooks 'org-after-demote-entry-hook)))
(defun org-map-tree (fun)
"Call FUN for every heading underneath the current one."
@@ -8567,7 +8606,7 @@ See also `org-refile-use-outline-path' and `org-completion-use-ido'"
(org-show-context 'org-goto))
(if regionp
(progn
- (kill-new (buffer-substring region-start region-end))
+ (org-kill-new (buffer-substring region-start region-end))
(org-save-markers-in-region region-start region-end))
(org-copy-subtree 1 nil t))
(save-excursion