Subject: bug#28051: Multiline Statement Indentation Error in Inferior Python Mode

From: [email-masked]
Date: Mon, 21 Aug 2017 08:17:41 -0400

tags 28051 + patch
quit

[email-masked] writes:

> I can reproduce this on Windows.  And on GNU/Linux after doing (setq
> python-shell-completion-native-enable nil).  Perhaps this is one of the
> "limitations" referred to in the comments of python.el:
>
>     ;; ...the "fallback" or "legacy" mechanism works by executing Python
>     ;; code in the background and enables auto-completion for shells
>     ;; that do not support receiving escape sequences (with some
>     ;; limitations, i.e. completion in blocks does not work).

I think the best we can do is disable completion with an error message
when the prompt is "...", see attached.

>From 20693abb64a342255a076645b758590373308a52 Mon Sep 17 00:00:00 2001
From: Noam Postavsky <[email-masked]>
Date: Sat, 19 Aug 2017 11:45:07 -0400
Subject: [PATCH] Disable completion while entering python multiline statements

The "legacy" completion mechanism sends newlines to the running python
process to get the list of completions, which confuses things if the
user is in the middle of entering a multiline statement (Bug#28051).
It's better to disable completion in this case.
* lisp/progmodes/python.el (python-shell--block-prompt): New variable.
(python-shell-prompt-set-calculated-regexps): Set it.
(python-shell-completion-at-point): Bail out with error message if
current prompt is a block prompt.
---
 lisp/progmodes/python.el | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index b8f8ed2a06..897ee856a5 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -2212,6 +2212,11 @@ python-shell--prompt-calculated-input-regexp
 Do not set this variable directly, instead use
 `python-shell-prompt-set-calculated-regexps'.")
 
+(defvar python-shell--block-prompt nil
+  "Input block prompt for inferior python shell.
+Do not set this variable directly, instead use
+`python-shell-prompt-set-calculated-regexps'.")
+
 (defvar python-shell--prompt-calculated-output-regexp nil
   "Calculated output prompt regexp for inferior python shell.
 Do not set this variable directly, instead use
@@ -2366,6 +2371,7 @@ python-shell-prompt-set-calculated-regexps
         (dolist (prompt (butlast detected-prompts))
           (setq prompt (regexp-quote prompt))
           (cl-pushnew prompt input-prompts :test #'string=))
+        (setq python-shell--block-prompt (nth 1 detected-prompts))
         (cl-pushnew (regexp-quote
                      (car (last detected-prompts)))
                     output-prompts :test #'string=))
@@ -2726,6 +2732,7 @@ inferior-python-mode
   (set (make-local-variable 'python-shell-interpreter-args)
        (or python-shell--interpreter-args python-shell-interpreter-args))
   (set (make-local-variable 'python-shell--prompt-calculated-input-regexp) nil)
+  (set (make-local-variable 'python-shell--block-prompt) nil)
   (set (make-local-variable 'python-shell--prompt-calculated-output-regexp) nil)
   (python-shell-prompt-set-calculated-regexps)
   (setq comint-prompt-regexp python-shell--prompt-calculated-input-regexp)
@@ -3632,7 +3639,9 @@ python-shell-completion-at-point
                        ;; Also, since pdb interaction is single-line
                        ;; based, this is enough.
                        (string-match-p python-shell-prompt-pdb-regexp prompt))
-                   #'python-shell-completion-get-completions)
+                   (if (equal python-shell--block-prompt prompt)
+                       (user-error "Cannot use standard completion in multiline statement")
+                     #'python-shell-completion-get-completions))
                   (t #'python-shell-completion-native-get-completions)))))
     (list start end
           (completion-table-dynamic
-- 
2.14.1