emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Nicolas Goaziou <n.goaziou@gmail.com>
To: Bastien <bzg@altern.org>
Cc: nicholas.dokos@hp.com, emacs-orgmode@gnu.org,
	Carsten Dominik <carsten.dominik@gmail.com>
Subject: Re: How do I create a drawer?
Date: Wed, 25 Jan 2012 17:33:22 +0100	[thread overview]
Message-ID: <87vcnzeo8d.fsf@gmail.com> (raw)
In-Reply-To: <878vkvg8m5.fsf@gnu.org> (Bastien's message of "Wed, 25 Jan 2012 15:27:46 +0100")

[-- Attachment #1: Type: text/plain, Size: 1455 bytes --]

Hello,

Bastien <bzg@altern.org> writes:

> The version I just pushed does not handle this kind of problem.
> If you think it's worth the trouble, can you have a look at it?

I've checked the code, and the `org-insert-drawer' is actually not what
I had in mind.

To me, there are really two types of drawers: system drawers and user's
drawers (which I'll simply call "drawers" from now).  System drawers
usually go just below the current headline (which is mandatory) and are
inserted automatically by some Org mechanism. Drawers can go anywhere,
even before the first headline, and are usually inserted manually.

Being interactive, `org-insert-drawer' is clearly user-oriented. An user
calling this function will probably want to insert a drawer at point (if
not around region), much less likely to insert a system drawer manually.

Thus, that function shouldn't be used for `org-insert-property-drawer'
internals, which needs to move point back to the headline.

Therefore, I suggest the following draft of a patch, that mostly reverts
commit splitting `org-insert-property-drawer' and makes
`org-insert-drawer' more user friendly. It provides the following
facilities:

  - headline inclusion check,
  - drawer insertion without requiring an headline above,
  - skip trailing blank lines (i.e. to wrap buffer around a just marked
    paragraph),
  - Ignore system drawer's names in completion list.

What do you think?


Regards,

-- 
Nicolas Goaziou

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: insert drawer patch --]
[-- Type: text/x-patch, Size: 6275 bytes --]

From f3c76eb772d1d8e0fa9fc53f10ed8985334c75bf Mon Sep 17 00:00:00 2001
From: Nicolas Goaziou <n.goaziou@gmail.com>
Date: Wed, 25 Jan 2012 16:48:21 +0100
Subject: [PATCH] Make org-insert-drawer more user oriented

* lisp/org.el (org-insert-property-drawer): Do not rely on
  `org-insert-drawer' since properties drawers are not meant for
  user's consumption.
(org-insert-drawer): Insert drawer at point.  If a region is provided,
wrap the drawer around it instead.  When offering completion, ignore
internal drawers.  Provide an error message when region contains an
headline.
---
 lisp/org.el |  143 +++++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 91 insertions(+), 52 deletions(-)

diff --git a/lisp/org.el b/lisp/org.el
index 1fa7259..cada815 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -14399,61 +14399,100 @@ 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."
+  "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)
-  (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)))))
+  (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 (or drawer
+		     (completing-read
+		      "Drawer: " org-drawers
+		      (lambda (d) (not (member d system-drawers)))))))
+    (if (not (org-region-active-p))
+	;; Insert a drawer at point.
+	(progn
+	  (unless (bolp) (insert "\n"))
+	  (insert (format ":%s:\n\n:END:\n" drawer))
+	  (forward-line -2))
+      (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.
-- 
1.7.8.4


  reply	other threads:[~2012-01-25 16:35 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-01-25  0:46 How do I create a drawer? Nick Dokos
2012-01-25  8:29 ` Olaf Dietsche
2012-01-25 14:25   ` Bastien
2012-01-25  8:44 ` Russell Adams
2012-01-25  9:03 ` Bastien
2012-01-25  9:17   ` Rainer M Krug
2012-01-25 13:16   ` Carsten Dominik
2012-01-25 13:29     ` Nicolas Goaziou
2012-01-25 14:09       ` Carsten Dominik
2012-01-25 14:17         ` Nicolas Goaziou
2012-01-25 14:27           ` Bastien
2012-01-25 16:33             ` Nicolas Goaziou [this message]
2012-01-26  8:28               ` Bastien
2012-01-25 14:26     ` Bastien
2012-01-25 14:34       ` Nick Dokos
2012-01-26  1:46         ` François Pinard

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87vcnzeo8d.fsf@gmail.com \
    --to=n.goaziou@gmail.com \
    --cc=bzg@altern.org \
    --cc=carsten.dominik@gmail.com \
    --cc=emacs-orgmode@gnu.org \
    --cc=nicholas.dokos@hp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).