Indent code in org-babel src blocks
Asked Answered
R

4

17

In an org-mode file, with code like the following:

#+begin_src emacs-lisp
(add-to-list 'org-tab-before-tab-emulation-hook
             (lambda ()
               (when (within-the-body-of-a-begin-src-block)
                 (indent-for-tab-command--as-if-in-lisp-mode))))
#+end_src

I would like the TAB key to indent the code as it would if it were in a buffer in lisp mode.

What I need is:

  • A way to figure out whether the cursor is within a src block. It needs to not trigger when on the header line itself, as in that case the default org folding should take place.
  • A way to indent the code according to the mode (emacs-lisp in this case) specified in the header.

Org can already syntax highlight src blocks according to mode, and the TAB hooks are there. This looks do-able.

Racy answered 2/4, 2013 at 20:5 Comment(4)
Since you're editing the current code, would C-c ' to enter the editing mode suffice?Ungula
Yes, I know about that shortcut, but it feels too heavy when editing many short snippets, such as in an emacs config-within-org file.Racy
might be helpful on this threadUngula
I’m voting to close this question because I believe this belongs to emacs.stackexchange.comDeification
N
46

Since Emacs 24.1 you can now set the following option:

(setq org-src-tab-acts-natively t)

...and that should handle all src blocks.

Neurasthenia answered 1/12, 2014 at 20:23 Comment(2)
This is the best answer I didn't expect to find this week :-)Timofei
Yasnippet users who encounter a yasnippet fallback loop when doing this might find this thread useful: github.com/joaotavora/yasnippet/issues/761Moscow
B
21

Just move point into the code block and press C-c '

This will pop up a buffer in elisp-mode, syntax higlighting ad all...

Baese answered 11/6, 2013 at 6:45 Comment(2)
after exiting the code block editor, the code seems to be indented by 2 spaces, not sure why that is.Quadrivial
@RudolfOlah - you can turn this off with: (setq org-edit-src-content-indentation 0)Omnipotent
R
2

Here's a rough solution:

(defun indent-org-src-block-line ()
  "Indent the current line of emacs lisp code."
  (interactive)
  (let ((info (org-babel-get-src-block-info 'light)))
    (when info
      (let ((lang (nth 0 info)))
        (when (string= lang "emacs-lisp")
          (let ((indent-line-function 'lisp-indent-line))
            (indent-for-tab-command)))))))

(add-to-list 'org-tab-before-tab-emulation-hook
             'indent-org-src-block-line)

It only handles emacs-lisp blocks. I've only tested with the src block un-indented (not the org default).

It is tough in general to make one mode work inside another - many keyboard commands will conflict. But some of the more basic strokes, like tab for indent, newline, commenting (org will comment the lisp code with #, which is wrong) seem like they could be made to work and would have the largest impact.

Racy answered 2/4, 2013 at 20:6 Comment(0)
P
1
(defun my/org-cleanup ()
  (interactive)
  (org-edit-special)
  (indent-buffer)
  (org-edit-src-exit))

should do it, where `indent-buffer' is defined as:

(defun indent-buffer ()
  (interactive)
  (indent-region (point-min) (point-max)))
Pinkston answered 1/12, 2014 at 14:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.