emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Orgmode] Org-remember-handler fix for empty remember buffer


From: Carsten Dominik
Subject: Re: [Orgmode] Org-remember-handler fix for empty remember buffer
Date: Sun, 7 Jun 2009 16:18:58 +0200

Hi Ryan,

could you please post a patch instead, using "diff -u"  ?  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:address@hidden:]*\\)?[ \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.
address@hidden
http://lists.gnu.org/mailman/listinfo/emacs-orgmode





reply via email to

[Prev in Thread] Current Thread [Next in Thread]