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
electric-indent-mode
...
(let ((act (or (run-hook-with-args-until-success
'electric-indent-functions
last-command-event)
(memq last-command-event electric-indent-chars))))
(not
(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)
'do-indent)
(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)))
(save-excursion
(insert ?\n (make-string 3 last-command-event))
(indent-according-to-mode))
(newline-and-indent)))
(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)
(make-string 3 last-command-event)
is wrong. It inserts three unneeded quotes. Thanks!
Commented
May 24, 2017 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():
d
After hitting TAB
, it becomes
def foo():
"""|
"""
You can also write a custom snippet to make it
def foo():
"""
|
"""