Don't quote lambda expressions with `quote'.
[bpt/emacs.git] / lisp / org / org-src.el
CommitLineData
c8d0cf5c
CD
1;;; org-src.el --- Source code examples in Org
2;;
95df8112 3;; Copyright (C) 2004-2011 Free Software Foundation, Inc.
c8d0cf5c
CD
4;;
5;; Author: Carsten Dominik <carsten at orgmode dot org>
6;; Bastien Guerry <bzg AT altern DOT org>
8bfe682a 7;; Dan Davison <davison at stats dot ox dot ac dot uk>
c8d0cf5c
CD
8;; Keywords: outlines, hypermedia, calendar, wp
9;; Homepage: http://orgmode.org
acedf35c 10;; Version: 7.4
c8d0cf5c
CD
11;;
12;; This file is part of GNU Emacs.
13;;
14;; GNU Emacs is free software: you can redistribute it and/or modify
15;; it under the terms of the GNU General Public License as published by
16;; the Free Software Foundation, either version 3 of the License, or
17;; (at your option) any later version.
18
19;; GNU Emacs is distributed in the hope that it will be useful,
20;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22;; GNU General Public License for more details.
23
24;; You should have received a copy of the GNU General Public License
25;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
27;;
28;;; Commentary:
29
30;; This file contains the code dealing with source code examples in Org-mode.
31
32;;; Code:
33
34(require 'org-macs)
35(require 'org-compat)
afe98dfa
CD
36(require 'ob-keys)
37(require 'ob-comint)
8bfe682a
CD
38(eval-when-compile
39 (require 'cl))
c8d0cf5c
CD
40
41(declare-function org-do-remove-indentation "org" (&optional n))
ed21c5c8 42(declare-function org-at-table.el-p "org" ())
c8d0cf5c 43(declare-function org-get-indentation "org" (&optional line))
8bfe682a 44(declare-function org-switch-to-buffer-other-window "org" (&rest args))
c8d0cf5c
CD
45
46(defcustom org-edit-src-region-extra nil
47 "Additional regexps to identify regions for editing with `org-edit-src-code'.
48For examples see the function `org-edit-src-find-region-and-lang'.
49The regular expression identifying the begin marker should end with a newline,
50and the regexp marking the end line should start with a newline, to make sure
51there are kept outside the narrowed region."
52 :group 'org-edit-structure
53 :type '(repeat
54 (list
55 (regexp :tag "begin regexp")
56 (regexp :tag "end regexp")
57 (choice :tag "language"
58 (string :tag "specify")
59 (integer :tag "from match group")
60 (const :tag "from `lang' element")
61 (const :tag "from `style' element")))))
62
63(defcustom org-coderef-label-format "(ref:%s)"
64 "The default coderef format.
65This format string will be used to search for coderef labels in literal
66examples (EXAMPLE and SRC blocks). The format can be overwritten in
86fbb8ca 67an individual literal example with the -l option, like
c8d0cf5c
CD
68
69#+BEGIN_SRC pascal +n -r -l \"((%s))\"
70...
71#+END_SRC
72
73If you want to use this for HTML export, make sure that the format does
74not introduce special font-locking, and avoid the HTML special
75characters `<', `>', and `&'. The reason for this restriction is that
76the labels are searched for only after htmlize has done its job."
77 :group 'org-edit-structure ; FIXME this is not in the right group
78 :type 'string)
79
80(defcustom org-edit-fixed-width-region-mode 'artist-mode
81 "The mode that should be used to edit fixed-width regions.
82These are the regions where each line starts with a colon."
83 :group 'org-edit-structure
84 :type '(choice
85 (const artist-mode)
86 (const picture-mode)
87 (const fundamental-mode)
88 (function :tag "Other (specify)")))
89
8bfe682a 90(defcustom org-src-preserve-indentation nil
86fbb8ca
CD
91 "If non-nil preserve leading whitespace characters on export.
92If non-nil leading whitespace characters in source code blocks
93are preserved on export, and when switching between the org
94buffer and the language mode edit buffer. If this variable is nil
95then, after editing with \\[org-edit-src-code], the
8bfe682a
CD
96minimum (across-lines) number of leading whitespace characters
97are removed from all lines, and the code block is uniformly
98indented according to the value of `org-edit-src-content-indentation'."
99 :group 'org-edit-structure
100 :type 'boolean)
101
c8d0cf5c 102(defcustom org-edit-src-content-indentation 2
8bfe682a 103 "Indentation for the content of a source code block.
c8d0cf5c
CD
104This should be the number of spaces added to the indentation of the #+begin
105line in order to compute the indentation of the block content after
86fbb8ca 106editing it with \\[org-edit-src-code]. Has no effect if
8bfe682a 107`org-src-preserve-indentation' is non-nil."
c8d0cf5c
CD
108 :group 'org-edit-structure
109 :type 'integer)
110
afe98dfa
CD
111(defvar org-src-strip-leading-and-trailing-blank-lines nil
112 "If non-nil, blank lines are removed when exiting the code edit
113buffer.")
114
c8d0cf5c
CD
115(defcustom org-edit-src-persistent-message t
116 "Non-nil means show persistent exit help message while editing src examples.
117The message is shown in the header-line, which will be created in the
118first line of the window showing the editing buffer.
119When nil, the message will only be shown intermittently in the echo area."
120 :group 'org-edit-structure
121 :type 'boolean)
122
8bfe682a
CD
123(defcustom org-src-window-setup 'reorganize-frame
124 "How the source code edit buffer should be displayed.
125Possible values for this option are:
126
127current-window Show edit buffer in the current window, keeping all other
128 windows.
129other-window Use `switch-to-buffer-other-window' to display edit buffer.
130reorganize-frame Show only two windows on the current frame, the current
131 window and the edit buffer. When exiting the edit buffer,
132 return to one window.
133other-frame Use `switch-to-buffer-other-frame' to display edit buffer.
134 Also, when exiting the edit buffer, kill that frame."
135 :group 'org-edit-structure
136 :type '(choice
137 (const current-window)
138 (const other-frame)
139 (const other-window)
140 (const reorganize-frame)))
141
c8d0cf5c
CD
142(defvar org-src-mode-hook nil
143 "Hook run after Org switched a source code snippet to its Emacs mode.
144This hook will run
145
146- when editing a source code snippet with \"C-c '\".
147- When formatting a source code snippet for export with htmlize.
148
149You may want to use this hook for example to turn off `outline-minor-mode'
150or similar things which you want to have when editing a source code file,
151but which mess up the display of a snippet in Org exported files.")
152
54a0dee5 153(defcustom org-src-lang-modes
8d642074 154 '(("ocaml" . tuareg) ("elisp" . emacs-lisp) ("ditaa" . artist)
afe98dfa
CD
155 ("asymptote" . asy) ("dot" . fundamental) ("sqlite" . sql)
156 ("calc" . fundamental))
54a0dee5
CD
157 "Alist mapping languages to their major mode.
158The key is the language name, the value is the string that should
159be inserted as the name of the major mode. For many languages this is
160simple, but for language where this is not the case, this variable
161provides a way to simplify things on the user side.
162For example, there is no ocaml-mode in Emacs, but the mode to use is
163`tuareg-mode'."
164 :group 'org-edit-structure
165 :type '(repeat
166 (cons
167 (string "Language name")
168 (symbol "Major mode"))))
169
c8d0cf5c
CD
170;;; Editing source examples
171
b016851c
SM
172(defvar org-src-mode-map
173 (let ((map (make-sparse-keymap)))
174 (define-key map "\C-c'" 'org-edit-src-exit)
175 map))
afe98dfa 176
c8d0cf5c
CD
177(defvar org-edit-src-force-single-line nil)
178(defvar org-edit-src-from-org-mode nil)
86fbb8ca 179(defvar org-edit-src-allow-write-back-p t)
c8d0cf5c
CD
180(defvar org-edit-src-picture nil)
181(defvar org-edit-src-beg-marker nil)
182(defvar org-edit-src-end-marker nil)
183(defvar org-edit-src-overlay nil)
8bfe682a
CD
184(defvar org-edit-src-block-indentation nil)
185(defvar org-edit-src-saved-temp-window-config nil)
186
187(defvar org-src-ask-before-returning-to-edit-buffer t
188 "If nil, when org-edit-src code is used on a block that already
189 has an active edit buffer, it will switch to that edit buffer
190 immediately; otherwise it will ask whether you want to return
191 to the existing edit buffer.")
c8d0cf5c 192
afe98dfa
CD
193(defvar org-src-babel-info nil)
194
c8d0cf5c
CD
195(define-minor-mode org-src-mode
196 "Minor mode for language major mode buffers generated by org.
197This minor mode is turned on in two situations:
198- when editing a source code snippet with \"C-c '\".
199- When formatting a source code snippet for export with htmlize.
200There is a mode hook, and keybindings for `org-edit-src-exit' and
201`org-edit-src-save'")
202
afe98dfa 203(defun org-edit-src-code (&optional context code edit-buffer-name quietp)
c8d0cf5c 204 "Edit the source code example at point.
afe98dfa
CD
205The example is copied to a separate buffer, and that buffer is
206switched to the correct language mode. When done, exit with
207\\[org-edit-src-exit]. This will remove the original code in the
208Org buffer, and replace it with the edited version. Optional
209argument CONTEXT is used by \\[org-edit-src-save] when calling
210this function. See \\[org-src-window-setup] to configure the
211display of windows containing the Org buffer and the code
212buffer."
c8d0cf5c 213 (interactive)
8bfe682a
CD
214 (unless (eq context 'save)
215 (setq org-edit-src-saved-temp-window-config (current-window-configuration)))
afe98dfa 216 (let ((mark (and (org-region-active-p) (mark)))
c8d0cf5c 217 (case-fold-search t)
c8d0cf5c 218 (info (org-edit-src-find-region-and-lang))
afe98dfa 219 (babel-info (org-babel-get-src-block-info 'light))
c8d0cf5c
CD
220 (org-mode-p (eq major-mode 'org-mode))
221 (beg (make-marker))
222 (end (make-marker))
8bfe682a 223 (preserve-indentation org-src-preserve-indentation)
86fbb8ca 224 (allow-write-back-p (null code))
afe98dfa
CD
225 block-nindent total-nindent ovl lang lang-f single lfmt buffer msg
226 begline markline markcol line col)
c8d0cf5c
CD
227 (if (not info)
228 nil
229 (setq beg (move-marker beg (nth 0 info))
230 end (move-marker end (nth 1 info))
86fbb8ca
CD
231 msg (if allow-write-back-p
232 (substitute-command-keys
233 "Edit, then exit with C-c ' (C-c and single quote)")
234 "Exit with C-c ' (C-c and single quote)")
235 code (or code (buffer-substring-no-properties beg end))
54a0dee5
CD
236 lang (or (cdr (assoc (nth 2 info) org-src-lang-modes))
237 (nth 2 info))
238 lang (if (symbolp lang) (symbol-name lang) lang)
c8d0cf5c
CD
239 single (nth 3 info)
240 lfmt (nth 4 info)
8bfe682a 241 block-nindent (nth 5 info)
c8d0cf5c
CD
242 lang-f (intern (concat lang "-mode"))
243 begline (save-excursion (goto-char beg) (org-current-line)))
acedf35c
CD
244 (if (and mark (>= mark beg) (<= mark (1+ end)))
245 (save-excursion (goto-char (min mark end))
afe98dfa
CD
246 (setq markline (org-current-line)
247 markcol (current-column))))
ed21c5c8
CD
248 (if (equal lang-f 'table.el-mode)
249 (setq lang-f (lambda ()
250 (text-mode)
251 (if (org-bound-and-true-p flyspell-mode)
252 (flyspell-mode -1))
253 (table-recognize)
254 (org-set-local 'org-edit-src-content-indentation 0))))
c8d0cf5c
CD
255 (unless (functionp lang-f)
256 (error "No such language mode: %s" lang-f))
afe98dfa
CD
257 (save-excursion
258 (if (> (point) end) (goto-char end))
259 (setq line (org-current-line)
260 col (current-column)))
c8d0cf5c 261 (if (and (setq buffer (org-edit-src-find-buffer beg end))
8bfe682a
CD
262 (if org-src-ask-before-returning-to-edit-buffer
263 (y-or-n-p "Return to existing edit buffer? [n] will revert changes: ") t))
264 (org-src-switch-to-buffer buffer 'return)
c8d0cf5c
CD
265 (when buffer
266 (with-current-buffer buffer
267 (if (boundp 'org-edit-src-overlay)
86fbb8ca 268 (delete-overlay org-edit-src-overlay)))
c8d0cf5c 269 (kill-buffer buffer))
54a0dee5 270 (setq buffer (generate-new-buffer
86fbb8ca
CD
271 (or edit-buffer-name
272 (org-src-construct-edit-buffer-name (buffer-name) lang))))
273 (setq ovl (make-overlay beg end))
274 (overlay-put ovl 'edit-buffer buffer)
275 (overlay-put ovl 'help-echo "Click with mouse-1 to switch to buffer editing this segment")
276 (overlay-put ovl 'face 'secondary-selection)
277 (overlay-put ovl
278 'keymap
279 (let ((map (make-sparse-keymap)))
280 (define-key map [mouse-1] 'org-edit-src-continue)
281 map))
282 (overlay-put ovl :read-only "Leave me alone")
8bfe682a
CD
283 (org-src-switch-to-buffer buffer 'edit)
284 (if (eq single 'macro-definition)
285 (setq code (replace-regexp-in-string "\\\\n" "\n" code t t)))
c8d0cf5c
CD
286 (insert code)
287 (remove-text-properties (point-min) (point-max)
288 '(display nil invisible nil intangible nil))
8bfe682a
CD
289 (unless preserve-indentation
290 (setq total-nindent (or (org-do-remove-indentation) 0)))
c8d0cf5c 291 (let ((org-inhibit-startup t))
afe98dfa
CD
292 (condition-case e
293 (funcall lang-f)
294 (error
295 (error "Language mode `%s' fails with: %S" lang-f (nth 1 e)))))
c8d0cf5c
CD
296 (set (make-local-variable 'org-edit-src-force-single-line) single)
297 (set (make-local-variable 'org-edit-src-from-org-mode) org-mode-p)
86fbb8ca 298 (set (make-local-variable 'org-edit-src-allow-write-back-p) allow-write-back-p)
8bfe682a 299 (set (make-local-variable 'org-src-preserve-indentation) preserve-indentation)
afe98dfa
CD
300 (when babel-info
301 (set (make-local-variable 'org-src-babel-info) babel-info))
c8d0cf5c
CD
302 (when lfmt
303 (set (make-local-variable 'org-coderef-label-format) lfmt))
304 (when org-mode-p
305 (goto-char (point-min))
306 (while (re-search-forward "^," nil t)
8bfe682a 307 (if (eq (org-current-line) line) (setq total-nindent (1+ total-nindent)))
c8d0cf5c 308 (replace-match "")))
afe98dfa
CD
309 (when markline
310 (org-goto-line (1+ (- markline begline)))
311 (org-move-to-column
312 (if preserve-indentation markcol (max 0 (- markcol total-nindent))))
313 (push-mark (point) 'no-message t)
314 (setq deactivate-mark nil))
54a0dee5 315 (org-goto-line (1+ (- line begline)))
8bfe682a
CD
316 (org-move-to-column
317 (if preserve-indentation col (max 0 (- col total-nindent))))
c8d0cf5c
CD
318 (org-set-local 'org-edit-src-beg-marker beg)
319 (org-set-local 'org-edit-src-end-marker end)
320 (org-set-local 'org-edit-src-overlay ovl)
8bfe682a 321 (org-set-local 'org-edit-src-block-indentation block-nindent)
54a0dee5
CD
322 (org-src-mode)
323 (set-buffer-modified-p nil)
c8d0cf5c
CD
324 (and org-edit-src-persistent-message
325 (org-set-local 'header-line-format msg)))
afe98dfa 326 (unless quietp (message "%s" msg))
c8d0cf5c
CD
327 t)))
328
329(defun org-edit-src-continue (e)
330 (interactive "e")
331 (mouse-set-point e)
332 (let ((buf (get-char-property (point) 'edit-buffer)))
8bfe682a 333 (if buf (org-src-switch-to-buffer buf 'continue)
c8d0cf5c
CD
334 (error "Something is wrong here"))))
335
8bfe682a
CD
336(defun org-src-switch-to-buffer (buffer context)
337 (case org-src-window-setup
0adf5618 338 (current-window
8bfe682a 339 (switch-to-buffer buffer))
0adf5618 340 (other-window
8bfe682a 341 (switch-to-buffer-other-window buffer))
0adf5618 342 (other-frame
8bfe682a 343 (case context
0adf5618 344 (exit
8bfe682a
CD
345 (let ((frame (selected-frame)))
346 (switch-to-buffer-other-frame buffer)
347 (delete-frame frame)))
0adf5618 348 (save
8bfe682a
CD
349 (kill-buffer (current-buffer))
350 (switch-to-buffer buffer))
351 (t
352 (switch-to-buffer-other-frame buffer))))
0adf5618 353 (reorganize-frame
8bfe682a
CD
354 (if (eq context 'edit) (delete-other-windows))
355 (org-switch-to-buffer-other-window buffer)
356 (if (eq context 'exit) (delete-other-windows)))
0adf5618 357 (switch-invisibly
afe98dfa 358 (set-buffer buffer))
8bfe682a
CD
359 (t
360 (message "Invalid value %s for org-src-window-setup"
361 (symbol-name org-src-window-setup))
362 (switch-to-buffer buffer))))
363
8d642074 364(defun org-src-construct-edit-buffer-name (org-buffer-name lang)
86fbb8ca 365 "Construct the buffer name for a source editing buffer."
8d642074
CD
366 (concat "*Org Src " org-buffer-name "[ " lang " ]*"))
367
c8d0cf5c
CD
368(defun org-edit-src-find-buffer (beg end)
369 "Find a source editing buffer that is already editing the region BEG to END."
370 (catch 'exit
371 (mapc
372 (lambda (b)
373 (with-current-buffer b
8d642074 374 (if (and (string-match "\\`*Org Src " (buffer-name))
c8d0cf5c
CD
375 (local-variable-p 'org-edit-src-beg-marker (current-buffer))
376 (local-variable-p 'org-edit-src-end-marker (current-buffer))
377 (equal beg org-edit-src-beg-marker)
378 (equal end org-edit-src-end-marker))
379 (throw 'exit (current-buffer)))))
380 (buffer-list))
381 nil))
382
383(defun org-edit-fixed-width-region ()
384 "Edit the fixed-width ascii drawing at point.
385This must be a region where each line starts with a colon followed by
386a space character.
387An new buffer is created and the fixed-width region is copied into it,
388and the buffer is switched into `artist-mode' for editing. When done,
389exit with \\[org-edit-src-exit]. The edited text will then replace
390the fragment in the Org-mode buffer."
391 (interactive)
392 (let ((line (org-current-line))
8bfe682a 393 (col (current-column))
c8d0cf5c
CD
394 (case-fold-search t)
395 (msg (substitute-command-keys
396 "Edit, then exit with C-c ' (C-c and single quote)"))
397 (org-mode-p (eq major-mode 'org-mode))
398 (beg (make-marker))
399 (end (make-marker))
8bfe682a
CD
400 (preserve-indentation org-src-preserve-indentation)
401 block-nindent ovl beg1 end1 code begline buffer)
c8d0cf5c
CD
402 (beginning-of-line 1)
403 (if (looking-at "[ \t]*[^:\n \t]")
404 nil
405 (if (looking-at "[ \t]*\\(\n\\|\\'\\)")
406 (setq beg1 (point) end1 beg1)
407 (save-excursion
408 (if (re-search-backward "^[ \t]*[^: \t]" nil 'move)
409 (setq beg1 (point-at-bol 2))
410 (setq beg1 (point))))
411 (save-excursion
412 (if (re-search-forward "^[ \t]*[^: \t]" nil 'move)
413 (setq end1 (1- (match-beginning 0)))
414 (setq end1 (point))))
54a0dee5 415 (org-goto-line line))
c8d0cf5c
CD
416 (setq beg (move-marker beg beg1)
417 end (move-marker end end1)
418 code (buffer-substring-no-properties beg end)
419 begline (save-excursion (goto-char beg) (org-current-line)))
420 (if (and (setq buffer (org-edit-src-find-buffer beg end))
421 (y-or-n-p "Return to existing edit buffer? [n] will revert changes: "))
422 (switch-to-buffer buffer)
423 (when buffer
424 (with-current-buffer buffer
425 (if (boundp 'org-edit-src-overlay)
86fbb8ca 426 (delete-overlay org-edit-src-overlay)))
c8d0cf5c 427 (kill-buffer buffer))
8d642074
CD
428 (setq buffer (generate-new-buffer
429 (org-src-construct-edit-buffer-name
430 (buffer-name) "Fixed Width")))
86fbb8ca
CD
431 (setq ovl (make-overlay beg end))
432 (overlay-put ovl 'face 'secondary-selection)
433 (overlay-put ovl 'edit-buffer buffer)
434 (overlay-put ovl 'help-echo "Click with mouse-1 to switch to buffer editing this segment")
435 (overlay-put ovl 'face 'secondary-selection)
436 (overlay-put ovl
c8d0cf5c
CD
437 'keymap
438 (let ((map (make-sparse-keymap)))
439 (define-key map [mouse-1] 'org-edit-src-continue)
440 map))
86fbb8ca 441 (overlay-put ovl :read-only "Leave me alone")
c8d0cf5c
CD
442 (switch-to-buffer buffer)
443 (insert code)
444 (remove-text-properties (point-min) (point-max)
445 '(display nil invisible nil intangible nil))
8bfe682a 446 (setq block-nindent (or (org-do-remove-indentation) 0))
c8d0cf5c
CD
447 (cond
448 ((eq org-edit-fixed-width-region-mode 'artist-mode)
449 (fundamental-mode)
450 (artist-mode 1))
86fbb8ca 451 (t (funcall org-edit-fixed-width-region-mode)))
c8d0cf5c
CD
452 (set (make-local-variable 'org-edit-src-force-single-line) nil)
453 (set (make-local-variable 'org-edit-src-from-org-mode) org-mode-p)
454 (set (make-local-variable 'org-edit-src-picture) t)
455 (goto-char (point-min))
456 (while (re-search-forward "^[ \t]*: ?" nil t)
457 (replace-match ""))
54a0dee5 458 (org-goto-line (1+ (- line begline)))
8bfe682a 459 (org-move-to-column (max 0 (- col block-nindent 2)))
c8d0cf5c
CD
460 (org-set-local 'org-edit-src-beg-marker beg)
461 (org-set-local 'org-edit-src-end-marker end)
462 (org-set-local 'org-edit-src-overlay ovl)
8bfe682a
CD
463 (org-set-local 'org-edit-src-block-indentation block-nindent)
464 (org-set-local 'org-edit-src-content-indentation 0)
465 (org-set-local 'org-src-preserve-indentation nil)
54a0dee5
CD
466 (org-src-mode)
467 (set-buffer-modified-p nil)
c8d0cf5c
CD
468 (and org-edit-src-persistent-message
469 (org-set-local 'header-line-format msg)))
470 (message "%s" msg)
471 t)))
472
473(defun org-edit-src-find-region-and-lang ()
474 "Find the region and language for a local edit.
475Return a list with beginning and end of the region, a string representing
8bfe682a 476the language, a switch telling if the content should be in a single line."
c8d0cf5c
CD
477 (let ((re-list
478 (append
479 org-edit-src-region-extra
480 '(
481 ("<src\\>[^<]*>[ \t]*\n?" "\n?[ \t]*</src>" lang)
482 ("<literal\\>[^<]*>[ \t]*\n?" "\n?[ \t]*</literal>" style)
483 ("<example>[ \t]*\n?" "\n?[ \t]*</example>" "fundamental")
484 ("<lisp>[ \t]*\n?" "\n?[ \t]*</lisp>" "emacs-lisp")
485 ("<perl>[ \t]*\n?" "\n?[ \t]*</perl>" "perl")
486 ("<python>[ \t]*\n?" "\n?[ \t]*</python>" "python")
487 ("<ruby>[ \t]*\n?" "\n?[ \t]*</ruby>" "ruby")
488 ("^[ \t]*#\\+begin_src\\( \\([^ \t\n]+\\)\\)?.*\n" "\n[ \t]*#\\+end_src" 2)
489 ("^[ \t]*#\\+begin_example.*\n" "\n[ \t]*#\\+end_example" "fundamental")
490 ("^[ \t]*#\\+html:" "\n" "html" single-line)
491 ("^[ \t]*#\\+begin_html.*\n" "\n[ \t]*#\\+end_html" "html")
492 ("^[ \t]*#\\+latex:" "\n" "latex" single-line)
493 ("^[ \t]*#\\+begin_latex.*\n" "\n[ \t]*#\\+end_latex" "latex")
494 ("^[ \t]*#\\+ascii:" "\n" "fundamental" single-line)
495 ("^[ \t]*#\\+begin_ascii.*\n" "\n[ \t]*#\\+end_ascii" "fundamental")
496 ("^[ \t]*#\\+docbook:" "\n" "xml" single-line)
8bfe682a
CD
497 ("^[ \t]*#\\+macro:[ \t]+\\S-+\\( \\|$\\)"
498 "\n" "fundamental" macro-definition)
c8d0cf5c
CD
499 ("^[ \t]*#\\+begin_docbook.*\n" "\n[ \t]*#\\+end_docbook" "xml")
500 )))
501 (pos (point))
502 re1 re2 single beg end lang lfmt match-re1 ind entry)
503 (catch 'exit
504 (while (setq entry (pop re-list))
505 (setq re1 (car entry) re2 (nth 1 entry) lang (nth 2 entry)
506 single (nth 3 entry))
507 (save-excursion
508 (if (or (looking-at re1)
509 (re-search-backward re1 nil t))
510 (progn
511 (setq match-re1 (match-string 0))
512 (setq beg (match-end 0)
513 lang (org-edit-src-get-lang lang)
514 lfmt (org-edit-src-get-label-format match-re1)
515 ind (org-edit-src-get-indentation (match-beginning 0)))
516 (if (and (re-search-forward re2 nil t)
517 (>= (match-end 0) pos))
518 (throw 'exit (list beg (match-beginning 0)
519 lang single lfmt ind))))
520 (if (or (looking-at re2)
521 (re-search-forward re2 nil t))
522 (progn
523 (setq end (match-beginning 0))
524 (if (and (re-search-backward re1 nil t)
525 (<= (match-beginning 0) pos))
526 (progn
527 (setq lfmt (org-edit-src-get-label-format
528 (match-string 0))
529 ind (org-edit-src-get-indentation
530 (match-beginning 0)))
531 (throw 'exit
532 (list (match-end 0) end
533 (org-edit-src-get-lang lang)
86fbb8ca
CD
534 single lfmt ind)))))))))
535 (when (org-at-table.el-p)
536 (re-search-backward "^[\t]*[^ \t|\\+]" nil t)
537 (setq beg (1+ (point-at-eol)))
538 (goto-char beg)
539 (or (re-search-forward "^[\t]*[^ \t|\\+]" nil t)
540 (progn (goto-char (point-max)) (newline)))
541 (setq end (point-at-bol))
542 (setq ind (org-edit-src-get-indentation beg))
543 (throw 'exit (list beg end 'table.el nil nil ind))))))
c8d0cf5c
CD
544
545(defun org-edit-src-get-lang (lang)
546 "Extract the src language."
547 (let ((m (match-string 0)))
548 (cond
549 ((stringp lang) lang)
550 ((integerp lang) (match-string lang))
551 ((and (eq lang 'lang)
552 (string-match "\\<lang=\"\\([^ \t\n\"]+\\)\"" m))
553 (match-string 1 m))
554 ((and (eq lang 'style)
555 (string-match "\\<style=\"\\([^ \t\n\"]+\\)\"" m))
556 (match-string 1 m))
557 (t "fundamental"))))
558
559(defun org-edit-src-get-label-format (s)
560 "Extract the label format."
561 (save-match-data
562 (if (string-match "-l[ \t]+\\\\?\"\\([^\t\r\n\"]+\\)\\\\?\"" s)
563 (match-string 1 s))))
564
565(defun org-edit-src-get-indentation (pos)
86fbb8ca 566 "Count leading whitespace characters on line."
c8d0cf5c
CD
567 (save-match-data
568 (goto-char pos)
569 (org-get-indentation)))
570
8bfe682a 571(defun org-edit-src-exit (&optional context)
c8d0cf5c
CD
572 "Exit special edit and protect problematic lines."
573 (interactive)
86fbb8ca
CD
574 (unless (org-bound-and-true-p org-edit-src-from-org-mode)
575 (error "This is not a sub-editing buffer, something is wrong"))
ed21c5c8 576 (widen)
8bfe682a
CD
577 (let* ((beg org-edit-src-beg-marker)
578 (end org-edit-src-end-marker)
579 (ovl org-edit-src-overlay)
580 (buffer (current-buffer))
581 (single (org-bound-and-true-p org-edit-src-force-single-line))
582 (macro (eq single 'macro-definition))
583 (total-nindent (+ (or org-edit-src-block-indentation 0)
584 org-edit-src-content-indentation))
585 (preserve-indentation org-src-preserve-indentation)
86fbb8ca 586 (allow-write-back-p (org-bound-and-true-p org-edit-src-allow-write-back-p))
8bfe682a 587 (delta 0) code line col indent)
86fbb8ca
CD
588 (when allow-write-back-p
589 (unless preserve-indentation (untabify (point-min) (point-max)))
afe98dfa
CD
590 (if org-src-strip-leading-and-trailing-blank-lines
591 (save-excursion
592 (goto-char (point-min))
593 (if (looking-at "[ \t\n]*\n") (replace-match ""))
594 (unless macro
595 (if (re-search-forward "\n[ \t\n]*\\'" nil t) (replace-match ""))))))
c8d0cf5c
CD
596 (setq line (if (org-bound-and-true-p org-edit-src-force-single-line)
597 1
8bfe682a
CD
598 (org-current-line))
599 col (current-column))
86fbb8ca
CD
600 (when allow-write-back-p
601 (when single
602 (goto-char (point-min))
603 (if (re-search-forward "\\s-+\\'" nil t) (replace-match ""))
604 (goto-char (point-min))
605 (let ((cnt 0))
606 (while (re-search-forward "\n" nil t)
607 (setq cnt (1+ cnt))
608 (replace-match (if macro "\\n" " ") t t))
609 (when (and macro (> cnt 0))
610 (goto-char (point-max)) (insert "\\n")))
611 (goto-char (point-min))
612 (if (looking-at "\\s-*") (replace-match " ")))
613 (when (org-bound-and-true-p org-edit-src-from-org-mode)
614 (goto-char (point-min))
615 (while (re-search-forward
616 (if (org-mode-p) "^\\(.\\)" "^\\([*]\\|[ \t]*#\\+\\)") nil t)
617 (if (eq (org-current-line) line) (setq delta (1+ delta)))
618 (replace-match ",\\1")))
619 (when (org-bound-and-true-p org-edit-src-picture)
620 (setq preserve-indentation nil)
621 (untabify (point-min) (point-max))
622 (goto-char (point-min))
623 (while (re-search-forward "^" nil t)
624 (replace-match ": ")))
625 (unless (or single preserve-indentation (= total-nindent 0))
626 (setq indent (make-string total-nindent ?\ ))
627 (goto-char (point-min))
628 (while (re-search-forward "^" nil t)
629 (replace-match indent)))
630 (if (org-bound-and-true-p org-edit-src-picture)
631 (setq total-nindent (+ total-nindent 2)))
632 (setq code (buffer-string))
633 (set-buffer-modified-p nil))
8bfe682a 634 (org-src-switch-to-buffer (marker-buffer beg) (or context 'exit))
c8d0cf5c
CD
635 (kill-buffer buffer)
636 (goto-char beg)
86fbb8ca
CD
637 (when allow-write-back-p
638 (delete-region beg end)
639 (insert code)
640 (goto-char beg)
641 (if single (just-one-space)))
ed21c5c8 642 (if (memq t (mapcar (lambda (overlay)
86fbb8ca 643 (eq (overlay-get overlay 'invisible)
ed21c5c8 644 'org-hide-block))
86fbb8ca 645 (overlays-at (point))))
ed21c5c8
CD
646 ;; Block is hidden; put point at start of block
647 (beginning-of-line 0)
648 ;; Block is visible, put point where it was in the code buffer
649 (org-goto-line (1- (+ (org-current-line) line)))
650 (org-move-to-column (if preserve-indentation col (+ col total-nindent delta))))
c8d0cf5c 651 (move-marker beg nil)
8bfe682a
CD
652 (move-marker end nil))
653 (unless (eq context 'save)
654 (when org-edit-src-saved-temp-window-config
655 (set-window-configuration org-edit-src-saved-temp-window-config)
656 (setq org-edit-src-saved-temp-window-config nil))))
c8d0cf5c
CD
657
658(defun org-edit-src-save ()
659 "Save parent buffer with current state source-code buffer."
660 (interactive)
8bfe682a
CD
661 (let ((p (point)) (m (mark)) msg)
662 (save-window-excursion
663 (org-edit-src-exit 'save)
8d642074
CD
664 (save-buffer)
665 (setq msg (current-message))
8bfe682a
CD
666 (if (eq org-src-window-setup 'other-frame)
667 (let ((org-src-window-setup 'current-window))
668 (org-edit-src-code 'save))
669 (org-edit-src-code 'save)))
670 (push-mark m 'nomessage)
671 (goto-char (min p (point-max)))
672 (message (or msg ""))))
c8d0cf5c 673
54a0dee5 674(defun org-src-mode-configure-edit-buffer ()
86fbb8ca 675 (when (org-bound-and-true-p org-edit-src-from-org-mode)
54a0dee5 676 (org-add-hook 'kill-buffer-hook
4f91a816 677 (lambda () (delete-overlay org-edit-src-overlay)) nil 'local)
86fbb8ca
CD
678 (if (org-bound-and-true-p org-edit-src-allow-write-back-p)
679 (progn
680 (setq buffer-offer-save t)
681 (setq buffer-file-name
682 (concat (buffer-file-name (marker-buffer org-edit-src-beg-marker))
683 "[" (buffer-name) "]"))
684 (if (featurep 'xemacs)
685 (progn
686 (make-variable-buffer-local 'write-contents-hooks) ; needed only for 21.4
687 (setq write-contents-hooks '(org-edit-src-save)))
688 (setq write-contents-functions '(org-edit-src-save))))
689 (setq buffer-read-only t))))
54a0dee5
CD
690
691(org-add-hook 'org-src-mode-hook 'org-src-mode-configure-edit-buffer)
692
afe98dfa
CD
693
694(defun org-src-associate-babel-session (info)
695 "Associate edit buffer with comint session."
696 (interactive)
697 (let ((session (cdr (assoc :session (nth 2 info)))))
698 (and session (not (string= session "none"))
699 (org-babel-comint-buffer-livep session)
700 ((lambda (f) (and (fboundp f) (funcall f session)))
701 (intern (format "org-babel-%s-associate-session" (nth 0 info)))))))
702
703(defun org-src-babel-configure-edit-buffer ()
704 (when org-src-babel-info
705 (org-src-associate-babel-session org-src-babel-info)))
706
707(org-add-hook 'org-src-mode-hook 'org-src-babel-configure-edit-buffer)
708(defmacro org-src-do-at-code-block (&rest body)
709 "Execute a command from an edit buffer in the Org-mode buffer."
710 `(let ((beg-marker org-edit-src-beg-marker))
711 (if beg-marker
712 (with-current-buffer (marker-buffer beg-marker)
713 (goto-char (marker-position beg-marker))
714 ,@body))))
715
716(defun org-src-do-key-sequence-at-code-block (&optional key)
717 "Execute key sequence at code block in the source Org buffer.
718The command bound to KEY in the Org-babel key map is executed
719remotely with point temporarily at the start of the code block in
720the Org buffer.
721
722This command is not bound to a key by default, to avoid conflicts
723with language major mode bindings. To bind it to C-c @ in all
724language major modes, you could use
725
726 (add-hook 'org-src-mode-hook
727 (lambda () (define-key org-src-mode-map \"\\C-c@\"
728 'org-src-do-key-sequence-at-code-block)))
729
730In that case, for example, C-c @ t issued in code edit buffers
731would tangle the current Org code block, C-c @ e would execute
732the block and C-c @ h would display the other available
733Org-babel commands."
734 (interactive "kOrg-babel key: ")
735 (if (equal key (kbd "C-g")) (keyboard-quit)
736 (org-edit-src-save)
737 (org-src-do-at-code-block
738 (call-interactively
739 (lookup-key org-babel-map key)))))
740
741(defcustom org-src-tab-acts-natively nil
742 "If non-nil, the effect of TAB in a code block is as if it were
743issued in the language major mode buffer."
744 :type 'boolean
745 :group 'org-babel)
746
747(defun org-src-native-tab-command-maybe ()
748 "Perform language-specific TAB action.
749Alter code block according to effect of TAB in the language major
750mode."
751 (and org-src-tab-acts-natively
752 (let ((org-src-strip-leading-and-trailing-blank-lines nil))
753 (org-babel-do-key-sequence-in-edit-buffer (kbd "TAB")))))
754
755(add-hook 'org-tab-first-hook 'org-src-native-tab-command-maybe)
756
757(defun org-src-font-lock-fontify-block (lang start end)
758 "Fontify code block.
759This function is called by emacs automatic fontification, as long
760as `org-src-fontify-natively' is non-nil. For manual
761fontification of code blocks see `org-src-fontify-block' and
762`org-src-fontify-buffer'"
763 (let* ((lang-mode (org-src-get-lang-mode lang))
764 (string (buffer-substring-no-properties start end))
765 (modified (buffer-modified-p))
766 (org-buffer (current-buffer)) pos next)
767 (remove-text-properties start end '(face nil))
768 (with-current-buffer
769 (get-buffer-create
770 (concat " org-src-fontification:" (symbol-name lang-mode)))
771 (delete-region (point-min) (point-max))
772 (insert string)
773 (unless (eq major-mode lang-mode) (funcall lang-mode))
774 (font-lock-fontify-buffer)
775 (setq pos (point-min))
776 (while (setq next (next-single-property-change pos 'face))
777 (put-text-property
778 (+ start (1- pos)) (+ start next) 'face
779 (get-text-property pos 'face) org-buffer)
780 (setq pos next)))
781 (add-text-properties
782 start end
783 '(font-lock-fontified t fontified t font-lock-multiline t))
784 (set-buffer-modified-p modified))
785 t) ;; Tell `org-fontify-meta-lines-and-blocks' that we fontified
786
787(defun org-src-fontify-block ()
788 "Fontify code block at point."
789 (interactive)
790 (save-excursion
791 (let ((org-src-fontify-natively t)
792 (info (org-edit-src-find-region-and-lang)))
793 (font-lock-fontify-region (nth 0 info) (nth 1 info)))))
794
795(defun org-src-fontify-buffer ()
796 "Fontify all code blocks in the current buffer"
797 (interactive)
798 (org-babel-map-src-blocks nil
799 (org-src-fontify-block)))
800
801(defun org-src-get-lang-mode (lang)
802 "Return major mode that should be used for LANG.
803LANG is a string, and the returned major mode is a symbol."
804 (intern
805 (concat
806 ((lambda (l) (if (symbolp l) (symbol-name l) l))
807 (or (cdr (assoc lang org-src-lang-modes)) lang)) "-mode")))
808
c8d0cf5c
CD
809(provide 'org-src)
810
c8d0cf5c 811;;; org-src.el ends here