summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Guerry <bzg@altern.org>2012-01-26 09:18:10 +0100
committerBastien Guerry <bzg@altern.org>2012-01-26 09:18:10 +0100
commit471ddbd14e2bb3e7689cdca5e6a461e54b8be9d8 (patch)
tree7098d56d133cc72ff2c8e7e271b3a29004f01ad1
parent674bb56857584f3ab72ac9a4ef2b7e791533d43b (diff)
downloadorg-mode-471ddbd14e2bb3e7689cdca5e6a461e54b8be9d8.tar.gz
Improve `org-insert-drawer' and related documentation.
* org.el (org-insert-property-drawer): Not an interactive command anymore. (org-insert-drawer): With a prefix argument, insert a property drawer. Check for headline within the region before inserting the drawer. Don't include special drawers in the completion table. (org-mode-map): New keybinding `C-c C-x d' for `org-insert-drawer'. * org.texi (Drawers): How to insert/complete drawers. Thanks to Nicolas Goaziou for the discussion and the patch.
-rw-r--r--doc/org.texi16
-rw-r--r--lisp/org.el155
2 files changed, 113 insertions, 58 deletions
diff --git a/doc/org.texi b/doc/org.texi
index f216aa0..a285cca 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -1768,6 +1768,8 @@ numerically, alphabetically, by time, or by custom function.
@cindex visibility cycling, drawers
@vindex org-drawers
+@cindex org-insert-drawer
+@kindex C-c C-x d
Sometimes you want to keep information associated with an entry, but you
normally don't want to see it. For this, Org mode has @emph{drawers}.
Drawers need to be configured with the variable
@@ -1784,6 +1786,13 @@ look like this:
After the drawer.
@end example
+You can interactively insert drawers at point by calling
+@code{org-insert-drawer}, which is bound to @key{C-c C-x d}. With an active
+region, this command will put the region inside the drawer. With a prefix
+argument, this command calls @code{org-insert-property-drawer} and add a
+property drawer right below the current headline. Completion over drawer
+keywords is also possible using @key{M-TAB}.
+
Visibility cycling (@pxref{Visibility cycling}) on the headline will hide and
show the entry, but keep the drawer collapsed to a single line. In order to
look inside the drawer, you need to move the cursor to the drawer line and
@@ -4894,8 +4903,8 @@ in the current file will be offered as possible completions.
@orgcmd{C-c C-x p,org-set-property}
Set a property. This prompts for a property name and a value. If
necessary, the property drawer is created as well.
-@item M-x org-insert-property-drawer
-@findex org-insert-property-drawer
+@item C-u M-x org-insert-drawer
+@cindex org-insert-drawer
Insert a property drawer into the current entry. The drawer will be
inserted early in the entry, but after the lines with planning
information like deadlines.
@@ -15912,6 +15921,7 @@ If WHICH is nil or `all', get all properties. If WHICH is
`special' or `standard', only get that subclass.
@end defun
@vindex org-use-property-inheritance
+@findex org-insert-property-drawer
@defun org-entry-get pom property &optional inherit
Get value of PROPERTY for entry at point-or-marker POM. By default,
this only looks at properties defined locally in the entry. If INHERIT
@@ -15934,7 +15944,7 @@ Get all property keys in the current buffer.
@end defun
@defun org-insert-property-drawer
-Insert a property drawer at point.
+Insert a property drawer for the current entry. Also
@end defun
@defun org-entry-put-multivalued-property pom property &rest values
diff --git a/lisp/org.el b/lisp/org.el
index 1fa7259..94ff9f7 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -14398,62 +14398,106 @@ formats in the current buffer."
(defun org-insert-property-drawer ()
"Insert a property drawer into the current entry."
- (interactive)
- (org-insert-drawer "PROPERTIES"))
+ (org-back-to-heading t)
+ (looking-at org-outline-regexp)
+ (let ((indent (if org-adapt-indentation
+ (- (match-end 0) (match-beginning 0))
+ 0))
+ (beg (point))
+ (re (concat "^[ \t]*" org-keyword-time-regexp))
+ end hiddenp)
+ (outline-next-heading)
+ (setq end (point))
+ (goto-char beg)
+ (while (re-search-forward re end t))
+ (setq hiddenp (outline-invisible-p))
+ (end-of-line 1)
+ (and (equal (char-after) ?\n) (forward-char 1))
+ (while (looking-at "^[ \t]*\\(:CLOCK:\\|:LOGBOOK:\\|CLOCK:\\|:END:\\)")
+ (if (member (match-string 1) '("CLOCK:" ":END:"))
+ ;; just skip this line
+ (beginning-of-line 2)
+ ;; Drawer start, find the end
+ (re-search-forward "^\\*+ \\|^[ \t]*:END:" nil t)
+ (beginning-of-line 1)))
+ (org-skip-over-state-notes)
+ (skip-chars-backward " \t\n\r")
+ (if (eq (char-before) ?*) (forward-char 1))
+ (let ((inhibit-read-only t)) (insert "\n:PROPERTIES:\n:END:"))
+ (beginning-of-line 0)
+ (org-indent-to-column indent)
+ (beginning-of-line 2)
+ (org-indent-to-column indent)
+ (beginning-of-line 0)
+ (if hiddenp
+ (save-excursion
+ (org-back-to-heading t)
+ (hide-entry))
+ (org-flag-drawer t))))
-(defun org-insert-drawer (&optional drawer)
- "Insert a drawer into the current entry."
- (interactive)
- (if (org-region-active-p)
- (let ((rbeg (region-beginning))
- (rend (region-end))
- (drawer (or drawer (completing-read "Drawer: " org-drawers))))
- (goto-char rbeg)
- (insert ":" drawer ":\n")
- (move-beginning-of-line 1)
- (indent-for-tab-command)
- (goto-char rend)
- (move-end-of-line 1)
- (insert "\n:END:")
- (move-beginning-of-line 1)
- (indent-for-tab-command))
- (org-back-to-heading t)
- (looking-at org-outline-regexp)
- (let ((indent (if org-adapt-indentation
- (- (match-end 0) (match-beginning 0))
- 0))
- (beg (point))
- (re (concat "^[ \t]*" org-keyword-time-regexp))
- (drawer (or drawer (completing-read "Drawer: " org-drawers)))
- end hiddenp)
- (outline-next-heading)
- (setq end (point))
- (goto-char beg)
- (while (re-search-forward re end t))
- (setq hiddenp (outline-invisible-p))
- (end-of-line 1)
- (and (equal (char-after) ?\n) (forward-char 1))
- (while (looking-at "^[ \t]*\\(:CLOCK:\\|:LOGBOOK:\\|CLOCK:\\|:END:\\)")
- (if (member (match-string 1) '("CLOCK:" ":END:"))
- ;; just skip this line
- (beginning-of-line 2)
- ;; Drawer start, find the end
- (re-search-forward "^\\*+ \\|^[ \t]*:END:" nil t)
- (beginning-of-line 1)))
- (org-skip-over-state-notes)
- (skip-chars-backward " \t\n\r")
- (if (eq (char-before) ?*) (forward-char 1))
- (let ((inhibit-read-only t)) (insert "\n:" drawer ":\n:END:"))
- (beginning-of-line 0)
- (org-indent-to-column indent)
- (beginning-of-line 2)
- (org-indent-to-column indent)
- (beginning-of-line 0)
- (if hiddenp
- (save-excursion
- (org-back-to-heading t)
- (hide-entry))
- (org-flag-drawer t)))))
+(defun org-insert-drawer (&optional arg drawer)
+ "Insert a drawer at point.
+
+Optional argument DRAWER, when non-nil, is a string representing
+drawer's name. Otherwise, the user is prompted for a name.
+
+If a region is active, insert the drawer around that region
+instead.
+
+Point is left between drawer's boundaries."
+ (interactive "P")
+ (let* ((logbook (if (stringp org-log-into-drawer) org-log-into-drawer
+ "LOGBOOK"))
+ ;; SYSTEM-DRAWERS is a list of drawer names that are used
+ ;; internally by Org. They are meant to be inserted
+ ;; automatically.
+ (system-drawers `("CLOCK" ,logbook "PROPERTIES"))
+ ;; Remove system drawers from list. Note: For some reason,
+ ;; `org-completing-read' ignores the predicate while
+ ;; `completing-read' handles it fine.
+ (drawer (if arg "PROPERTIES"
+ (or drawer
+ (completing-read
+ "Drawer: " org-drawers
+ (lambda (d) (not (member d system-drawers))))))))
+ (cond
+ ;; With C-u, fall back on `org-insert-property-drawer'
+ (arg (org-insert-property-drawer))
+ ;; With an active region, insert a drawer at point.
+ ((not (org-region-active-p))
+ (progn
+ (unless (bolp) (insert "\n"))
+ (insert (format ":%s:\n\n:END:\n" drawer))
+ (forward-line -2)))
+ ;; Otherwise, insert the drawer at point
+ (t
+ (let ((rbeg (region-beginning))
+ (rend (copy-marker (region-end))))
+ (unwind-protect
+ (progn
+ (goto-char rbeg)
+ (beginning-of-line)
+ (when (save-excursion
+ (re-search-forward org-outline-regexp-bol rend t))
+ (error "Drawers cannot contain headlines"))
+ ;; Position point at the beginning of the first
+ ;; non-blank line in region. Insert drawer's opening
+ ;; there, then indent it.
+ (org-skip-whitespace)
+ (beginning-of-line)
+ (insert ":" drawer ":\n")
+ (forward-line -1)
+ (indent-for-tab-command)
+ ;; Move point to the beginning of the first blank line
+ ;; after the last non-blank line in region. Insert
+ ;; drawer's closing, then indent it.
+ (goto-char rend)
+ (skip-chars-backward " \r\t\n")
+ (insert "\n:END:")
+ (indent-for-tab-command)
+ (unless (eolp) (insert "\n")))
+ ;; Clear marker, whatever the outcome of insertion is.
+ (set-marker rend nil)))))))
(defvar org-property-set-functions-alist nil
"Property set function alist.
@@ -17320,6 +17364,7 @@ BEG and END default to the buffer boundaries."
(org-defkey org-mode-map "\C-c$" 'org-archive-subtree)
(org-defkey org-mode-map "\C-c\C-x\C-s" 'org-advertized-archive-subtree)
(org-defkey org-mode-map "\C-c\C-x\C-a" 'org-archive-subtree-default)
+(org-defkey org-mode-map "\C-c\C-xd" 'org-insert-drawer)
(org-defkey org-mode-map "\C-c\C-xa" 'org-toggle-archive-tag)
(org-defkey org-mode-map "\C-c\C-xA" 'org-archive-to-archive-sibling)
(org-defkey org-mode-map "\C-c\C-xb" 'org-tree-to-indirect-buffer)