Browse Source

Example editing: Allow multiple editing buffers

Hsiu-Khuern Tang writes:

> Hi Carsten,
>
> You recently changed org-edit-src-code to use a separate buffer
> instead of an indirect buffer.  One side effect of this is that I
> can no longer edit several code examples at the same time:
> opening the second buffer will silently discard any changes made
> in the first.  I would prefer this behavior: when opening the
> second edit source buffer, write any changes in the first buffer
> to the originating Org buffer (but don't save it, of course).
>
> Another approach is to use different buffer names.

The better approach is clearly to allow several buffers, now
implemented with this commit.
Carsten Dominik 16 years ago
parent
commit
cc50f83583
4 changed files with 85 additions and 58 deletions
  1. 5 0
      doc/ChangeLog
  2. 10 10
      doc/org.texi
  3. 4 0
      lisp/ChangeLog
  4. 66 48
      lisp/org.el

+ 5 - 0
doc/ChangeLog

@@ -1,3 +1,8 @@
+2009-05-16  Carsten Dominik  <carsten.dominik@gmail.com>
+
+	* org.texi (Literal examples): Document the new implementation for
+	editing source code.
+
 2009-05-13  Carsten Dominik  <carsten.dominik@gmail.com>
 
 	* org.texi (Publishing action): Mention the new publishing

+ 10 - 10
doc/org.texi

@@ -7995,16 +7995,16 @@ areas in HTML export}.
 @kindex C-c '
 @item C-c '
 Edit the source code example at point in its native mode.  This works by
