diff --git a/.emacs.d/lisp/python.el b/.emacs.d/lisp/python.el index ca69b68..15041a3 100644 --- a/.emacs.d/lisp/python.el +++ b/.emacs.d/lisp/python.el @@ -3071,28 +3071,38 @@ When a match is found, native completion is disabled." "Try to setup native completion, return non-nil on success." (let ((process (python-shell-get-process))) (python-shell-send-string - (funcall - 'mapconcat - #'identity - (list - "try:" - " import readline" - " def completer(text, state, c=readline.get_completer()):" - " completion = c(text, state)" - " if not completion and state == 1:" - " return text + '__dummy_completion__'" - " else:" - " return completion" - " readline.set_completer(completer)" - " if readline.__doc__ and 'libedit' in readline.__doc__:" - " readline.parse_and_bind('bind ^I rl_complete')" - " else:" - " readline.parse_and_bind('tab: complete')" - " print ('python.el: readline is available')" - " del completer, readline # Some cleanup" - "except:" - " print ('python.el: readline not available')") - "\n") + ;; Ensure at least two completions: + ;; - Random prefix avoids common prefix inline completion + ;; - Two completions avoid single inline completion + ;; - One sure completion avoids waiting output timeout + "try: + import readline + def completer(text, state, + real_completer=readline.get_completer(), + last_state=[None]): + completion = None + if state == 0: + last_state[0] = None + if last_state[0] is None: + completion = real_completer(text, state) + if not completion: + last_state[0] = state + if (state == last_state[0] or + state - 1 == last_state[0] == 0): + import random + completion = '%s%d__dummy_completion__' % ( + text, random.randint(1000, 10000)) + return completion + readline.set_completer(completer) + if readline.__doc__ and 'libedit' in readline.__doc__: + readline.parse_and_bind('bind ^I rl_complete') + else: + readline.parse_and_bind('tab: complete') + readline.parse_and_bind('set page-completions off') + print('python.el: readline is available') + del completer, readline # Env cleanup +except: + print('python.el: readline not available')" process) (python-shell-accept-process-output process) (when (save-excursion @@ -3206,9 +3216,7 @@ completion." #'comint-redirect-filter original-filter-fn)) (set-process-filter process #'comint-redirect-filter)) (process-send-string process input-to-send) - (accept-process-output - process - python-shell-completion-native-output-timeout) + (accept-process-output process 0.3) ;; XXX: can't use `python-shell-accept-process-output' ;; here because there are no guarantees on how output ;; ends. The workaround here is to call @@ -3217,13 +3225,12 @@ completion." (while (accept-process-output process python-shell-completion-native-output-timeout)) - (cl-remove - (concat input "__dummy_completion__") + (cl-remove-if + (lambda (c) (string-match "__dummy_completion__" c)) (split-string (buffer-substring-no-properties (point-min) (point-max)) - separators t) - :test #'string=))) + separators t)))) (set-process-filter process original-filter-fn))))) (defun python-shell-completion-get-completions (process import input)