8

I'm going kinda crazy trying to understand what's going on here... Asked this question on the r/emacs subreddit so apologies if any of you are seeing this again.

Do org blocks allow TAB indentation without going into special editing mode via C-c ' ?

I have the following relevant settings in my custom-set-variables block (i.e. edited via customize-mode.

 '(org-edit-src-content-indentation 0)
 '(org-src-preserve-indentation nil)

I used these settings because I was getting sick of editing code in the source block and having all the lines jump 2 spaces to the right.

org-src-tab-acts-natively is set to t as well.

But now when I write

#+begin_src python
def hello():
|
#+end_src

the cursor is stuck at the start of the line and I can't use TAB to indent to add a new line, i.e. to make it look like:

def hello( ):
    print("hello)

TAB used to work -- or atleast, I thought it was working. This github comment suggests that this facility was never actually available, and we always had to use C-c ' to edit code properly. But then this Stackoverflow post and answers, as well as this github issue seem to imply otherwise.

Now, I have also set org-adapt-indentation to nil, because I prefer org-headings, sub-headings and text to be aligned with the buffer edge. If I set it to 1, it looks like there is some aligning going on when I hit TAB, but this is not perfect. Does this explain the "pseudo-indenting" that I had before, and there really is no inherent TAB indent in org blocks?

I have also been recommended poly-mode and poly-org, but I'd first like to understand what is going on here.

EDIT: I have neglected to say that the message Can’t guess python-indent-offset, using defaults: 4 appears in the minibuffer after each failed TAB press. I wouldn't have thought that would be the difference, as long as it guessed a non-zero offset.

EDIT: Org mode version 9.4.4 (release_9.4.4 @ /usr/share/emacs/27.2/lisp/org/)

EDIT: Here is the tab-indentation behavior when running emacs -Q https://i.stack.imgur.com/Bm05v.jpg

2
  • What is the value of org-cycle-emulate-tab? If nil, set it to t and try again. Check the doc string of the variable with C-h v org-cycle-emulate-tab.
    – NickD
    Nov 3, 2021 at 16:33
  • To avoid getting the message Can't guess ... add this to your python configuration: (setq python-indent-guess-indent-offset-verbose nil). Take care also to init tab-width to 4 and config python-indent-offset also to 4.
    – Ian
    Nov 4, 2021 at 14:04

1 Answer 1

3

TAB is bound to org-cycle in Org mode buffers: that function generally cycles the element that the cursor is on (headlines, drawers, source blocks) between the folded and unfolded state. But Org mode makes use of context-dependent bindings very often and that confuses things. E.g. in this case, if the cursor is in a table, the table is realigned and the cursor moves to the next cell.

But when the cursor is not on anything that org-cycle considers "special" to do something interesting, then it just executes the global binding of TAB which re-indents lines, assuming that org-cycle-emulate-tab is not nil. In that case, TAB in your python source code block (as opposed on the #+BEGIN_SRC line which folds the code block) should indent using indent-for-tab-command (unless you have modified the global binding of TAB).

EDIT: for debugging, try adding and evaluating the following source block to an Org mode file:

#+begin_src elisp
(global-key-binding (kbd "TAB"))
#+end_src

#+RESULTS:
: indent-for-tab-command

Do you get indent-for-tab-command as the result? If so, go to your python source block and say M-x indent-for-tab-command - do you get the indentation you expect?

EDIT 2: Note that you should not expect "real" python indentation. This is more like typing python code in a buffer that is in fundamental mode.

EDIT 3: I stand corrected: you should expect "real" python indentation: indent-for-tab-command calls the function which is the value of the variable indent-line-function. Now inside an Org mode buffer, the value of that variable is org-indent-line, which, in source code blocks, calls org-babel-do-key-sequence-in-edit-buffer; that in turn calls the macro org-babel-do-in-edit-buffer: that finally calls whatever function is bound to TAB in the context of an edit buffer created by org-edit-src-code and then does org-edit-src-exit - phew! That's basically what would happen interactively, if you did C-c ' in the source block, typed a TAB in the resulting source buffer (which is in python mode!) and then exited with another C-c '. But note that using two tabs to unindent, as would happen if you did it interactively, does not work: each tab is treated separately, so we go into the source buffer twice, do a single tab each time and exit. There are limitations to this approach.

7
  • Thanks -- it was nil, but setting org-cycle-emulate-tab to t (i.e. "Everywhere except in headlines") still does not fix this (even if I change org-src-preserve-indentation. Presumably indentation works for you, and properly (i.e. the tab does 4 spaces rather than whatever org-edit-src-content-indentation is set to)? Perhaps I need to do emacs -Q again and see if some other mode is hogging TAB, though I can't see which one. Nov 3, 2021 at 17:40
  • 1
    I get two spaces on the first line and four additional spaces on subsequent lines, but N.B. this is more or less an accident: it's what you would get say if you tried typing python code in a buffer that is in Fundamental mode. You cannot expect it to do what "real" indentation would do in a python mode buffer.
    – NickD
    Nov 3, 2021 at 18:46
  • 1
    I added some debugging suggestions, as well as the caveat from the previous comment to the answer.
    – NickD
    Nov 3, 2021 at 18:49
  • I do get indent-for-tab-command when I evaluate that code block and running M-x indent-for-tab-command has the same result as using TAB -- no indent. However, I think I have neglected to say that the message Can’t guess python-indent-offset, using defaults: 4 appears in the minibuffer each time. I wouldn't have thought that would be the difference, as long as it guessed a non-zero offset. Nov 3, 2021 at 19:36
  • Re: "you should not expect "real" python indentation", OK, but I would have thought having the variable org-src-tab-acts-natively would allow this to be the case, as this answer and the *Help* page suggests. In any case, just a naive/fundamental-mode style indentation via TAB seems beyond me at the moment. Nov 3, 2021 at 19:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.