aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/python.el
diff options
context:
space:
mode:
authorFabián Ezequiel Gallina2015-08-23 14:54:56 -0300
committerFabián Ezequiel Gallina2015-08-23 14:55:06 -0300
commita92066b80e4245f5093fa1ed481f0e3eb377f504 (patch)
treea03a4c055ce3ea33bc9b4518511d357c3d5c8e7a /lisp/progmodes/python.el
parente7be9861962a5a399047e86a254c2534d5d4d146 (diff)
downloademacs-a92066b80e4245f5093fa1ed481f0e3eb377f504.tar.gz
emacs-a92066b80e4245f5093fa1ed481f0e3eb377f504.zip
python.el: Fix completion for pdb interactions
* lisp/progmodes/python.el (python-shell-completion-setup-code): Simplify. Toggle print_mode for native wrapped completer. (python-shell-completion-native-setup): Ensure process buffer. Add print_mode attribute to completer wrapper to toggle returning or printing candidates. (python-shell-completion-native-get-completions): Cleanup. (python-shell-completion-get-completions): Cleanup. (python-shell-completion-at-point): Perform prompt checks. Force fallback completion in pdb interactions.
Diffstat (limited to 'lisp/progmodes/python.el')
-rw-r--r--lisp/progmodes/python.el266
1 files changed, 139 insertions, 127 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 426b465f745..93ef7fe9db6 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -3138,50 +3138,56 @@ This function takes the list of setup code to send from the
3138;;; Shell completion 3138;;; Shell completion
3139 3139
3140(defcustom python-shell-completion-setup-code 3140(defcustom python-shell-completion-setup-code
3141 "try: 3141 "
3142 import readline 3142def __PYTHON_EL_get_completions(text):
3143except: 3143 completions = []
3144 def __PYTHON_EL_get_completions(text): 3144 completer = None
3145 return [] 3145
3146else: 3146 try:
3147 def __PYTHON_EL_get_completions(text): 3147 import readline
3148
3148 try: 3149 try:
3149 import __builtin__ 3150 import __builtin__
3150 except ImportError: 3151 except ImportError:
3151 # Python 3 3152 # Python 3
3152 import builtins as __builtin__ 3153 import builtins as __builtin__
3153 builtins = dir(__builtin__) 3154 builtins = dir(__builtin__)
3154 completions = [] 3155
3155 is_ipython = ('__IPYTHON__' in builtins or 3156 is_ipython = ('__IPYTHON__' in builtins or
3156 '__IPYTHON__active' in builtins) 3157 '__IPYTHON__active' in builtins)
3157 splits = text.split() 3158 splits = text.split()
3158 is_module = splits and splits[0] in ('from', 'import') 3159 is_module = splits and splits[0] in ('from', 'import')
3159 try: 3160
3160 if is_ipython and is_module: 3161 if is_ipython and is_module:
3161 from IPython.core.completerlib import module_completion 3162 from IPython.core.completerlib import module_completion
3162 completions = module_completion(text.strip()) 3163 completions = module_completion(text.strip())
3163 elif is_ipython and '__IP' in builtins: 3164 elif is_ipython and '__IP' in builtins:
3164 completions = __IP.complete(text) 3165 completions = __IP.complete(text)
3165 elif is_ipython and 'get_ipython' in builtins: 3166 elif is_ipython and 'get_ipython' in builtins:
3166 completions = get_ipython().Completer.all_completions(text) 3167 completions = get_ipython().Completer.all_completions(text)
3167 else: 3168 else:
3168 # Try to reuse current completer. 3169 # Try to reuse current completer.
3170 completer = readline.get_completer()
3171 if not completer:
3172 # importing rlcompleter sets the completer, use it as a
3173 # last resort to avoid breaking customizations.
3174 import rlcompleter
3169 completer = readline.get_completer() 3175 completer = readline.get_completer()
3170 if not completer: 3176 if getattr(completer, 'PYTHON_EL_WRAPPED', False):
3171 # importing rlcompleter sets the completer, use it as a 3177 completer.print_mode = False
3172 # last resort to avoid breaking customizations. 3178 i = 0
3173 import rlcompleter 3179 while True:
3174 completer = readline.get_completer() 3180 completion = completer(text, i)
3175 i = 0 3181 if not completion:
3176 while True: 3182 break
3177 completion = completer(text, i) 3183 i += 1
3178 if not completion: 3184 completions.append(completion)
3179 break 3185 except:
3180 i += 1 3186 pass
3181 completions.append(completion) 3187 finally:
3182 except: 3188 if getattr(completer, 'PYTHON_EL_WRAPPED', False):
3183 pass 3189 completer.print_mode = True
3184 return completions" 3190 return completions"
3185 "Code used to setup completion in inferior Python processes." 3191 "Code used to setup completion in inferior Python processes."
3186 :type 'string 3192 :type 'string
3187 :group 'python) 3193 :group 'python)
@@ -3243,12 +3249,13 @@ When a match is found, native completion is disabled."
3243 python-shell-completion-native-try-output-timeout)) 3249 python-shell-completion-native-try-output-timeout))
3244 (python-shell-completion-native-get-completions 3250 (python-shell-completion-native-get-completions
3245 (get-buffer-process (current-buffer)) 3251 (get-buffer-process (current-buffer))
3246 nil "int"))) 3252 nil "")))
3247 3253
3248(defun python-shell-completion-native-setup () 3254(defun python-shell-completion-native-setup ()
3249 "Try to setup native completion, return non-nil on success." 3255 "Try to setup native completion, return non-nil on success."
3250 (let ((process (python-shell-get-process))) 3256 (let ((process (python-shell-get-process)))
3251 (python-shell-send-string " 3257 (with-current-buffer (process-buffer process)
3258 (python-shell-send-string "
3252def __PYTHON_EL_native_completion_setup(): 3259def __PYTHON_EL_native_completion_setup():
3253 try: 3260 try:
3254 import readline 3261 import readline
@@ -3283,6 +3290,7 @@ def __PYTHON_EL_native_completion_setup():
3283 def __init__(self, completer): 3290 def __init__(self, completer):
3284 self.completer = completer 3291 self.completer = completer
3285 self.last_completion = None 3292 self.last_completion = None
3293 self.print_mode = True
3286 3294
3287 def __call__(self, text, state): 3295 def __call__(self, text, state):
3288 if state == 0: 3296 if state == 0:
@@ -3312,8 +3320,11 @@ def __PYTHON_EL_native_completion_setup():
3312 # For every non-dummy completion, return a repeated dummy 3320 # For every non-dummy completion, return a repeated dummy
3313 # one and print the real candidate so it can be retrieved 3321 # one and print the real candidate so it can be retrieved
3314 # by comint output filters. 3322 # by comint output filters.
3315 print (completion) 3323 if self.print_mode:
3316 return '0__dummy_completion__' 3324 print (completion)
3325 return '0__dummy_completion__'
3326 else:
3327 return completion
3317 else: 3328 else:
3318 return completion 3329 return completion
3319 3330
@@ -3346,17 +3357,18 @@ def __PYTHON_EL_native_completion_setup():
3346 # Require just one tab to send output. 3357 # Require just one tab to send output.
3347 readline.parse_and_bind('set show-all-if-ambiguous on') 3358 readline.parse_and_bind('set show-all-if-ambiguous on')
3348 3359
3349 print ('python.el: readline is available') 3360 print ('python.el: native completion setup loaded')
3350 except: 3361 except:
3351 print ('python.el: readline not available') 3362 print ('python.el: native completion setup failed')
3352 3363
3353__PYTHON_EL_native_completion_setup()" 3364__PYTHON_EL_native_completion_setup()" process)
3354 process) 3365 (when (and
3355 (python-shell-accept-process-output process) 3366 (python-shell-accept-process-output
3356 (when (save-excursion 3367 process python-shell-completion-native-try-output-timeout)
3357 (re-search-backward 3368 (save-excursion
3358 (regexp-quote "python.el: readline is available") nil t 1)) 3369 (re-search-backward
3359 (python-shell-completion-native-try)))) 3370 (regexp-quote "python.el: native completion setup loaded") nil t 1)))
3371 (python-shell-completion-native-try)))))
3360 3372
3361(defun python-shell-completion-native-turn-off (&optional msg) 3373(defun python-shell-completion-native-turn-off (&optional msg)
3362 "Turn off shell native completions. 3374 "Turn off shell native completions.
@@ -3421,91 +3433,75 @@ With argument MSG show activation/deactivation message."
3421When IMPORT is non-nil takes precedence over INPUT for 3433When IMPORT is non-nil takes precedence over INPUT for
3422completion." 3434completion."
3423 (with-current-buffer (process-buffer process) 3435 (with-current-buffer (process-buffer process)
3424 (when (and python-shell-completion-native-enable 3436 (let* ((input (or import input))
3425 (python-util-comint-last-prompt) 3437 (original-filter-fn (process-filter process))
3426 (>= (point) (cdr (python-util-comint-last-prompt)))) 3438 (redirect-buffer (get-buffer-create
3427 (let* ((input (or import input)) 3439 python-shell-completion-native-redirect-buffer))
3428 (original-filter-fn (process-filter process)) 3440 (trigger "\t")
3429 (redirect-buffer (get-buffer-create 3441 (new-input (concat input trigger))
3430 python-shell-completion-native-redirect-buffer)) 3442 (input-length
3431 (trigger "\t") 3443 (save-excursion
3432 (new-input (concat input trigger)) 3444 (+ (- (point-max) (comint-bol)) (length new-input))))
3433 (input-length 3445 (delete-line-command (make-string input-length ?\b))
3434 (save-excursion 3446 (input-to-send (concat new-input delete-line-command)))
3435 (+ (- (point-max) (comint-bol)) (length new-input)))) 3447 ;; Ensure restoring the process filter, even if the user quits
3436 (delete-line-command (make-string input-length ?\b)) 3448 ;; or there's some other error.
3437 (input-to-send (concat new-input delete-line-command))) 3449 (unwind-protect
3438 ;; Ensure restoring the process filter, even if the user quits 3450 (with-current-buffer redirect-buffer
3439 ;; or there's some other error. 3451 ;; Cleanup the redirect buffer
3440 (unwind-protect 3452 (erase-buffer)
3441 (with-current-buffer redirect-buffer 3453 ;; Mimic `comint-redirect-send-command', unfortunately it
3442 ;; Cleanup the redirect buffer 3454 ;; can't be used here because it expects a newline in the
3443 (erase-buffer) 3455 ;; command and that's exactly what we are trying to avoid.
3444 ;; Mimic `comint-redirect-send-command', unfortunately it 3456 (let ((comint-redirect-echo-input nil)
3445 ;; can't be used here because it expects a newline in the 3457 (comint-redirect-completed nil)
3446 ;; command and that's exactly what we are trying to avoid. 3458 (comint-redirect-perform-sanity-check nil)
3447 (let ((comint-redirect-echo-input nil) 3459 (comint-redirect-insert-matching-regexp t)
3448 (comint-redirect-completed nil) 3460 (comint-redirect-finished-regexp
3449 (comint-redirect-perform-sanity-check nil) 3461 "1__dummy_completion__[[:space:]]*\n")
3450 (comint-redirect-insert-matching-regexp t) 3462 (comint-redirect-output-buffer redirect-buffer))
3451 (comint-redirect-finished-regexp 3463 ;; Compatibility with Emacs 24.x. Comint changed and
3452 "1__dummy_completion__[[:space:]]*\n") 3464 ;; now `comint-redirect-filter' gets 3 args. This
3453 (comint-redirect-output-buffer redirect-buffer)) 3465 ;; checks which version of `comint-redirect-filter' is
3454 ;; Compatibility with Emacs 24.x. Comint changed and 3466 ;; in use based on its args and uses `apply-partially'
3455 ;; now `comint-redirect-filter' gets 3 args. This 3467 ;; to make it up for the 3 args case.
3456 ;; checks which version of `comint-redirect-filter' is 3468 (if (= (length
3457 ;; in use based on its args and uses `apply-partially' 3469 (help-function-arglist 'comint-redirect-filter)) 3)
3458 ;; to make it up for the 3 args case. 3470 (set-process-filter
3459 (if (= (length 3471 process (apply-partially
3460 (help-function-arglist 'comint-redirect-filter)) 3) 3472 #'comint-redirect-filter original-filter-fn))
3461 (set-process-filter 3473 (set-process-filter process #'comint-redirect-filter))
3462 process (apply-partially 3474 (process-send-string process input-to-send)
3463 #'comint-redirect-filter original-filter-fn)) 3475 ;; Grab output until our dummy completion used as
3464 (set-process-filter process #'comint-redirect-filter)) 3476 ;; output end marker is found.
3465 (process-send-string process input-to-send) 3477 (when (python-shell-accept-process-output
3466 ;; Grab output until our dummy completion used as 3478 process python-shell-completion-native-output-timeout
3467 ;; output end marker is found. 3479 comint-redirect-finished-regexp)
3468 (when (python-shell-accept-process-output 3480 (re-search-backward "0__dummy_completion__" nil t)
3469 process python-shell-completion-native-output-timeout 3481 (cl-remove-duplicates
3470 comint-redirect-finished-regexp) 3482 (split-string
3471 (re-search-backward "0__dummy_completion__" nil t) 3483 (buffer-substring-no-properties
3472 (cl-remove-duplicates 3484 (line-beginning-position) (point-min))
3473 (split-string 3485 "[ \f\t\n\r\v()]+" t)
3474 (buffer-substring-no-properties 3486 :test #'string=))))
3475 (line-beginning-position) (point-min)) 3487 (set-process-filter process original-filter-fn)))))
3476 "[ \f\t\n\r\v()]+" t)
3477 :test #'string=))))
3478 (set-process-filter process original-filter-fn))))))
3479 3488
3480(defun python-shell-completion-get-completions (process import input) 3489(defun python-shell-completion-get-completions (process import input)
3481 "Do completion at point using PROCESS for IMPORT or INPUT. 3490 "Do completion at point using PROCESS for IMPORT or INPUT.
3482When IMPORT is non-nil takes precedence over INPUT for 3491When IMPORT is non-nil takes precedence over INPUT for
3483completion." 3492completion."
3493 (setq input (or import input))
3484 (with-current-buffer (process-buffer process) 3494 (with-current-buffer (process-buffer process)
3485 (let* ((prompt 3495 (let ((completions
3486 (let ((prompt-boundaries (python-util-comint-last-prompt))) 3496 (python-util-strip-string
3487 (buffer-substring-no-properties 3497 (python-shell-send-string-no-output
3488 (car prompt-boundaries) (cdr prompt-boundaries)))) 3498 (format
3489 (completion-code
3490 ;; Check whether a prompt matches a pdb string, an import
3491 ;; statement or just the standard prompt and use the
3492 ;; correct python-shell-completion-*-code string
3493 (when (string-match python-shell--prompt-calculated-input-regexp prompt)
3494 ;; Since there are no guarantees the user will remain
3495 ;; in the same context where completion code was sent
3496 ;; (e.g. user steps into a function), safeguard
3497 ;; resending completion setup continuously.
3498 (concat python-shell-completion-setup-code 3499 (concat python-shell-completion-setup-code
3499 "\nprint (" python-shell-completion-string-code ")"))) 3500 "\nprint (" python-shell-completion-string-code ")")
3500 (subject (or import input))) 3501 input) process))))
3501 (when (and completion-code (> (length input) 0)) 3502 (when (> (length completions) 2)
3502 (let ((completions 3503 (split-string completions
3503 (python-util-strip-string 3504 "^'\\|^\"\\|;\\|'$\\|\"$" t)))))
3504 (python-shell-send-string-no-output
3505 (format completion-code subject) process))))
3506 (when (> (length completions) 2)
3507 (split-string completions
3508 "^'\\|^\"\\|;\\|'$\\|\"$" t)))))))
3509 3505
3510(defun python-shell-completion-at-point (&optional process) 3506(defun python-shell-completion-at-point (&optional process)
3511 "Function for `completion-at-point-functions' in `inferior-python-mode'. 3507 "Function for `completion-at-point-functions' in `inferior-python-mode'.
@@ -3532,10 +3528,26 @@ using that one instead of current buffer's process."
3532 (forward-char (length (match-string-no-properties 0))) 3528 (forward-char (length (match-string-no-properties 0)))
3533 (point)))) 3529 (point))))
3534 (end (point)) 3530 (end (point))
3531 (prompt-boundaries (python-util-comint-last-prompt))
3532 (prompt
3533 (with-current-buffer (process-buffer process)
3534 (when prompt-boundaries
3535 (buffer-substring-no-properties
3536 (car prompt-boundaries) (cdr prompt-boundaries)))))
3535 (completion-fn 3537 (completion-fn
3536 (if python-shell-completion-native-enable 3538 (with-current-buffer (process-buffer process)
3537 #'python-shell-completion-native-get-completions 3539 (cond ((or (null prompt)
3538 #'python-shell-completion-get-completions))) 3540 (< (point) (cdr prompt-boundaries)))
3541 #'ignore)
3542 ((or (not python-shell-completion-native-enable)
3543 ;; Even if native completion is enabled, for
3544 ;; pdb interaction always use the fallback
3545 ;; mechanism since the completer is changed.
3546 ;; Also, since pdb interaction is single-line
3547 ;; based, this is enough.
3548 (string-match-p python-shell-prompt-pdb-regexp prompt))
3549 #'python-shell-completion-get-completions)
3550 (t #'python-shell-completion-native-get-completions)))))
3539 (list start end 3551 (list start end
3540 (completion-table-dynamic 3552 (completion-table-dynamic
3541 (apply-partially 3553 (apply-partially