From mboxrd@z Thu Jan 1 00:00:00 1970 From: Carsten Dominik Subject: Re: Org-remember-handler fix for empty remember buffer Date: Mon, 8 Jun 2009 19:45:37 +0200 Message-ID: References: <4A280827.2070705@virginia.edu> Mime-Version: 1.0 (Apple Message framework v935.3) Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MDivn-0001jw-ON for emacs-orgmode@gnu.org; Mon, 08 Jun 2009 13:46:47 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MDivj-0001gH-Qh for emacs-orgmode@gnu.org; Mon, 08 Jun 2009 13:46:47 -0400 Received: from [199.232.76.173] (port=33074 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MDivj-0001fu-G8 for emacs-orgmode@gnu.org; Mon, 08 Jun 2009 13:46:43 -0400 Received: from mail-ew0-f210.google.com ([209.85.219.210]:41141) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1MDivi-0005ZP-ND for emacs-orgmode@gnu.org; Mon, 08 Jun 2009 13:46:43 -0400 Received: by ewy6 with SMTP id 6so6604842ewy.42 for ; Mon, 08 Jun 2009 10:46:41 -0700 (PDT) In-Reply-To: <4A280827.2070705@virginia.edu> List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: "Ryan C. Thompson" Cc: emacs-orgmode@gnu.org Fixed, thanks. - Carsten On Jun 4, 2009, at 7:45 PM, Ryan C. Thompson wrote: > Hi, > > I ran into a problem with org's remember functionality, and found a > fix for it. The problem is that if you attempt to either abort or > remember an empty buffer (that is, a buffer containing only > whitespace and comments), then org-mode hits an error and fails to > do either, leaving the buffer annoyingly open. > > The bug is in the loop that deletes trailing comments and > whitespace. If the buffer is empty, then this loop reaches the first > line, and attempts to delete a region starting at position zero, > which causes the error. Here is the modified function definition > that checks for this condition. > > As a bonus, the function also auto-aborts instead of saving if the > buffer is empty. > > Thank you, > > Ryan Thompson > > > > ;; Fix for empty remember buffer. > (defun org-remember-handler () > "Store stuff from remember.el into an org file. > When the template has specified a file and a headline, the entry is > filed > there, or in the location defined by `org-default-notes-file' and > `org-remember-default-headline'. > > If no defaults have been defined, or if the current prefix argument > is 1 (so you must use `C-1 C-c C-c' to exit remember), an interactive > process is used to select the target location. > > When the prefix is 0 (i.e. when remember is exited with `C-0 C-c C- > c'), > the entry is filed to the same location as the previous note. > > When the prefix is 2 (i.e. when remember is exited with `C-2 C-c C- > c'), > the entry is filed as a subentry of the entry where the clock is > currently running. > > When `C-u' has been used as prefix argument, the note is stored and > emacs > moves point to the new location of the note, so that editing can be > continued there (similar to inserting \"%&\" into the template). > > Before storing the note, the function ensures that the text has an > org-mode-style headline, i.e. a first line that starts with > a \"*\". If not, a headline is constructed from the current date and > some additional data. > > If the variable `org-adapt-indentation' is non-nil, the entire text is > also indented so that it starts in the same column as the headline > \(i.e. after the stars). > > See also the variable `org-reverse-note-order'." > (interactive) > (when (and (equal current-prefix-arg 2) > (not (marker-buffer org-clock-marker))) > (error "No running clock")) > (when (org-bound-and-true-p org-jump-to-target-location) > (let* ((end (min (point-max) (1+ (point)))) > (beg (point))) > (if (= end beg) (setq beg (1- beg))) > (put-text-property beg end 'org-position-cursor t))) > (goto-char (point-min)) > (while (looking-at "^[ \t]*\n\\|^##.*\n") > (replace-match "")) > (goto-char (point-max)) > (beginning-of-line 1) > (catch 'quit > (while (looking-at "[ \t]*$\\|##.*") > ;; Abort on empty buffer > (if (= (point) (point-min)) > (throw 'quit nil) > (previous-line))) > (delete-region (point) (point-max)) > (backward-delete-char 1) > (if org-note-abort (throw 'quit nil)) > ;; Also abort on an empty (i.e. whitespace-only) buffer > ;; (if (not (string-match "[^[:space:]]" (buffer-substring-no- > properties (point-min) (point-max)))) (return t)) > (let* ((visitp (org-bound-and-true-p org-jump-to-target-location)) > (previousp (and (member current-prefix-arg '((16) 0)) > org-remember-previous-location)) > (clockp (equal current-prefix-arg 2)) > (fastp (org-xor (equal current-prefix-arg 1) > org-remember-store-without-prompt)) > (file (cond > (fastp org-default-notes-file) > ((and (eq org-remember-interactive-interface 'refile) > org-refile-targets) > org-default-notes-file) > ((not previousp) > (org-get-org-file)))) > (heading org-remember-default-headline) > (visiting (and file (org-find-base-buffer-visiting file))) > (org-startup-folded nil) > (org-startup-align-all-tables nil) > (org-goto-start-pos 1) > spos exitcmd level reversed txt) > (when (equal current-prefix-arg '(4)) > (setq visitp t)) > (when previousp > (setq file (car org-remember-previous-location) > visiting (and file (org-find-base-buffer-visiting file)) > heading (cdr org-remember-previous-location) > fastp t)) > (when clockp > (setq file (buffer-file-name (marker-buffer org-clock-marker)) > visiting (and file (org-find-base-buffer-visiting file)) > heading org-clock-heading-for-remember > fastp t)) > (setq current-prefix-arg nil) > ;; Modify text so that it becomes a nice subtree which can be > inserted > ;; into an org tree. > (goto-char (point-min)) > (if (re-search-forward "[ \t\n]+\\'" nil t) > ;; remove empty lines at end > (replace-match "")) > (goto-char (point-min)) > (unless (looking-at org-outline-regexp) > ;; add a headline > (insert (concat "* " (current-time-string) > " (" (remember-buffer-desc) ")\n")) > (backward-char 1) > (when org-adapt-indentation > (while (re-search-forward "^" nil t) > (insert " ")))) > (goto-char (point-min)) > (if (re-search-forward "\n[ \t]*\n[ \t\n]*\\'" nil t) > (replace-match "\n\n") > (if (re-search-forward "[ \t\n]*\\'") > (replace-match "\n"))) > (goto-char (point-min)) > (setq txt (buffer-string)) > (org-save-markers-in-region (point-min) (point-max)) > (when (and (eq org-remember-interactive-interface 'refile) > (not fastp)) > (org-refile nil (or visiting (find-file-noselect file))) > (and visitp (run-with-idle-timer 0.01 nil 'org-remember-visit- > immediately)) > (save-excursion > (bookmark-jump "org-refile-last-stored") > (bookmark-set "org-remember-last-stored") > (move-marker org-remember-last-stored-marker (point))) > (throw 'quit t)) > ;; Find the file > (with-current-buffer (or visiting (find-file-noselect file)) > (unless (org-mode-p) > (error "Target files for remember notes must be in Org-mode")) > (save-excursion > (save-restriction > (widen) > (and (goto-char (point-min)) > (not (re-search-forward "^\\* " nil t)) > (insert "\n* " (or (and (stringp heading) heading) > "Notes") "\n")) > (setq reversed (org-notes-order-reversed-p)) > > ;; Find the default location > (when heading > (cond > ((eq heading 'top) > (goto-char (point-min)) > (or (looking-at org-outline-regexp) > (re-search-forward org-outline-regexp nil t)) > (setq org-goto-start-pos (or (match-beginning 0) (point-min)))) > ((eq heading 'bottom) > (goto-char (point-max)) > (or (bolp) (newline)) > (setq org-goto-start-pos (point))) > ((and (stringp heading) (string-match "\\S-" heading)) > (goto-char (point-min)) > (if (re-search-forward > (concat "^\\*+[ \t]+" (regexp-quote heading) > (org-re "\\([ \t]+:[[:alnum:]@_:]*\\)?[ \t]*$")) > nil t) > (setq org-goto-start-pos (match-beginning 0)) > (when fastp > (goto-char (point-max)) > (unless (bolp) (newline)) > (insert "* " heading "\n") > (setq org-goto-start-pos (point-at-bol 0))))) > (t (goto-char (point-min)) (setq org-goto-start-pos (point) > heading 'top)))) > > ;; Ask the User for a location, using the appropriate interface > (cond > ((and fastp (memq heading '(top bottom))) > (setq spos org-goto-start-pos > exitcmd (if (eq heading 'top) 'left nil))) > (fastp (setq spos org-goto-start-pos > exitcmd 'return)) > ((eq org-remember-interactive-interface 'outline) > (setq spos (org-get-location (current-buffer) > org-remember-help) > exitcmd (cdr spos) > spos (car spos))) > ((eq org-remember-interactive-interface 'outline-path- > completion) > (let ((org-refile-targets '((nil . (:maxlevel . 10)))) > (org-refile-use-outline-path t)) > (setq spos (org-refile-get-location "Heading: ") > exitcmd 'return > spos (nth 3 spos)))) > (t (error "This should not happen"))) > (if (not spos) (throw 'quit nil)) ; return nil to show we did > ; not handle this note > (and visitp (run-with-idle-timer 0.01 nil 'org-remember-visit- > immediately)) > (goto-char spos) > (cond ((org-on-heading-p t) > (org-back-to-heading t) > (setq level (funcall outline-level)) > (cond > ((eq exitcmd 'return) > ;; sublevel of current > (setq org-remember-previous-location > (cons (abbreviate-file-name file) > (org-get-heading 'notags))) > (if reversed > (outline-next-heading) > (org-end-of-subtree t) > (if (not (bolp)) > (if (looking-at "[ \t]*\n") > (beginning-of-line 2) > (end-of-line 1) > (insert "\n")))) > (org-paste-subtree (org-get-valid-level level 1) txt) > (and org-auto-align-tags (org-set-tags nil t)) > (bookmark-set "org-remember-last-stored") > (move-marker org-remember-last-stored-marker (point))) > ((eq exitcmd 'left) > ;; before current > (org-paste-subtree level txt) > (and org-auto-align-tags (org-set-tags nil t)) > (bookmark-set "org-remember-last-stored") > (move-marker org-remember-last-stored-marker (point))) > ((eq exitcmd 'right) > ;; after current > (org-end-of-subtree t) > (org-paste-subtree level txt) > (and org-auto-align-tags (org-set-tags nil t)) > (bookmark-set "org-remember-last-stored") > (move-marker org-remember-last-stored-marker (point))) > (t (error "This should not happen")))) > > ((eq heading 'bottom) > (org-paste-subtree 1 txt) > (and org-auto-align-tags (org-set-tags nil t)) > (bookmark-set "org-remember-last-stored") > (move-marker org-remember-last-stored-marker (point))) > > ((and (bobp) (not reversed)) > ;; Put it at the end, one level below level 1 > (save-restriction > (widen) > (goto-char (point-max)) > (if (not (bolp)) (newline)) > (org-paste-subtree (org-get-valid-level 1 1) txt) > (and org-auto-align-tags (org-set-tags nil t)) > (bookmark-set "org-remember-last-stored") > (move-marker org-remember-last-stored-marker (point)))) > > ((and (bobp) reversed) > ;; Put it at the start, as level 1 > (save-restriction > (widen) > (goto-char (point-min)) > (re-search-forward "^\\*+ " nil t) > (beginning-of-line 1) > (org-paste-subtree 1 txt) > (and org-auto-align-tags (org-set-tags nil t)) > (bookmark-set "org-remember-last-stored") > (move-marker org-remember-last-stored-marker (point)))) > (t > ;; Put it right there, with automatic level determined by > ;; org-paste-subtree or from prefix arg > (org-paste-subtree > (if (numberp current-prefix-arg) current-prefix-arg) > txt) > (and org-auto-align-tags (org-set-tags nil t)) > (bookmark-set "org-remember-last-stored") > (move-marker org-remember-last-stored-marker (point)))) > > (when remember-save-after-remembering > (save-buffer) > (if (and (not visiting) > (not (equal (marker-buffer org-clock-marker) > (current-buffer)))) > (kill-buffer (current-buffer))))))))) > > t) ;; return t to indicate that we took care of this note. > > > _______________________________________________ > Emacs-orgmode mailing list > Remember: use `Reply All' to send replies to the list. > Emacs-orgmode@gnu.org > http://lists.gnu.org/mailman/listinfo/emacs-orgmode