From a41feacbef34a115fca87df2e77e6230125a5a8e Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Sat, 25 Jul 2009 15:15:07 -0400 Subject: [PATCH] Add patch against org core regarding source code edit buffers, with explanation. --- org-babel.org | 200 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 198 insertions(+), 2 deletions(-) diff --git a/org-babel.org b/org-babel.org index dab4e613e..8dcc63d9a 100644 --- a/org-babel.org +++ b/org-babel.org @@ -260,8 +260,204 @@ but with preference given to ** TODO take default values for header args from properties Use file-wide and subtree wide properties to set default values for header args. -** TODO support for working with =*Org Edit Src Example*= buffers [2/5] -*** TODO name edit buffer according to #+srcname (and language?) + + [DED] One thing I'm finding when working with R is that an org file + may contain many source blocks, but that I just want to evaluate a + subset of them. Typically this is in order to take up where I left + off: I need to recreate a bunch of variables in the session + environment. I'm thinking maybe we want to use a tag-based + mechanism similar to :export: and :noexport: to control evaluation + on a per-subtree basis. + +** TODO support for working with =*Org Edit Src Example*= buffers [3/5] +*** Patch against org source. + I've worked on several related changes to source code edit buffer + behaviour in the org core. My current patch (below) does the + following. Detailed explanation / working notes are below. + - C-x s offers to save edit buffers + - C-x C-c offers to save edit buffers + - C-x k warns that you're killing an edit buffer + - If you do kill an edit buffer, the overlay in the parent buffer is removed + - Edit buffers are named *Org Src []*, where + is the name of the org-mode buffer containing this + source code block, and lang is the language major mode. The + latter might be unnecessary? + +#+begin_example +diff --git a/lisp/org-src.el b/lisp/org-src.el +index 2083c77..2be21e6 100644 +--- a/lisp/org-src.el ++++ b/lisp/org-src.el +@@ -113,7 +113,7 @@ but which mess up the display of a snippet in Org exported files.") + + (defvar org-src-mode-map (make-sparse-keymap)) + (define-key org-src-mode-map "\C-c'" 'org-edit-src-exit) +-(define-key org-src-mode-map "\C-x\C-s" 'org-edit-src-save) ++;; (define-key org-src-mode-map "\C-x\C-s" 'org-edit-src-save) + (defvar org-edit-src-force-single-line nil) + (defvar org-edit-src-from-org-mode nil) + (defvar org-edit-src-picture nil) +@@ -168,7 +168,8 @@ the edited version." + (if (boundp 'org-edit-src-overlay) + (org-delete-overlay org-edit-src-overlay))) + (kill-buffer buffer)) +- (setq buffer (generate-new-buffer "*Org Edit Src Example*")) ++ (setq buffer (generate-new-buffer ++ (concat "*Org Src " (file-name-nondirectory buffer-file-name) "[" lang "]*"))) + (setq ovl (org-make-overlay beg end)) + (org-overlay-put ovl 'face 'secondary-selection) + (org-overlay-put ovl 'edit-buffer buffer) +@@ -186,8 +187,7 @@ the edited version." + '(display nil invisible nil intangible nil)) + (org-do-remove-indentation) + (let ((org-inhibit-startup t)) +- (funcall lang-f) +- (org-src-mode)) ++ (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 +@@ -201,6 +201,7 @@ the edited version." + (org-set-local 'org-edit-src-end-marker end) + (org-set-local 'org-edit-src-overlay ovl) + (org-set-local 'org-edit-src-nindent nindent) ++ (org-src-mode) + (and org-edit-src-persistent-message + (org-set-local 'header-line-format msg))) + (message "%s" msg) +@@ -400,12 +401,13 @@ 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 (string-match "\\`*Org Edit " (buffer-name (current-buffer))) +- (error "This is not an sub-editing buffer, something is wrong...")) ++ (unless org-edit-src-from-org-mode ++ (error "This is not a sub-editing buffer, something is wrong...")) + (let ((beg org-edit-src-beg-marker) + (end org-edit-src-end-marker) + (ovl org-edit-src-overlay) + (buffer (current-buffer)) ++ (buffer-file-name nil) + (nindent org-edit-src-nindent) + code line) + (untabify (point-min) (point-max)) +@@ -464,6 +466,17 @@ the language, a switch telling of the content should be in a single line." + (goto-char (min p (point-max))) + (message (or msg "")))) + ++(defun org-src-mode-configure-buffer () ++ (setq buffer-offer-save t) ++ (setq buffer-file-name ++ (concat (buffer-file-name (marker-buffer org-edit-src-beg-marker)) ++ "[" (buffer-name) "]")) ++ (setq write-contents-functions '(org-edit-src-save)) ++ (org-add-hook 'kill-buffer-hook ++ '(lambda () (org-delete-overlay org-edit-src-overlay)) nil 'local)) ++ ++(org-add-hook 'org-src-mode-hook 'org-src-mode-configure-buffer) ++ + (provide 'org-src) + + ;; arch-tag: 6a1fc84f-dec7-47be-a416-64be56bea5d8 + +#+end_example + +**** Detailed working notes to go with that patch +***** Recap of current org-src-mode + + If you use C-c ' to work on code in a begin_source block, the code + buffer is put in minor mode org-src-mode, which features the + following two useful key-bindings: + + | C-x s | org-edit-src-save | save the code in the source code block in the parent org file | + | C-c ' | org-edit-src-exit | return to the parent org file with new code | + + Furthermore, while the edit buffer is alive, the originating code + block is subject to a special overlay which links to the edit + buffer when you click on it. + + This is all excellent, and I use it daily, but I think there's + still a couple of improvements that we should make. + +***** Proposed bug I + C-x k kills the buffer without questions; the overlay remains, but + now links to a deleted buffer. +***** Proposed bug II + C-x C-c kills a modified edit buffer silently, without offering to + save your work. I have lost work like that a number of times + recently. +***** Proposed bug III + C-x s does not offer to save a modified edit buffer +***** Notes on solution +****** write-contents-functions + A good start seems to be to use org-src-mode-hook to add + org-edit-src-save to the write-contents-functions list. This + means that when it comes to saving, org-edit-src-save will be + called and no subsequent attempt will be made to save the buffer + in the normal way. (This should obviate the remapping of C-x C-s + to org-edit-src-save in org-src.el) +****** buffer-offer-save + We also want to set this to t. + +****** Where does this get us? + + - C-x s still does *not* offer to save the edit buffer. That's + because buffer-file-name is nil. + + - C-x C-c does ask us whether we want to save the + edit buffer. However, since buffer-file-name is nil it asks us + for a file name. The check in org-edit-src-exit throws an error + unless the buffer is named '* Org Edit '... + + - C-x k kills the buffer silently, leaving a broken overlay + link. If buffer-file-name were set, it would have warned that + the buffer was modified. + +****** buffer-file-name + So, that all suggests that we need to set buffer-file-name, even + though we don't really want to associate this buffer with a file + in the normal way. As for the file name, my current suggestion + is parent-org-filename[edit-buffer-name]. + + [I had to move the (org-src-mode) call to the end of + org-edit-src-code to make sure that the required variables were + defined when the hook was called.] + +****** And so where are we now? + - C-x s *does* offer to save the edit buffer, but in saving + produces a warning that the edit buffer is modified. + - C-x k now gives a warning that the edit buffer is modified + (even if it's not). + - C-x C-c is working as desired, except that again we get + warnings that the edit buffer is modified, once when we save, + and again just before exiting emacs. + - And C-c ' now issues a warning that the edit buffer is + modified when we leave it, which we don't want. +****** So, we need to get rid of the buffer modification warnings. + I've made buffer-file-name nil inside the let binding in + org-edit-src-exit. +****** And? + - C-x s behaves as desired, except that as was already the case, + the edit buffer is always considered modified, and so repeated + invocations keep saving it. + - As was already the case, C-x k always gives a warning that the + edit buffer has been modified. + - C-x C-c is as desired (offers to save the edit buffer) except + that it warns of the modified buffer just before exiting. + - C-c ' is as it should be (silent) +***** Conclusion + We've got the desired behaviour, at the cost of being forced to + assign a buffer-file-name to the edit buffer. The consequence is + that the edit buffer is considered to always be modified, since + a file of that name is never actually written to (doesn't even + exist). I couldn't see a way to trick emacs into believing that + the buffer was unmodified since last save. But in any case, I + think there's an argument that these modifications warnings are + a good thing, because one should not leave active edit buffers + around: you should always have exited with C-c ' first. + +*** DONE name edit buffer according to #+srcname (and language?) + See above patch agains org. *** TODO optionally evaluate header references when we switch to =*Org Edit Src*= buffer That seems to imply that the header references need to be evaluated and transformed into the target language object when we hit C-c ' to