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.
This commit is contained in:
Bastien Guerry 2012-01-26 09:18:10 +01:00
parent 674bb56857
commit 471ddbd14e
2 changed files with 113 additions and 58 deletions

View File

@ -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

View File

@ -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)