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 năm trước cách đây
mục cha
commit
cc50f83583
4 tập tin đã thay đổi với 85 bổ sung58 xóa
  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