summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <mail@nicolasgoaziou.fr>2014-11-23 00:31:23 +0100
committerNicolas Goaziou <mail@nicolasgoaziou.fr>2014-11-24 00:07:39 +0100
commit203bf5870f7b27b96fb3e4adbd06cf37a38d7512 (patch)
treebeaa3cf4facfb52b1cfc16d7bb01c65cb8c23250
parent9c06f8cce93f479bff5ef053777c235935717a66 (diff)
downloadorg-mode-203bf5870f7b27b96fb3e4adbd06cf37a38d7512.tar.gz
org-src: Unify source editing tools
* lisp/org-src.el (org-src-strip-leading-and-trailing-blanklines, org-edit-src-force-single-line, org-edit-src-picture, org-edit-src-from-org-mode, org-edit-src-allow-write-back-p, org-edit-src-beg-marker, org-edit-src-end-marker, org-edit-src-overlay, org-edit-src-block-indentation, org-edit-src-saved-temp-window-config, org-edit-src-code-timer): Remove variables. (org-src--allow-write-back-p, org-src--beg-marker, org-src--block-indentation, org-src--code-timer, org-src--end-marker, org-src--end-marker, org-src--from-org-mode, org-src--overlay, org-src--saved-temp-window-config, org-src--type, org-src--babel-info): New variables. (org-src--construct-edit-buffer-name, org-src--edit-buffer, org-src--source-buffer, org-src--get-lang-mode, org-src--coordinates, org-src--goto-coordinates, org-src--element-contents-area, org-src--make-source-overlay, org-src--on-element-p, org-src--contents-for-write-back, org-src--edit-element, org-edit-table.el, org-edit-export-block): New functions. (org-edit-src-find-buffer, org-src-construct-edit-buffer-name, org-src-tangle, org-src-in-org-buffer): Remove functions. (org-edit-src-code, org-edit-fixed-width-region, org-edit-src-abort, org-edit-src-save): Use new functions and variables. (org-edit-src-exit): Use new functions and variables. Change signature. * lisp/org.el (org-edit-special, org-indent-line, org-indent-region): Use new functions and variables. * lisp/ob-core.el (org-babel-do-in-edit-buffer): Remove useless check. (org-babel-expand-src-block): Apply signature change. This patches resolves discrepancies between source editing tools and globally simplifies process (auto-save feature, region preservation...). It introduces export block editing. It also moves internal variables and functions into an appropriate namespace and delete some unused functions.
-rw-r--r--lisp/ob-core.el11
-rw-r--r--lisp/org-src.el1068
-rwxr-xr-xlisp/org.el7
3 files changed, 545 insertions, 541 deletions
diff --git a/lisp/ob-core.el b/lisp/ob-core.el
index 6c38677..0584a8d 100644
--- a/lisp/ob-core.el
+++ b/lisp/ob-core.el
@@ -49,9 +49,8 @@
(declare-function tramp-file-name-host "tramp" (vec))
(declare-function with-parsed-tramp-file-name "tramp" (filename var &rest body))
(declare-function org-icompleting-read "org" (&rest args))
-(declare-function org-edit-src-code "org-src"
- (&optional context code edit-buffer-name quietp))
-(declare-function org-edit-src-exit "org-src" (&optional context))
+(declare-function org-edit-src-code "org-src" (&optional code edit-buffer-name))
+(declare-function org-edit-src-exit "org-src" ())
(declare-function org-open-at-point "org" (&optional in-emacs reference-buffer))
(declare-function org-save-outline-visibility "org-macs" (use-markers &rest body))
(declare-function org-outline-overlay-data "org" (&optional use-markers))
@@ -777,8 +776,7 @@ arguments and pop open the results in a preview buffer."
(funcall assignments-cmd params))))))
(if (org-called-interactively-p 'any)
(org-edit-src-code
- nil expanded
- (concat "*Org-Babel Preview " (buffer-name) "[ " lang " ]*"))
+ expanded (concat "*Org-Babel Preview " (buffer-name) "[ " lang " ]*"))
expanded)))
(defun org-babel-edit-distance (s1 s2)
@@ -994,8 +992,7 @@ Return t if a code block was found at point, nil otherwise."
(when (and (org-babel-where-is-src-block-head)
(org-edit-src-code))
(unwind-protect (progn ,@body)
- (if (org-bound-and-true-p org-edit-src-from-org-mode)
- (org-edit-src-exit)))
+ (org-edit-src-exit))
t)))
(def-edebug-spec org-babel-do-in-edit-buffer (body))
diff --git a/lisp/org-src.el b/lisp/org-src.el
index 20819d6..700bc3c 100644
--- a/lisp/org-src.el
+++ b/lisp/org-src.el
@@ -38,16 +38,12 @@
(require 'cl))
(declare-function org-do-remove-indentation "org" (&optional n))
-(declare-function org-at-table.el-p "org" ())
-(declare-function org-in-block-p "org" (names))
(declare-function org-get-indentation "org" (&optional line))
(declare-function org-switch-to-buffer-other-window "org" (&rest args))
(declare-function org-pop-to-buffer-same-window
"org-compat" (&optional buffer-or-name norecord label))
(declare-function org-base-buffer "org" (buffer))
-(declare-function org-babel-tangle "ob-tangle" (&optional arg target-file lang))
-
(defcustom org-edit-src-turn-on-auto-save nil
"Non-nil means turn `auto-save-mode' on when editing a source block.
This will save the content of the source code editing buffer into
@@ -121,9 +117,6 @@ editing it with \\[org-edit-src-code]. Has no effect if
:group 'org-edit-structure
:type 'integer)
-(defvar org-src-strip-leading-and-trailing-blank-lines nil
- "If non-nil, blank lines are removed when exiting the code edit buffer.")
-
(defcustom org-edit-src-persistent-message t
"Non-nil means show persistent exit help message while editing src examples.
The message is shown in the header-line, which will be created in the
@@ -186,357 +179,295 @@ issued in the language major mode buffer."
:version "24.1"
:group 'org-babel)
-;;; Editing source examples
-
-(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-c\C-k" 'org-edit-src-abort)
-(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-allow-write-back-p t)
-(defvar org-edit-src-picture nil)
-(defvar org-edit-src-beg-marker nil)
-(defvar org-edit-src-end-marker nil)
-(defvar org-edit-src-overlay nil)
-(defvar org-edit-src-block-indentation nil)
-(defvar org-edit-src-saved-temp-window-config nil)
+
+;;; Internal functions and variables
-(defvar org-src-babel-info nil)
+(defvar org-src--allow-write-back-p t)
+(defvar org-src--beg-marker nil)
+(defvar org-src--block-indentation nil)
+(defvar org-src--code-timer nil)
+(defvar org-src--end-marker nil)
+(defvar org-src--from-org-mode nil)
+(defvar org-src--overlay nil)
+(defvar org-src--saved-temp-window-config nil)
+(defvar org-src--type nil)
+(defvar org-src--babel-info nil)
-(defcustom org-src-ask-before-returning-to-edit-buffer t
- "If nil, when org-edit-src code is used on a block that already
-has an active edit buffer, it will switch to that edit buffer
-immediately; otherwise it will ask whether you want to return to
-the existing edit buffer."
- :group 'org-edit-structure
- :version "24.4"
- :package-version '(Org . "8.0")
- :type 'boolean)
+(defun org-src--construct-edit-buffer-name (org-buffer-name lang)
+ "Construct the buffer name for a source editing buffer."
+ (concat "*Org Src " org-buffer-name "[ " lang " ]*"))
-(define-minor-mode org-src-mode
- "Minor mode for language major mode buffers generated by org.
-This minor mode is turned on in two situations:
-- when editing a source code snippet with \"C-c '\".
-- When formatting a source code snippet for export with htmlize.
-There is a mode hook, and keybindings for `org-edit-src-exit' and
-`org-edit-src-save'")
+(defun org-src--edit-buffer (beg end)
+ "Return buffer editing area between BEG and END.
+Return nil if there is no such buffer."
+ (catch 'exit
+ (dolist (b (buffer-list))
+ (with-current-buffer b
+ (and (org-src-edit-buffer-p)
+ (eq beg org-src--beg-marker)
+ (eq end org-src--end-marker)
+ (throw 'exit b))))))
+
+(defun org-src--source-buffer ()
+ "Return source buffer edited by current buffer."
+ (unless (org-src-edit-buffer-p) (error "Not in a source buffer"))
+ (or (marker-buffer org-src--beg-marker)
+ (error "No source buffer available for current editing session")))
+
+(defun org-src--get-lang-mode (lang)
+ "Return major mode that should be used for LANG.
+LANG is a string, and the returned major mode is a symbol."
+ (intern
+ (concat
+ (let ((l (or (cdr (assoc lang org-src-lang-modes)) lang)))
+ (if (symbolp l) (symbol-name l) l))
+ "-mode")))
-(defvar org-edit-src-code-timer nil)
-(defun org-edit-src-code (&optional context code edit-buffer-name)
- "Edit the source CODE block at point.
-The code is copied to a separate buffer and the appropriate mode
-is turned on. When done, exit with \\[org-edit-src-exit]. This will
-remove the original code in the Org buffer, and replace it with the
-edited version. An optional argument CONTEXT is used by \\[org-edit-src-save]
-when calling this function. See `org-src-window-setup' to configure
-the display of windows containing the Org buffer and the code buffer."
- (interactive)
- (if (not (or (org-in-block-p '("src" "example" "latex" "html"))
- (org-at-table.el-p)))
- (user-error "Not in a source code or example block")
- (unless (eq context 'save)
- (setq org-edit-src-saved-temp-window-config (current-window-configuration)))
- (let* ((mark (and (org-region-active-p) (mark)))
- (case-fold-search t)
- (info
- ;; If the src region consists in no lines, we insert a blank
- ;; line.
- (let* ((temp (org-edit-src-find-region-and-lang))
- (beg (nth 0 temp))
- (end (nth 1 temp)))
- (if (>= end beg) temp
- (goto-char beg)
- (insert "\n")
- (org-edit-src-find-region-and-lang))))
- (full-info (org-babel-get-src-block-info 'light))
- (org-mode-p (derived-mode-p 'org-mode)) ;; derived-mode-p is reflexive
- (beg (make-marker))
- ;; Move marker with inserted text for case when src block is
- ;; just one empty line, i.e. beg == end.
- (end (copy-marker (make-marker) t))
- (allow-write-back-p (null code))
- block-nindent total-nindent ovl lang lang-f single lfmt buffer msg
- begline markline markcol line col transmitted-variables)
- (setq beg (move-marker beg (nth 0 info))
- end (move-marker end (nth 1 info))
- msg (if allow-write-back-p
- (substitute-command-keys
- "Edit, then exit with C-c ' (C-c and single quote) -- C-c C-k to abort")
- "Exit with C-c ' (C-c and single quote) -- C-c C-k to abort")
- code (or code (buffer-substring-no-properties beg end))
- lang (or (cdr (assoc (nth 2 info) org-src-lang-modes))
- (nth 2 info))
- lang (if (symbolp lang) (symbol-name lang) lang)
- single (nth 3 info)
- block-nindent (nth 5 info)
- lang-f (intern (concat lang "-mode"))
- begline (save-excursion (goto-char beg) (org-current-line))
- transmitted-variables
- `((org-edit-src-content-indentation
- ,org-edit-src-content-indentation)
- (org-edit-src-force-single-line ,single)
- (org-edit-src-from-org-mode ,org-mode-p)
- (org-edit-src-allow-write-back-p ,allow-write-back-p)
- (org-src-preserve-indentation ,org-src-preserve-indentation)
- (org-src-babel-info ,(org-babel-get-src-block-info 'light))
- (org-coderef-label-format
- ,(or (nth 4 info) org-coderef-label-format))
- (org-edit-src-beg-marker ,beg)
- (org-edit-src-end-marker ,end)
- (org-edit-src-block-indentation ,block-nindent)))
- (if (and mark (>= mark beg) (<= mark (1+ end)))
- (save-excursion (goto-char (min mark end))
- (setq markline (org-current-line)
- markcol (current-column))))
- (if (equal lang-f 'table.el-mode)
- (setq lang-f (lambda ()
- (text-mode)
- (if (org-bound-and-true-p flyspell-mode)
- (flyspell-mode -1))
- (table-recognize)
- (org-set-local 'org-edit-src-content-indentation 0))))
- (unless (functionp lang-f)
- (error "No such language mode: %s" lang-f))
- (save-excursion
- (if (> (point) end) (goto-char end))
- (setq line (org-current-line)
- col (current-column)))
- (if (and (setq buffer (org-edit-src-find-buffer beg end))
- (or (eq context 'save)
- (if org-src-ask-before-returning-to-edit-buffer
- (y-or-n-p "Return to existing edit buffer ([n] will revert changes)? ") t)))
- (org-src-switch-to-buffer buffer 'return)
- (when buffer
- (with-current-buffer buffer
- (if (boundp 'org-edit-src-overlay)
- (delete-overlay org-edit-src-overlay)))
- (kill-buffer buffer))
- (setq buffer (generate-new-buffer
- (or edit-buffer-name
- (org-src-construct-edit-buffer-name (buffer-name) lang))))
- (setq ovl (make-overlay beg end))
- (overlay-put ovl 'edit-buffer buffer)
- (overlay-put ovl 'help-echo "Click with mouse-1 to switch to buffer editing this segment")
- (overlay-put ovl 'face 'secondary-selection)
- (overlay-put ovl
- 'keymap
- (let ((map (make-sparse-keymap)))
- (define-key map [mouse-1] 'org-edit-src-continue)
- map))
- (overlay-put ovl :read-only "Leave me alone")
- (setq transmitted-variables
- (append transmitted-variables `((org-edit-src-overlay ,ovl))))
+(defun org-src--coordinates (pos beg end)
+ "Return coordinates of POS relatively to BEG and END.
+POS, BEG and END are buffer positions. Return value is either
+a cons cell (LINE . COLUMN) or symbol `end'. See also
+`org-src--goto-coordinates'."
+ (if (>= pos end) 'end
+ (org-with-wide-buffer
+ (goto-char (max beg pos))
+ (cons (count-lines beg (line-beginning-position))
+ ;; Column is relative to the end of line to avoid problems of
+ ;; comma escaping or colons appended in front of the line.
+ (- (current-column)
+ (progn (end-of-line) (current-column)))))))
+
+(defun org-src--goto-coordinates (coord beg end)
+ "Move to coordinates COORD relatively to BEG and END.
+COORD are coordinates, as returned by `org-src--coordinates',
+which see. BEG and END are buffer positions."
+ (goto-char
+ (if (eq coord 'end) (max (1- end) beg)
+ ;; If BEG happens to be located outside of the narrowed part of
+ ;; the buffer, widen it first.
+ (org-with-wide-buffer
+ (goto-char beg)
+ (forward-line (car coord))
+ (end-of-line)
+ (org-move-to-column (max (+ (current-column) (cdr coord)) 0))
+ (point)))))
+
+(defun org-src--element-contents-area (element)
+ "Return contents boundaries of ELEMENT.
+Return value is a pair (BEG . END) where BEG and END are buffer
+positions."
+ (let ((blockp (memq (org-element-type element)
+ '(example-block export-block src-block))))
+ (cons (org-with-wide-buffer
+ (goto-char (org-element-property :post-affiliated element))
+ (if blockp (line-beginning-position 2) (point)))
+ (org-with-wide-buffer
+ (goto-char (org-element-property :end element))
+ (skip-chars-backward " \r\t\n")
+ (line-beginning-position (if blockp 1 2))))))
+
+(defun org-src--make-source-overlay (beg end edit-buffer)
+ "Create overlay between BEG and END positions and return it.
+EDIT-BUFFER is the buffer currently editing area between BEG and
+END."
+ (let ((overlay (make-overlay beg end)))
+ (overlay-put overlay 'face 'secondary-selection)
+ (overlay-put overlay 'edit-buffer edit-buffer)
+ (overlay-put overlay 'help-echo
+ "Click with mouse-1 to switch to buffer editing this segment")
+ (overlay-put overlay 'face 'secondary-selection)
+ (overlay-put overlay 'keymap
+ (let ((map (make-sparse-keymap)))
+ (define-key map [mouse-1] 'org-edit-src-continue)
+ map))
+ (overlay-put overlay :read-only "Leave me alone")
+ overlay))
+
+(defun org-src--on-element-p (element)
+ "Non-nil when point is on ELEMENT."
+ (and (>= (point) (org-element-property :begin element))
+ (<= (point)
+ (org-with-wide-buffer
+ (goto-char (org-element-property :end element))
+ (skip-chars-backward " \r\t\n")
+ (line-end-position)))))
+
+(defun org-src--contents-for-write-back ()
+ "Return buffer contents in a format appropriate for write back.
+Assume point is in the corresponding edit buffer."
+ (let ((indentation (+ (or org-src--block-indentation 0)
+ (if (memq org-src--type '(example-block src-block))
+ org-edit-src-content-indentation
+ 0)))
+ (preserve-indentation org-src-preserve-indentation)
+ (contents (org-with-wide-buffer (buffer-string)))
+ (fixed-width-p (eq org-src--type 'fixed-width)))
+ (with-temp-buffer
+ (insert contents)
+ (goto-char (point-min))
+ (if fixed-width-p
+ (progn
+ (untabify (point-min) (point-max))
+ (let ((prefix (concat (and (not preserve-indentation)
+ (make-string indentation ?\s))
+ ": ")))
+ (while (not (eobp)) (insert prefix) (forward-line))))
+ (unless preserve-indentation (untabify (point-min) (point-max)))
+ (org-escape-code-in-region (point-min) (point-max))
+ (unless (or preserve-indentation (zerop indentation))
+ (let ((ind (make-string indentation ?\s)))
+ (while (not (eobp))
+ (when (org-looking-at-p "[ \t]*\\S-") (insert ind))
+ (forward-line)))))
+ (buffer-string))))
+
+(defun org-src--edit-element (element name &optional major write-back contents)
+ "Edit ELEMENT contents in a dedicated buffer.
+
+MAJOR is the major mode used in the edit buffer. A nil value is
+equivalent to `fundamental-mode'. When WRITE-BACK is non-nil,
+assume contents will replace original region. When CONTENTS is
+non-nil, display them in the edit buffer. Otherwise, assume they
+are located in property `:value'.
+
+Leave point in edit buffer."
+ (setq org-src--saved-temp-window-config (current-window-configuration))
+ (let* ((area (org-src--element-contents-area element))
+ (beg (copy-marker (car area)))
+ (end (copy-marker (cdr area) t))
+ (old-edit-buffer (org-src--edit-buffer beg end)))
+ (if (and old-edit-buffer
+ (or (not org-src-ask-before-returning-to-edit-buffer)
+ (y-or-n-p "Return to existing edit buffer ([n] will revert changes)? ")))
+ ;; Move to existing buffer.
+ (org-src-switch-to-buffer old-edit-buffer 'return)
+ ;; Discard old edit buffer.
+ (when old-edit-buffer
+ (with-current-buffer old-edit-buffer
+ (when (boundp 'org-src--overlay)
+ (delete-overlay org-src--overlay)))
+ (kill-buffer old-edit-buffer))
+ (let* ((org-mode-p (derived-mode-p 'org-mode))
+ (type (org-element-type element))
+ (ind (org-with-wide-buffer
+ (goto-char (org-element-property :begin element))
+ (org-get-indentation)))
+ (preserve-ind
+ (and (memq type '(example-block src-block))
+ (or (org-element-property :preserve-indent element)
+ org-src-preserve-indentation)))
+ ;; Store relative positions of mark (if any) and point
+ ;; within the edited area.
+ (point-coordinates (org-src--coordinates (point) beg end))
+ (mark-coordinates (and (org-region-active-p)
+ (let ((m (mark)))
+ (and (>= m beg) (>= end m)
+ (org-src--coordinates m beg end)))))
+ ;; Generate a new edit buffer.
+ (buffer (generate-new-buffer name))
+ ;; Add an overlay on top of source.
+ (overlay (org-src--make-source-overlay beg end buffer)))
+ ;; Switch to edit buffer.
(org-src-switch-to-buffer buffer 'edit)
- (if (eq single 'macro-definition)
- (setq code (replace-regexp-in-string "\\\\n" "\n" code t t)))
- (insert code)
+ ;; Insert contents.
+ (insert (or contents (org-element-property :value element)))
(remove-text-properties (point-min) (point-max)
'(display nil invisible nil intangible nil))
- (unless (cadr (assq 'org-src-preserve-indentation transmitted-variables))
- (setq total-nindent (or (org-do-remove-indentation) 0)))
- (let ((org-inhibit-startup t))
- (condition-case e
- (funcall lang-f)
- (error
- (message "Language mode `%s' fails with: %S" lang-f (nth 1 e)))))
- (dolist (pair transmitted-variables)
- (org-set-local (car pair) (cadr pair)))
- ;; Remove protecting commas from visible part of buffer.
- (org-unescape-code-in-region (point-min) (point-max))
- (when markline
- (org-goto-line (1+ (- markline begline)))
- (org-move-to-column
- (if org-src-preserve-indentation markcol
- (max 0 (- markcol total-nindent))))
- (push-mark (point) 'no-message t)
- (setq deactivate-mark nil))
- (org-goto-line (1+ (- line begline)))
- (org-move-to-column
- (if org-src-preserve-indentation col (max 0 (- col total-nindent))))
- (org-src-mode)
+ (unless preserve-ind (org-do-remove-indentation))
(set-buffer-modified-p nil)
(setq buffer-file-name nil)
+ ;; Start major mode.
+ (if (not major) (fundamental-mode)
+ (let ((org-inhibit-startup t))
+ (condition-case e (funcall major)
+ (error (message "Language mode `%s' fails with: %S"
+ major (nth 1 e))))))
+ ;; Transmit buffer-local variables for exit function. It must
+ ;; be done after initializing major mode, as this operation
+ ;; may reset them otherwise.
+ (org-set-local 'org-src--from-org-mode org-mode-p)
+ (org-set-local 'org-src--beg-marker beg)
+ (org-set-local 'org-src--end-marker end)
+ (org-set-local 'org-src--type type)
+ (org-set-local 'org-src--block-indentation ind)
+ (org-set-local 'org-src-preserve-indentation preserve-ind)
+ (org-set-local 'org-src--overlay overlay)
+ (org-set-local 'org-src--allow-write-back-p write-back)
+ ;; Start minor mode.
+ (org-src-mode)
+ (when org-edit-src-persistent-message
+ (org-set-local
+ 'header-line-format
+ (substitute-command-keys
+ (if write-back
+ "Edit, then exit with \\[org-edit-src-exit] or abort with \
+\\[org-edit-src-abort]"
+ "Exit with \\[org-edit-src-exit] or abort with \
+\\[org-edit-src-abort]"))))
+ ;; Possibly start `auto-save-mode'.
(when org-edit-src-turn-on-auto-save
(setq buffer-auto-save-file-name
(concat (make-temp-name "org-src-")
- (format-time-string "-%Y-%d-%m") ".txt")))
- (and org-edit-src-persistent-message
- (org-set-local 'header-line-format msg))
- (let ((edit-prep-func (intern (concat "org-babel-edit-prep:" lang))))
- (when (fboundp edit-prep-func)
- (funcall edit-prep-func full-info)))
- (or org-edit-src-code-timer
- (zerop org-edit-src-auto-save-idle-delay)
- (setq org-edit-src-code-timer
- (run-with-idle-timer
- org-edit-src-auto-save-idle-delay t
- (lambda ()
- (cond
- ((org-string-match-p "\\`\\*Org Src" (buffer-name))
- (when (buffer-modified-p) (org-edit-src-save)))
- ((not (org-some (lambda (b)
- (org-string-match-p "\\`\\*Org Src"
- (buffer-name b)))
- (buffer-list)))
- (cancel-timer org-edit-src-code-timer)
- (setq org-edit-src-code-timer nil))))))))
- t)))
-
-(defun org-edit-src-continue (e)
- "Continue editing source blocks." ;; Fixme: be more accurate
- (interactive "e")
- (mouse-set-point e)
- (let ((buf (get-char-property (point) 'edit-buffer)))
- (if buf (org-src-switch-to-buffer buf 'continue)
- (error "Something is wrong here"))))
-
-(defun org-src-switch-to-buffer (buffer context)
- (case org-src-window-setup
- ('current-window
- (org-pop-to-buffer-same-window buffer))
- ('other-window
- (switch-to-buffer-other-window buffer))
- ('other-frame
- (case context
- ('exit
- (let ((frame (selected-frame)))
- (switch-to-buffer-other-frame buffer)
- (delete-frame frame)))
- ('save
- (kill-buffer (current-buffer))
- (org-pop-to-buffer-same-window buffer))
- (t
- (switch-to-buffer-other-frame buffer))))
- ('reorganize-frame
- (if (eq context 'edit) (delete-other-windows))
- (org-switch-to-buffer-other-window buffer)
- (if (eq context 'exit) (delete-other-windows)))
- ('switch-invisibly
- (set-buffer buffer))
- (t
- (message "Invalid value %s for org-src-window-setup"
- (symbol-name org-src-window-setup))
- (org-pop-to-buffer-same-window buffer))))
-
-(defun org-src-construct-edit-buffer-name (org-buffer-name lang)
- "Construct the buffer name for a source editing buffer."
- (concat "*Org Src " org-buffer-name "[ " lang " ]*"))
-
-(defun org-src-edit-buffer-p (&optional buffer)
- "Test whether BUFFER (or the current buffer if BUFFER is nil)
-is a source block editing buffer."
- (let ((buffer (org-base-buffer (or buffer (current-buffer)))))
- (and (buffer-name buffer)
- (string-match "\\`*Org Src " (buffer-name buffer))
- (local-variable-p 'org-edit-src-beg-marker buffer)
- (local-variable-p 'org-edit-src-end-marker buffer))))
-
-(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 Src " (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))
+ (format-time-string "-%Y-%d-%m")
+ ".txt")))
+ ;; Move mark and point in edit buffer to the corresponding
+ ;; location.
+ (when mark-coordinates
+ (org-src--goto-coordinates mark-coordinates (point-min) (point-max))
+ (push-mark (point) 'no-message t)
+ (setq deactivate-mark nil))
+ (org-src--goto-coordinates point-coordinates (point-min) (point-max)))
+ ;; Install idle auto save feature, if necessary.
+ (or org-src--code-timer
+ (zerop org-edit-src-auto-save-idle-delay)
+ (setq org-src--code-timer
+ (run-with-idle-timer
+ org-edit-src-auto-save-idle-delay t
+ (lambda ()
+ (cond
+ ((org-src-edit-buffer-p)
+ (when (buffer-modified-p) (org-edit-src-save)))
+ ((not (org-some (lambda (b) (org-src-edit-buffer-p b))
+ (buffer-list)))
+ (cancel-timer org-src--code-timer)
+ (setq org-src--code-timer nil))))))))))
+
+
+
+;;; Fontification of source blocks
-(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
-a space character.
-An new buffer is created and the fixed-width region is copied into it,
-and the buffer is switched into `artist-mode' for editing. When done,
-exit with \\[org-edit-src-exit]. The edited text will then replace
-the fragment in the Org-mode buffer."
- (interactive)
- (let ((line (org-current-line))
- (col (current-column))
- (case-fold-search t)
- (msg (substitute-command-keys
- "Edit, then exit with C-c ' (C-c and single quote) -- C-c C-k to abort"))
- (org-mode-p (derived-mode-p 'org-mode))
- (beg (make-marker))
- (end (make-marker))
- (preserve-indentation org-src-preserve-indentation)
- block-nindent ovl beg1 end1 code begline buffer)
- (beginning-of-line 1)
- (if (looking-at "[ \t]*[^:\n \t]")
- nil
- (if (looking-at "[ \t]*\\(\n\\|\\'\\)")
- (setq beg1 (point) end1 beg1)
- (save-excursion
- (if (re-search-backward "^[ \t]*[^: \t]" nil 'move)
- (setq beg1 (point-at-bol 2))
- (setq beg1 (point))))
- (save-excursion
- (if (re-search-forward "^[ \t]*[^: \t]" nil 'move)
- (setq end1 (1- (match-beginning 0)))
- (setq end1 (point))))
- (org-goto-line line))
- (setq beg (move-marker beg beg1)
- end (move-marker end end1)
- code (buffer-substring-no-properties beg end)
- begline (save-excursion (goto-char beg) (org-current-line)))
- (if (and (setq buffer (org-edit-src-find-buffer beg end))
- (y-or-n-p "Return to existing edit buffer ([n] will revert changes)? "))
- (org-pop-to-buffer-same-window buffer)
- (when buffer
- (with-current-buffer buffer
- (if (boundp 'org-edit-src-overlay)
- (delete-overlay org-edit-src-overlay)))
- (kill-buffer buffer))
- (setq buffer (generate-new-buffer
- (org-src-construct-edit-buffer-name
- (buffer-name) "Fixed Width")))
- (setq ovl (make-overlay beg end))
- (overlay-put ovl 'face 'secondary-selection)
- (overlay-put ovl 'edit-buffer buffer)
- (overlay-put ovl 'help-echo "Click with mouse-1 to switch to buffer editing this segment")
- (overlay-put ovl 'face 'secondary-selection)
- (overlay-put ovl
- 'keymap
- (let ((map (make-sparse-keymap)))
- (define-key map [mouse-1] 'org-edit-src-continue)
- map))
- (overlay-put ovl :read-only "Leave me alone")
- (org-pop-to-buffer-same-window buffer)
- (insert code)
- (remove-text-properties (point-min) (point-max)
- '(display nil invisible nil intangible nil))
- (setq block-nindent (or (org-do-remove-indentation) 0))
- (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 ""))
- (org-goto-line (1+ (- line begline)))
- (org-move-to-column (max 0 (- col block-nindent 2)))
- (org-set-local 'org-edit-src-beg-marker beg)
- (org-set-local 'org-edit-src-end-marker end)
- (org-set-local 'org-edit-src-overlay ovl)
- (org-set-local 'org-edit-src-block-indentation block-nindent)
- (org-set-local 'org-edit-src-content-indentation 0)
- (org-set-local 'org-src-preserve-indentation nil)
- (org-src-mode)
- (set-buffer-modified-p nil)
- (and org-edit-src-persistent-message
- (org-set-local 'header-line-format msg)))
- (message "%s" msg)
- t)))
+(defun org-src-font-lock-fontify-block (lang start end)
+ "Fontify code block.
+This function is called by emacs automatic fontification, as long
+as `org-src-fontify-natively' is non-nil."
+ (let ((lang-mode (org-src--get-lang-mode lang)))
+ (when (fboundp lang-mode)
+ (let ((string (buffer-substring-no-properties start end))
+ (modified (buffer-modified-p))
+ (org-buffer (current-buffer)) pos next)
+ (remove-text-properties start end '(face nil))
+ (with-current-buffer
+ (get-buffer-create
+ (concat " org-src-fontification:" (symbol-name lang-mode)))
+ (delete-region (point-min) (point-max))
+ (insert string " ") ;; so there's a final property change
+ (unless (eq major-mode lang-mode) (funcall lang-mode))
+ (font-lock-fontify-buffer)
+ (setq pos (point-min))
+ (while (setq next (next-single-property-change pos 'face))
+ (put-text-property
+ (+ start (1- pos)) (1- (+ start next)) 'face
+ (get-text-property pos 'face) org-buffer)
+ (setq pos next)))
+ (add-text-properties
+ start end
+ '(font-lock-fontified t fontified t font-lock-multiline t))
+ (set-buffer-modified-p modified)))))
+
+
+
+;;; Escape contents
(defun org-escape-code-in-region (beg end)
"Escape lines between BEG and END.
@@ -571,152 +502,42 @@ with \",*\", \",#+\", \",,*\" and \",,#+\"."
(replace-regexp-in-string
"^[ \t]*,?\\(,\\)\\(?:\\*\\|#\\+\\)" "" s nil nil 1))
-(defun org-edit-src-exit (&optional context)
- "Exit special edit and protect problematic lines."
- (interactive)
- (unless (org-bound-and-true-p org-edit-src-from-org-mode)
- (error "This is not a sub-editing buffer, something is wrong"))
- (widen)
- (let* ((fixed-width-p (string-match "Fixed Width" (buffer-name)))
- (beg org-edit-src-beg-marker)
- (end org-edit-src-end-marker)
- (ovl org-edit-src-overlay)
- (bufstr (buffer-string))
- (buffer (current-buffer))
- (single (org-bound-and-true-p org-edit-src-force-single-line))
- (macro (eq single 'macro-definition))
- (total-nindent (+ (or org-edit-src-block-indentation 0)
- org-edit-src-content-indentation))
- (preserve-indentation org-src-preserve-indentation)
- (allow-write-back-p (org-bound-and-true-p org-edit-src-allow-write-back-p))
- (delta 0) code line col indent)
- (when allow-write-back-p
- (unless preserve-indentation (untabify (point-min) (point-max)))
- (if org-src-strip-leading-and-trailing-blank-lines
- (save-excursion
- (goto-char (point-min))
- (if (looking-at "[ \t\n]*\n") (replace-match ""))
- (unless macro
- (if (re-search-forward "\n[ \t\n]*\\'" nil t) (replace-match ""))))))
- (setq line (if (org-bound-and-true-p org-edit-src-force-single-line)
- 1
- (org-current-line))
- col (current-column))
- (when allow-write-back-p
- (when single
- (goto-char (point-min))
- (if (re-search-forward "\\s-+\\'" nil t) (replace-match ""))
- (goto-char (point-min))
- (let ((cnt 0))
- (while (re-search-forward "\n" nil t)
- (setq cnt (1+ cnt))
- (replace-match (if macro "\\n" " ") t t))
- (when (and macro (> cnt 0))
- (goto-char (point-max)) (insert "\\n")))
- (goto-char (point-min))
- (if (looking-at "\\s-*") (replace-match " ")))
- (when (and (org-bound-and-true-p org-edit-src-from-org-mode)
- (not fixed-width-p))
- (org-escape-code-in-region (point-min) (point-max))
- (setq delta (+ delta
- (save-excursion
- (org-goto-line line)
- (if (looking-at "[ \t]*\\(,,\\)?\\(\\*\\|#+\\)") 1
- 0)))))
- (when (org-bound-and-true-p org-edit-src-picture)
- (setq preserve-indentation nil)
- (untabify (point-min) (point-max))
- (goto-char (point-min))
- (while (re-search-forward "^" nil t)
- (replace-match ": ")))
- (unless (or single preserve-indentation (= total-nindent 0))
- (setq indent (make-string total-nindent ?\ ))
- (goto-char (point-min))
- (while (re-search-forward "\\(^\\).+" nil t)
- (replace-match indent nil nil nil 1)))
- (if (org-bound-and-true-p org-edit-src-picture)
- (setq total-nindent (+ total-nindent 2)))
- (setq code (buffer-string))
- (when (eq context 'save)
- (erase-buffer)
- (insert bufstr))
- (set-buffer-modified-p nil))
- (org-src-switch-to-buffer (marker-buffer beg) (or context 'exit))
- (if (eq context 'save) (save-buffer)
- (with-current-buffer buffer
- (set-buffer-modified-p nil))
- (kill-buffer buffer))
- (goto-char beg)
- (when allow-write-back-p
- (undo-boundary)
- (delete-region beg (max beg end))
- (unless (string-match "\\`[ \t]*\\'" code)
- (insert code))
- ;; Make sure the overlay stays in place
- (when (eq context 'save) (move-overlay ovl beg (point)))
- (goto-char beg)
- (if single (just-one-space)))
- (if (memq t (mapcar (lambda (overlay)
- (eq (overlay-get overlay 'invisible)
- 'org-hide-block))
- (overlays-at (point))))
- ;; Block is hidden; put point at start of block
- (beginning-of-line 0)
- ;; Block is visible, put point where it was in the code buffer
- (when allow-write-back-p
- (org-goto-line (1- (+ (org-current-line) line)))
- (org-move-to-column (if preserve-indentation col (+ col total-nindent delta)))))
- (unless (eq context 'save)
- (move-marker beg nil)
- (move-marker end nil)))
- (unless (eq context 'save)
- (when org-edit-src-saved-temp-window-config
- (set-window-configuration org-edit-src-saved-temp-window-config)
- (setq org-edit-src-saved-temp-window-config nil))))
-(defun org-edit-src-abort ()
- "Abort editing of the src code and return to the Org buffer."
- (interactive)
- (let (org-edit-src-allow-write-back-p)
- (org-edit-src-exit 'exit)))
-
-(defmacro org-src-in-org-buffer (&rest body)
- `(let ((p (point)) (m (mark)) (ul buffer-undo-list) msg)
- (save-window-excursion
- (org-edit-src-exit 'save)
- ,@body
- (setq msg (current-message))
- (if (eq org-src-window-setup 'other-frame)
- (let ((org-src-window-setup 'current-window))
- (org-edit-src-code 'save))
- (org-edit-src-code 'save)))
- (setq buffer-undo-list ul)
- (push-mark m 'nomessage)
- (goto-char (min p (point-max)))
- (message (or msg ""))))
-(def-edebug-spec org-src-in-org-buffer (body))
+
+;;; Org src minor mode
-(defun org-edit-src-save ()
- "Save parent buffer with current state source-code buffer."
- (interactive)
- (if (string-match "Fixed Width" (buffer-name))
- (user-error "Use C-c ' to save and exit, C-c C-k to abort editing")
- (org-src-in-org-buffer (save-buffer))))
+(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-c\C-k" 'org-edit-src-abort)
+(define-key org-src-mode-map "\C-x\C-s" 'org-edit-src-save)
-(defun org-src-tangle (arg)
- "Tangle the parent buffer."
- (interactive)
- (org-src-in-org-buffer (org-babel-tangle arg)))
+(defcustom org-src-ask-before-returning-to-edit-buffer t
+ "If nil, when org-edit-src code is used on a block that already
+has an active edit buffer, it will switch to that edit buffer
+immediately; otherwise it will ask whether you want to return to
+the existing edit buffer."
+ :group 'org-edit-structure
+ :version "24.4"
+ :package-version '(Org . "8.0")
+ :type 'boolean)
+
+(define-minor-mode org-src-mode
+ "Minor mode for language major mode buffers generated by org.
+This minor mode is turned on in two situations:
+- when editing a source code snippet with \"C-c '\".
+- When formatting a source code snippet for export with htmlize.
+There is a mode hook, and keybindings for `org-edit-src-exit' and
+`org-edit-src-save'")
(defun org-src-mode-configure-edit-buffer ()
- (when (org-bound-and-true-p org-edit-src-from-org-mode)
+ (when (org-bound-and-true-p org-src--from-org-mode)
(org-add-hook 'kill-buffer-hook
- #'(lambda () (delete-overlay org-edit-src-overlay)) nil 'local)
- (if (org-bound-and-true-p org-edit-src-allow-write-back-p)
+ (lambda () (delete-overlay org-src--overlay)) nil 'local)
+ (if (org-bound-and-true-p org-src--allow-write-back-p)
(progn
(setq buffer-offer-save t)
(setq buffer-file-name
- (concat (buffer-file-name (marker-buffer org-edit-src-beg-marker))
+ (concat (buffer-file-name (marker-buffer org-src--beg-marker))
"[" (buffer-name) "]"))
(if (featurep 'xemacs)
(progn
@@ -725,8 +546,11 @@ with \",*\", \",#+\", \",,*\" and \",,#+\"."
(setq write-contents-functions '(org-edit-src-save))))
(setq buffer-read-only t))))
-(org-add-hook 'org-src-mode-hook 'org-src-mode-configure-edit-buffer)
+(org-add-hook 'org-src-mode-hook #'org-src-mode-configure-edit-buffer)
+
+
+;;; Babel related functions
(defun org-src-associate-babel-session (info)
"Associate edit buffer with comint session."
@@ -739,17 +563,18 @@ with \",*\", \",#+\", \",,*\" and \",,#+\"."
(and (fboundp f) (funcall f session))))))
(defun org-src-babel-configure-edit-buffer ()
- (when org-src-babel-info
- (org-src-associate-babel-session org-src-babel-info)))
+ (when org-src--babel-info
+ (org-src-associate-babel-session org-src--babel-info)))
+
+(org-add-hook 'org-src-mode-hook #'org-src-babel-configure-edit-buffer)
-(org-add-hook 'org-src-mode-hook 'org-src-babel-configure-edit-buffer)
(defmacro org-src-do-at-code-block (&rest body)
- "Execute a command from an edit buffer in the Org-mode buffer."
- `(let ((beg-marker org-edit-src-beg-marker))
- (if beg-marker
- (with-current-buffer (marker-buffer beg-marker)
- (goto-char (marker-position beg-marker))
- ,@body))))
+ "Execute a command from an edit buffer in the Org mode buffer."
+ `(let ((beg-marker org-src--beg-marker))
+ (when beg-marker
+ (with-current-buffer (marker-buffer beg-marker)
+ (goto-char beg-marker)
+ ,@body))))
(def-edebug-spec org-src-do-at-code-block (body))
(defun org-src-do-key-sequence-at-code-block (&optional key)
@@ -774,45 +599,230 @@ Org-babel commands."
(if (equal key (kbd "C-g")) (keyboard-quit)
(org-edit-src-save)
(org-src-do-at-code-block
- (call-interactively
- (lookup-key org-babel-map key)))))
+ (call-interactively (lookup-key org-babel-map key)))))
+
+
+
+;;; Public functions
+
+(defun org-src-edit-buffer-p (&optional buffer)
+ "Non-nil when current buffer is a source editing buffer.
+If BUFFER is non-nil, test it instead."
+ (let ((buffer (org-base-buffer (or buffer (current-buffer)))))
+ (and (buffer-live-p buffer)
+ (local-variable-p 'org-src--beg-marker buffer)
+ (local-variable-p 'org-src--end-marker buffer))))
+
+(defun org-src-switch-to-buffer (buffer context)
+ (case org-src-window-setup
+ (current-window (org-pop-to-buffer-same-window buffer))
+ (other-window
+ (switch-to-buffer-other-window buffer))
+ (other-frame
+ (case context
+ (exit
+ (let ((frame (selected-frame)))
+ (switch-to-buffer-other-frame buffer)
+ (delete-frame frame)))
+ (save
+ (kill-buffer (current-buffer))
+ (org-pop-to-buffer-same-window buffer))
+ (t (switch-to-buffer-other-frame buffer))))
+ (reorganize-frame
+ (when (eq context 'edit) (delete-other-windows))
+ (org-switch-to-buffer-other-window buffer)
+ (when (eq context 'exit) (delete-other-windows)))
+ (switch-invisibly (set-buffer buffer))
+ (t
+ (message "Invalid value %s for `org-src-window-setup'"
+ org-src-window-setup)
+ (org-pop-to-buffer-same-window buffer))))
+
+(defun org-edit-table.el ()
+ "Edit \"table.el\" table at point.
+
+A new buffer is created and the table is copied into it. Then
+the table is recognized with `table-recognize'. When done
+editing, exit with \\[org-edit-src-exit]. The edited text will
+then replace the area in the Org mode buffer.
+
+Throw an error when not at such a table."
+ (interactive)
+ (let ((element (org-element-at-point)))
+ (unless (and (eq (org-element-type element) 'table)
+ (eq (org-element-property :type element) 'table.el)
+ (org-src--on-element-p element))
+ (user-error "Not in a table.el table"))
+ (org-src--edit-element
+ element
+ (org-src--construct-edit-buffer-name (buffer-name) "Table")
+ #'text-mode t)
+ (when (org-bound-and-true-p flyspell-mode) (flyspell-mode -1))
+ (table-recognize)
+ t))
+
+(defun org-edit-export-block ()
+ "Edit export block at point.
+
+A new buffer is created and the block is copied into it, and the
+buffer is switched into an appropriate major mode. See also
+`org-src-lang-modes'. When done, exit with
+\\[org-edit-src-exit]. The edited text will then replace the
+area in the Org mode buffer.
+
+Throw an error when not at an export block."
+ (interactive)
+ (let ((element (org-element-at-point)))
+ (unless (and (eq (org-element-type element) 'export-block)
+ (org-src--on-element-p element))
+ (user-error "Not in an export block"))
+ (let* ((type (downcase (org-element-property :type element)))
+ (mode (org-src--get-lang-mode type)))
+ (unless (functionp mode) (error "No such language mode: %s" mode))
+ (org-src--edit-element
+ element (org-src--construct-edit-buffer-name (buffer-name) type) mode t))
+ t))
+
+(defun org-edit-src-code (&optional code edit-buffer-name)
+ "Edit the source or example block at point.
+
+The code is copied to a separate buffer and the appropriate mode
+is turned on. When done, exit with \\[org-edit-src-exit]. This
+will remove the original code in the Org buffer, and replace it
+with the edited version. See `org-src-window-setup' to configure
+the display of windows containing the Org buffer and the code
+buffer.
+
+When optional argument CODE is a string, edit it in a dedicated
+buffer instead.
+
+When optional argument EDIT-BUFFER-NAME is non-nil, use it as the
+name of the sub-editing buffer."
+ (interactive)
+ (let* ((element (org-element-at-point))
+ (type (org-element-type element)))
+ (unless (and (memq type '(example-block src-block))
+ (org-src--on-element-p element))
+ (user-error "Not in a source or example block"))
+ (let* ((lang
+ (if (eq type 'src-block) (org-element-property :language element)
+ "example"))
+ (lang-f (and (eq type 'src-block) (org-src--get-lang-mode lang)))
+ (babel-info (and (eq type 'src-block)
+ (org-babel-get-src-block-info 'light))))
+ (when (and (eq type 'src-block) (not (functionp lang-f)))
+ (error "No such language mode: %s" lang-f))
+ (org-src--edit-element
+ element
+ (or edit-buffer-name
+ (org-src--construct-edit-buffer-name (buffer-name) lang))
+ lang-f (null code) (and code (org-unescape-code-in-string code)))
+ ;; Finalize buffer.
+ (org-set-local 'org-coderef-label-format
+ (or (org-element-property :label-fmt element)
+ org-coderef-label-format))
+ (when (eq type 'src-block)
+ (org-set-local 'org-src--babel-info babel-info)
+ (let ((edit-prep-func (intern (concat "org-babel-edit-prep:" lang))))
+ (when (fboundp edit-prep-func)
+ (funcall edit-prep-func babel-info))))
+ t)))
+
+(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 a space or a newline character.
+
+A new buffer is created and the fixed-width region is copied into
+it, and the buffer is switched into the major mode defined in
+`org-edit-fixed-width-region-mode', which see. When done, exit
+with \\[org-edit-src-exit]. The edited text will then replace
+the area in the Org mode buffer."
+ (interactive)
+ (let ((element (org-element-at-point)))
+ (unless (and (eq (org-element-type element) 'fixed-width)
+ (org-src--on-element-p element))
+ (user-error "Not in a fixed-width area"))
+ (org-src--edit-element
+ element
+ (org-src--construct-edit-buffer-name (buffer-name) "Fixed Width")
+ org-edit-fixed-width-region-mode
+ t)
+ ;; Return success.
+ t))
+
+(defun org-edit-src-abort ()
+ "Abort editing of the src code and return to the Org buffer."
+ (interactive)
+ (let (org-src--allow-write-back-p) (org-edit-src-exit)))
+
+(defun org-edit-src-continue (e)
+ "Unconditionally return to buffer editing area under point.
+Throw an error if there is no such buffer."
+ (interactive "e")
+ (mouse-set-point e)
+ (let ((buf (get-char-property (point) 'edit-buffer)))
+ (if buf (org-src-switch-to-buffer buf 'continue)
+ (user-error "No sub-editing buffer for area at point"))))
+
+(defun org-edit-src-save ()
+ "Save parent buffer with current state source-code buffer."
+ (interactive)
+ (unless (org-src-edit-buffer-p) (user-error "Not in a sub-editing buffer"))
+ (set-buffer-modified-p nil)
+ (let ((edited-code (org-src--contents-for-write-back))
+ (beg org-src--beg-marker)
+ (end org-src--end-marker)
+ (overlay org-src--overlay))
+ (with-current-buffer (org-src--source-buffer)
+ (undo-boundary)
+ (delete-region beg end)
+ (when (org-string-nw-p edited-code) (insert edited-code))
+ (unless (bolp) (insert "\n"))
+ (move-overlay overlay beg (point))
+ (save-buffer))))
+
+(defun org-edit-src-exit ()
+ "Kill current sub-editing buffer and return to source buffer."
+ (interactive)
+ (unless (org-src-edit-buffer-p) (error "Not in a sub-editing buffer"))
+ (let* ((allow-write-back-p org-src--allow-write-back-p)
+ (beg org-src--beg-marker)
+ (end org-src--end-marker)
+ (coordinates (org-src--coordinates (point) 1 (point-max)))
+ (code (and allow-write-back-p (org-src--contents-for-write-back))))
+ (set-buffer-modified-p nil)
+ ;; Switch to source buffer. Kill sub-editing buffer.
+ (let ((edit-buffer (current-buffer)))
+ (org-src-switch-to-buffer (marker-buffer beg) 'exit)
+ (kill-buffer edit-buffer))
+ ;; Insert modified code. Ensure it ends with a newline character.
+ (when (and allow-write-back-p
+ (not (equal (buffer-substring-no-properties beg end) code)))
+ (undo-boundary)
+ (goto-char beg)
+ (delete-region beg end)
+ (when (org-string-nw-p code)
+ (insert code)
+ (unless (bolp) (insert "\n"))))
+ ;; If we are to return to source buffer, put point at an
+ ;; appropriate location. In particular, if block is hidden, move
+ ;; to the beginning of the block opening line.
+ (goto-char beg)
+ (cond
+ ;; Block is hidden; move at start of block.
+ ((org-some (lambda (o) (eq (overlay-get o 'invisible) 'org-hide-block))
+ (overlays-at (point)))
+ (beginning-of-line 0))
+ (allow-write-back-p (org-src--goto-coordinates coordinates beg end)))
+ ;; Clean up left-over markers and restore window configuration.
+ (set-marker beg nil)
+ (set-marker end nil)
+ (when org-src--saved-temp-window-config
+ (set-window-configuration org-src--saved-temp-window-config)
+ (setq org-src--saved-temp-window-config nil))))
-(defun org-src-font-lock-fontify-block (lang start end)
- "Fontify code block.
-This function is called by emacs automatic fontification, as long
-as `org-src-fontify-natively' is non-nil."
- (let ((lang-mode (org-src-get-lang-mode lang)))
- (if (fboundp lang-mode)
- (let ((string (buffer-substring-no-properties start end))
- (modified (buffer-modified-p))
- (org-buffer (current-buffer)) pos next)
- (remove-text-properties start end '(face nil))
- (with-current-buffer
- (get-buffer-create
- (concat " org-src-fontification:" (symbol-name lang-mode)))
- (delete-region (point-min) (point-max))
- (insert string " ") ;; so there's a final property change
- (unless (eq major-mode lang-mode) (funcall lang-mode))
- (font-lock-fontify-buffer)
- (setq pos (point-min))
- (while (setq next (next-single-property-change pos 'face))
- (put-text-property
- (+ start (1- pos)) (1- (+ start next)) 'face
- (get-text-property pos 'face) org-buffer)
- (setq pos next)))
- (add-text-properties
- start end
- '(font-lock-fontified t fontified t font-lock-multiline t))
- (set-buffer-modified-p modified)))))
-
-(defun org-src-get-lang-mode (lang)
- "Return major mode that should be used for LANG.
-LANG is a string, and the returned major mode is a symbol."
- (intern
- (concat
- (let ((l (or (cdr (assoc lang org-src-lang-modes)) lang)))
- (if (symbolp l) (symbol-name l) l))
- "-mode")))
(provide 'org-src)
diff --git a/lisp/org.el b/lisp/org.el
index 6ab13f4..f9281ab 100755
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -22745,8 +22745,7 @@ Also align node properties according to `org-property-format'."
(goto-char (org-element-property :end element))
(skip-chars-backward " \r\t\n")
(line-beginning-position))))
- (let ((org-src-strip-leading-and-trailing-blank-lines nil))
- (org-babel-do-key-sequence-in-edit-buffer (kbd "TAB"))))
+ (org-babel-do-key-sequence-in-edit-buffer (kbd "TAB")))
(t
(let ((column (org--get-expected-indentation element nil)))
;; Preserve current column.
@@ -22854,9 +22853,7 @@ assumed to be significant there."
;; `org-src-tab-acts-natively' is non-nil.
(when (and (< (point) end) org-src-tab-acts-natively)
(ignore-errors
- (let (org-src-strip-leading-and-trailing-blank-lines
- ;; Region boundaries in edit buffer.
- (start (1+ (- (point) cbeg)))
+ (let ((start (1+ (- (point) cbeg)))
(end (- (min cend end) cbeg)))
(org-babel-do-in-edit-buffer
(indent-region start end))))))