summaryrefslogtreecommitdiff
path: root/lisp/org/org-src.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/org/org-src.el')
-rw-r--r--lisp/org/org-src.el123
1 files changed, 79 insertions, 44 deletions
diff --git a/lisp/org/org-src.el b/lisp/org/org-src.el
index 496dafe5e77..9d6bc1aa2c8 100644
--- a/lisp/org/org-src.el
+++ b/lisp/org/org-src.el
@@ -41,6 +41,7 @@
(declare-function org-at-table.el-p "org" ())
(declare-function org-get-indentation "org" (&optional line))
(declare-function org-switch-to-buffer-other-window "org" (&rest args))
+(declare-function org-strip-protective-commas "org" (beg end))
(declare-function org-pop-to-buffer-same-window
"org-compat" (&optional buffer-or-name norecord label))
(declare-function org-strip-protective-commas "org" (beg end))
@@ -112,8 +113,7 @@ editing it with \\[org-edit-src-code]. Has no effect if
: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.")
+ "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.
@@ -130,7 +130,7 @@ current-window Show edit buffer in the current window, keeping all other
windows.
other-window Use `switch-to-buffer-other-window' to display edit buffer.
reorganize-frame Show only two windows on the current frame, the current
- window and the edit buffer. When exiting the edit buffer,
+ window and the edit buffer. When exiting the edit buffer,
return to one window.
other-frame Use `switch-to-buffer-other-frame' to display edit buffer.
Also, when exiting the edit buffer, kill that frame."
@@ -174,6 +174,7 @@ For example, there is no ocaml-mode in Emacs, but the mode to use is
(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)
(defvar org-edit-src-force-single-line nil)
(defvar org-edit-src-from-org-mode nil)
@@ -187,9 +188,9 @@ For example, there is no ocaml-mode in Emacs, but the mode to use is
(defvar 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.")
+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.")
(defvar org-src-babel-info nil)
@@ -202,13 +203,13 @@ There is a mode hook, and keybindings for `org-edit-src-exit' and
`org-edit-src-save'")
(defun org-edit-src-code (&optional context code edit-buffer-name)
- "Edit the source code example at point.
+ "Edit the source CODE example at point.
The example is copied to a separate buffer, and that buffer is
switched to the correct language mode. 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. Optional
+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
+this function. See `org-src-window-setup' to configure the
display of windows containing the Org buffer and the code
buffer."
(interactive)
@@ -271,8 +272,9 @@ buffer."
(setq line (org-current-line)
col (current-column)))
(if (and (setq buffer (org-edit-src-find-buffer beg end))
- (if org-src-ask-before-returning-to-edit-buffer
- (y-or-n-p "Return to existing edit buffer? [n] will revert changes: ") t))
+ (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
@@ -309,7 +311,7 @@ buffer."
(error "Language mode `%s' fails with: %S" lang-f (nth 1 e)))))
(dolist (pair transmitted-variables)
(org-set-local (car pair) (cadr pair)))
- (if (eq major-mode 'org-mode)
+ (if (derived-mode-p 'org-mode)
(progn
(goto-char (point-min))
(while (re-search-forward "^," nil t)
@@ -328,6 +330,7 @@ buffer."
(if org-src-preserve-indentation col (max 0 (- col total-nindent))))
(org-src-mode)
(set-buffer-modified-p nil)
+ (setq buffer-file-name nil)
(and org-edit-src-persistent-message
(org-set-local 'header-line-format msg))
(let ((edit-prep-func (intern (concat "org-babel-edit-prep:" lang))))
@@ -336,6 +339,7 @@ buffer."
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)))
@@ -412,7 +416,7 @@ the fragment in the Org-mode buffer."
(case-fold-search t)
(msg (substitute-command-keys
"Edit, then exit with C-c ' (C-c and single quote)"))
- (org-mode-p (eq major-mode 'org-mode))
+ (org-mode-p (derived-mode-p 'org-mode))
(beg (make-marker))
(end (make-marker))
(preserve-indentation org-src-preserve-indentation)
@@ -436,7 +440,7 @@ the fragment in the Org-mode buffer."
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: "))
+ (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
@@ -452,10 +456,10 @@ the fragment in the Org-mode 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))
+ '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)
@@ -586,6 +590,21 @@ the language, a switch telling if the content should be in a single line."
(goto-char pos)
(org-get-indentation)))
+(defun org-add-protective-commas (beg end &optional line)
+ "Add protective commas in region.
+Return the delta in size of the region."
+ (interactive "r")
+ (let ((org-re "^\\(.\\)")
+ (other-re "^\\([*]\\|[ \t]*#\\+\\)")
+ (delta 0))
+ (save-excursion
+ (goto-char beg)
+ (while (re-search-forward (if (derived-mode-p 'org-mode) org-re other-re)
+ end t)
+ (if (and line (eq (org-current-line) line)) (setq delta (1+ delta)))
+ (replace-match ",\\1")))
+ delta))
+
(defun org-edit-src-exit (&optional context)
"Exit special edit and protect problematic lines."
(interactive)
@@ -595,6 +614,7 @@ the language, a switch telling if the content should be in a single line."
(let* ((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))
@@ -629,11 +649,8 @@ the language, a switch telling if the content should be in a single line."
(goto-char (point-min))
(if (looking-at "\\s-*") (replace-match " ")))
(when (org-bound-and-true-p org-edit-src-from-org-mode)
- (goto-char (point-min))
- (while (re-search-forward
- (if (eq major-mode 'org-mode) "^\\(.\\)" "^\\([*]\\|[ \t]*#\\+\\)") nil t)
- (if (eq (org-current-line) line) (setq delta (1+ delta)))
- (replace-match ",\\1")))
+ (setq delta (+ delta (org-add-protective-commas
+ (point-min) (point-max) line))))
(when (org-bound-and-true-p org-edit-src-picture)
(setq preserve-indentation nil)
(untabify (point-min) (point-max))
@@ -648,13 +665,18 @@ the language, a switch telling if the content should be in a single line."
(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))
- (kill-buffer buffer)
+ (if (eq context 'save) (save-buffer)
+ (kill-buffer buffer))
(goto-char beg)
(when allow-write-back-p
- (delete-region beg end)
+ (delete-region beg (1- end))
(insert code)
+ (delete-char 1)
(goto-char beg)
(if single (just-one-space)))
(if (memq t (mapcar (lambda (overlay)
@@ -666,28 +688,41 @@ the language, a switch telling if the content should be in a single line."
;; Block is visible, put point where it was in the code buffer
(org-goto-line (1- (+ (org-current-line) line)))
(org-move-to-column (if preserve-indentation col (+ col total-nindent delta))))
- (move-marker beg nil)
- (move-marker end nil))
+ (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))))
+(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))
+
(defun org-edit-src-save ()
"Save parent buffer with current state source-code buffer."
(interactive)
- (let ((p (point)) (m (mark)) msg)
- (save-window-excursion
- (org-edit-src-exit 'save)
- (save-buffer)
- (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)))
- (push-mark m 'nomessage)
- (goto-char (min p (point-max)))
- (message (or msg ""))))
+ (org-src-in-org-buffer (save-buffer)))
+
+(declare-function org-babel-tangle "ob-tangle" (&optional only-this-block target-file lang))
+
+(defun org-src-tangle (arg)
+ "Tangle the parent buffer."
+ (interactive)
+ (org-src-in-org-buffer (org-babel-tangle arg)))
(defun org-src-mode-configure-edit-buffer ()
(when (org-bound-and-true-p org-edit-src-from-org-mode)
@@ -739,7 +774,7 @@ remotely with point temporarily at the start of the code block in
the Org buffer.
This command is not bound to a key by default, to avoid conflicts
-with language major mode bindings. To bind it to C-c @ in all
+with language major mode bindings. To bind it to C-c @ in all
language major modes, you could use
(add-hook 'org-src-mode-hook
@@ -777,7 +812,7 @@ mode."
(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. For manual
+as `org-src-fontify-natively' is non-nil. For manual
fontification of code blocks see `org-src-fontify-block' and
`org-src-fontify-buffer'"
(let ((lang-mode (org-src-get-lang-mode lang)))
@@ -790,13 +825,13 @@ fontification of code blocks see `org-src-fontify-block' and
(get-buffer-create
(concat " org-src-fontification:" (symbol-name lang-mode)))
(delete-region (point-min) (point-max))
- (insert (concat string " ")) ;; so there's a final property change
+ (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)) (+ start next) 'face
+ (+ start (1- pos)) (1- (+ start next)) 'face
(get-text-property pos 'face) org-buffer)
(setq pos next)))
(add-text-properties
@@ -813,7 +848,7 @@ fontification of code blocks see `org-src-fontify-block' and
(font-lock-fontify-region (nth 0 info) (nth 1 info)))))
(defun org-src-fontify-buffer ()
- "Fontify all code blocks in the current buffer"
+ "Fontify all code blocks in the current buffer."
(interactive)
(org-babel-map-src-blocks nil
(org-src-fontify-block)))