-switching to an indirect buffer, narrowing the buffer and switching to the
-other mode.  You need to exit by pressing @kbd{C-c '} again@footnote{Upon
-exit, lines starting with @samp{*} or @samp{#} will get a comma prepended, to
-keep them from being interpreted by Org as outline nodes or special
-comments.  These commas will be striped for editing with @kbd{C-c '}, and
-also for export.}.  Fixed-width
-regions (where each line starts with a colon followed by a space) will be
-edited using @code{artist-mode}@footnote{You may select a different-mode with
-the variable @code{org-edit-fixed-width-region-mode}.} to allow creating
-ASCII drawings easily.  Using this command in an empty line will create a new
+switching to a temporary buffer with the source code.  You need to exit by
+pressing @kbd{C-c '} again@footnote{Upon exit, lines starting with @samp{*}
+or @samp{#} will get a comma prepended, to keep them from being interpreted
+by Org as outline nodes or special comments.  These commas will be striped
+for editing with @kbd{C-c '}, and also for export.}, the edited version will
+then replace the old version in the Org buffer.  Fixed-width regions
+(where each line starts with a colon followed by a space) will be edited
+using @code{artist-mode}@footnote{You may select a different-mode with the
+variable @code{org-edit-fixed-width-region-mode}.} to allow creating ASCII
+drawings easily.  Using this command in an empty line will create a new
 fixed-width region.
 @kindex C-c l
 @item C-c l

+ 4 - 0
lisp/ChangeLog

@@ -1,5 +1,9 @@
 2009-05-16  Carsten Dominik  <carsten.dominik@gmail.com>
 
+	* org.el (org-edit-src-code, org-edit-fixed-width-region): Use a
+	better bufer-generating mechanism.
+	(org-edit-src-find-buffer): New function.
+
 	* org-icalendar.el (org-print-icalendar-entries): Don't check for
 	archive tag, this is already done by `org-agenda-skip'.
 	data while constructing lost of tags.

+ 66 - 48
lisp/org.el

@@ -6389,7 +6389,7 @@ the edited version."
 	(org-mode-p (eq major-mode 'org-mode))
 	(beg (make-marker))
 	(end (make-marker))
-	lang lang-f single lfmt code begline)
+	lang lang-f single lfmt code begline buffer)
     (if (not info)
 	nil
       (setq beg (move-marker beg (nth 0 info))
@@ -6403,31 +6403,48 @@ the edited version."
       (unless (functionp lang-f)
 	(error "No such language mode: %s" lang-f))
       (goto-line line)
-      (if (get-buffer "*Org Edit Src Example*")
-	  (kill-buffer "*Org Edit Src Example*"))
-      (switch-to-buffer (get-buffer-create "*Org Edit Src Example*"))
-      (insert code)
-      (remove-text-properties (point-min) (point-max)
-			      '(display nil invisible nil intangible nil))
-      (let ((org-inhibit-startup t))
-	(funcall lang-f))
-      (set (make-local-variable 'org-edit-src-force-single-line) single)
-      (set (make-local-variable 'org-edit-src-from-org-mode) org-mode-p)
-      (when lfmt
-	(set (make-local-variable 'org-coderef-label-format) lfmt))
-      (when org-mode-p
-	(goto-char (point-min))
-	(while (re-search-forward "^," nil t)
-	  (replace-match "")))
-      (goto-line (1+ (- line begline)))
-      (org-exit-edit-mode)
-      (org-set-local 'org-edit-src-beg-marker beg)
-      (org-set-local 'org-edit-src-end-marker end)
-      (and org-edit-src-persistent-message
-	  (org-set-local 'header-line-format msg))
+      (if (and (setq buffer (org-edit-src-find-buffer beg end))
+	       (y-or-n-p "Return to existing edit buffer? [n] will revert changes: "))
+	  (switch-to-buffer buffer)
+	(and buffer (kill-buffer buffer))
+	(switch-to-buffer (generate-new-buffer "*Org Edit Src Example*"))
+	(insert code)
+	(remove-text-properties (point-min) (point-max)
+				'(display nil invisible nil intangible nil))
+	(let ((org-inhibit-startup t))
+	  (funcall lang-f))
+	(set (make-local-variable 'org-edit-src-force-single-line) single)
+	(set (make-local-variable 'org-edit-src-from-org-mode) org-mode-p)
+	(when lfmt
+	  (set (make-local-variable 'org-coderef-label-format) lfmt))
+	(when org-mode-p
+	  (goto-char (point-min))
+	  (while (re-search-forward "^," nil t)
+	    (replace-match "")))
+	(goto-line (1+ (- line begline)))
+	(org-exit-edit-mode)
+	(org-set-local 'org-edit-src-beg-marker beg)
+	(org-set-local 'org-edit-src-end-marker end)
+	(and org-edit-src-persistent-message
+	     (org-set-local 'header-line-format msg)))
       (message "%s" msg)
       t)))
 
+(defun org-edit-src-find-buffer (beg end)
+  "Find a source editing buffer that is already editing the region BEG to END."
+  (catch 'exit
+    (mapc 
+     (lambda (b)
+       (with-current-buffer b
+	 (if (and (string-match "\\`*Org Edit " (buffer-name))
+		  (local-variable-p 'org-edit-src-beg-marker (current-buffer))
+		  (local-variable-p 'org-edit-src-end-marker (current-buffer))
+		  (equal beg org-edit-src-beg-marker)
+		  (equal end org-edit-src-end-marker))
+	     (throw 'exit (current-buffer)))))
+     (buffer-list))
+    nil))
+
 (defun org-edit-fixed-width-region ()
   "Edit the fixed-width ascii drawing at point.
 This must be a region where each line starts with a colon followed by
@@ -6444,7 +6461,7 @@ the fragment in the Org-mode buffer."
 	(org-mode-p (eq major-mode 'org-mode))
 	(beg (make-marker))
 	(end (make-marker))
-	beg1 end1 code begline)
+	beg1 end1 code begline buffer)
     (beginning-of-line 1)
     (if (looking-at "[ \t]*[^:\n \t]")
 	nil
@@ -6463,29 +6480,31 @@ the fragment in the Org-mode buffer."
 	    end (move-marker end end1)
 	    code (buffer-substring-no-properties beg end)
 	    begline (save-excursion (goto-char beg) (org-current-line)))
-      (if (get-buffer "*Org Edit Picture*")
-	  (kill-buffer "*Org Edit Picture*"))
-      (switch-to-buffer (get-buffer-create "*Org Edit Picture*"))
-      (insert code)
-      (remove-text-properties (point-min) (point-max)
-			      '(display nil invisible nil intangible nil))
-      (cond
-       ((eq org-edit-fixed-width-region-mode 'artist-mode)
-	(fundamental-mode)
-	(artist-mode 1))
+      (if (and (setq buffer (org-edit-src-find-buffer beg end))
+	       (y-or-n-p "Return to existing edit buffer? [n] will revert changes: "))
+	  (switch-to-buffer buffer)
+	(and buffer (kill-buffer buffer))
+	(switch-to-buffer (generate-new-buffer "*Org Edit Picture*"))
+	(insert code)
+	(remove-text-properties (point-min) (point-max)
+				'(display nil invisible nil intangible nil))
+	(cond
+	 ((eq org-edit-fixed-width-region-mode 'artist-mode)
+	  (fundamental-mode)
+	  (artist-mode 1))
        (t (funcall org-edit-fixed-width-region-mode)))
-      (set (make-local-variable 'org-edit-src-force-single-line) nil)
-      (set (make-local-variable 'org-edit-src-from-org-mode) org-mode-p)
-      (set (make-local-variable 'org-edit-src-picture) t)
-      (goto-char (point-min))
-      (while (re-search-forward "^[ \t]*: ?" nil t)
-	(replace-match ""))
-      (goto-line (1+ (- line begline)))
-      (org-exit-edit-mode)
-      (org-set-local 'org-edit-src-beg-marker beg)
-      (org-set-local 'org-edit-src-end-marker end)
-      (and org-edit-src-persistent-message
-	  (org-set-local 'header-line-format msg))
+	(set (make-local-variable 'org-edit-src-force-single-line) nil)
+	(set (make-local-variable 'org-edit-src-from-org-mode) org-mode-p)
+	(set (make-local-variable 'org-edit-src-picture) t)
+	(goto-char (point-min))
+	(while (re-search-forward "^[ \t]*: ?" nil t)
+	  (replace-match ""))
+	(goto-line (1+ (- line begline)))
+	(org-exit-edit-mode)
+	(org-set-local 'org-edit-src-beg-marker beg)
+	(org-set-local 'org-edit-src-end-marker end)
+	(and org-edit-src-persistent-message
+	     (org-set-local 'header-line-format msg)))
       (message "%s" msg)
       t)))
 
@@ -6568,8 +6587,7 @@ the language, a switch telling of the content should be in a single line."
 (defun org-edit-src-exit ()
   "Exit special edit and protect problematic lines."
   (interactive)
-  (unless (member (buffer-name)
-		  '("*Org Edit Src Example*" "*Org Edit Picture*"))
+  (unless (string-match "\\`*Org Edit " (buffer-name (current-buffer)))
     (error "This is not an sub-editing buffer, something is wrong..."))
   (let ((line (if (org-bound-and-true-p org-edit-src-force-single-line)
 		  1