Cycling through indentation levels in python.el 1 can be achieved by pressing <tab> repeatedly, which is bound to indent-for-tab-command.

Now, consider:

(defun malb/my-indent (&optional arg)
    (interactive "P")
    (indent-for-tab-command arg))
(bind-key "C-<tab>" #'malb/my-indent)

Now, pressing C-<tab> repeatedly does not lead to cycling through indentation levels. On the other hand,

(bind-key "C-<tab>" #'indent-for-tab-command)

does lead to the desired outcome. Hence, somehow, calling indent-for-tab-command from another function behaves differently from calling it directly. Can anyone explain why that is?

2 Answers 2


If you follow through the code of indent-for-tab-command, you'll see the indentation is actually done by a indent-line-function. In Python mode, this is python-indent-line-function. The help for this function indicates that the cycling behaviour is only triggered if the previous command is in the list python-indent-trigger-commands. malb/myindent isn't in that list of course, so it doesn't work as you want.

You can fix this by adding your function:

(add-to-list 'python-indent-trigger-commands 'malb/my-indent)

The answer by Tyler is correct. I wanted to point out an alternative (but inferior) way to solve the problem. If it weren't for the variable python-indent-trigger-commands that Tyler pointed out, you might be stuck with finding a way of letting your command malb/my-indent masquerade as intend-for-tab-command. One way to achieve that would be as follows:

(defun my-indent (&optional arg)
  (interactive "P")
  (if (not (called-interactively-p))
      (indent-for-tab-command arg)
    (setq this-command 'indent-for-tab-command)
    (call-interactively 'indent-for-tab-command)))

This allows your wrapper layer to be more of a transparent pass-through. In your specific case, the use of call-interactively is not strictly necessary to achieve the desired effect, but it is in many other cases where you want to provide a wrapper around an existing command. That is because many commands behave differently depending on whether they were called interactively or called from lisp.


Your Answer

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

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