When adding the docstring to a fuction

def func():

After pressing RET I have this

def func():

Instead of this

def func():

| is a cursor.


The problem stems from this check in electric-indent-post-self-insert-function:

(defun electric-indent-post-self-insert-function ()
    (when (and
             (let ((act (or (run-hook-with-args-until-success
                            (memq last-command-event electric-indent-chars))))
                (or (memq act '(nil no-indent))
                    ;; In a string or comment.
                    (unless (eq act 'do-indent) (nth 8 (syntax-ppss))))))))

You can get around this by doing:

(defun always-do-indent (_char)
(defun my-python-mode-hook ()
  (add-hook 'electric-indent-functions #'always-do-indent nil t))
(add-hook 'python-mode-hook #'my-python-mode-hook)

Which will result in:

def foo():

To get the extra newline in the middle that you want, (assuming you have electric-pair-mode enabled) you can add this electric pair mode post self insert hook (adapted from Stefan's answer at https://stackoverflow.com/a/19715115/319698):

(defun python-electric-pair-docstring-delimiter ()
  (when (and electric-pair-mode
             (memq last-command-event '(?\" ?\'))
             (let ((count 0))
               (while (eq (char-before (- (point) count)) last-command-event)
                 (setq count (1+ count)))
               (= count 3)))
      (insert ?\n (make-string 3 last-command-event))

(defun my-python-mode-hook ()
  (add-hook 'post-self-insert-hook
            #'python-electric-pair-docstring-delimiter 'append t))
(add-hook 'python-mode-hook #'my-python-mode-hook)
  • Well, I've abandoned emacs for now, but as you can see this isn't doing what I wanted. Thanks anyway. Am I right that the core of a problem is that it doesn't indent in strings and comments? – user1685095 May 24 '17 at 16:36
  • yes, just like it does for parentheses and brackets etc. – user1685095 May 24 '17 at 16:43
  • I was, yes. Sorry I haven't mentioned it. – user1685095 May 24 '17 at 16:57
  • The first suggestion works as promised, but the second one doesn't change anything. – user1685095 May 24 '17 at 18:22
  • 1
    (make-string 3 last-command-event) is wrong. It inserts three unneeded quotes. Thanks! – user1685095 May 24 '17 at 19:07

I use yasnippet which avoids this problem. after writing function name, type d and hit TAB, it will expand to multiline string with correct indentation

def foo():

After hitting TAB, it becomes

def foo():

You can also write a custom snippet to make it

def foo():
  • Yeah, I use a lot of snippets in vim too, but I can't accept this as an answer. I'm interested in fixing this particular emacs bug, not just solving the problem via workaround. I think something like defadvice should help, but I'm to feeble in elisp. – user1685095 Mar 25 '17 at 8:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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