diff options
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 136 |
1 files changed, 94 insertions, 42 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index c89241bbaa0..da38152558f 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -3040,10 +3040,14 @@ When a match is found, native completion is disabled." | |||
| 3040 | "Enable readline based native completion." | 3040 | "Enable readline based native completion." |
| 3041 | :type 'boolean) | 3041 | :type 'boolean) |
| 3042 | 3042 | ||
| 3043 | (defcustom python-shell-completion-native-output-timeout 0.01 | 3043 | (defcustom python-shell-completion-native-output-timeout 5.0 |
| 3044 | "Time in seconds to wait for completion output before giving up." | 3044 | "Time in seconds to wait for completion output before giving up." |
| 3045 | :type 'float) | 3045 | :type 'float) |
| 3046 | 3046 | ||
| 3047 | (defcustom python-shell-completion-native-try-output-timeout 1.0 | ||
| 3048 | "Time in seconds to wait for *trying* native completion output." | ||
| 3049 | :type 'float) | ||
| 3050 | |||
| 3047 | (defvar python-shell-completion-native-redirect-buffer | 3051 | (defvar python-shell-completion-native-redirect-buffer |
| 3048 | " *Python completions redirect*" | 3052 | " *Python completions redirect*" |
| 3049 | "Buffer to be used to redirect output of readline commands.") | 3053 | "Buffer to be used to redirect output of readline commands.") |
| @@ -3057,7 +3061,9 @@ When a match is found, native completion is disabled." | |||
| 3057 | 3061 | ||
| 3058 | (defun python-shell-completion-native-try () | 3062 | (defun python-shell-completion-native-try () |
| 3059 | "Return non-nil if can trigger native completion." | 3063 | "Return non-nil if can trigger native completion." |
| 3060 | (let ((python-shell-completion-native-enable t)) | 3064 | (let ((python-shell-completion-native-enable t) |
| 3065 | (python-shell-completion-native-output-timeout | ||
| 3066 | python-shell-completion-native-try-output-timeout)) | ||
| 3061 | (python-shell-completion-native-get-completions | 3067 | (python-shell-completion-native-get-completions |
| 3062 | (get-buffer-process (current-buffer)) | 3068 | (get-buffer-process (current-buffer)) |
| 3063 | nil "int"))) | 3069 | nil "int"))) |
| @@ -3065,27 +3071,73 @@ When a match is found, native completion is disabled." | |||
| 3065 | (defun python-shell-completion-native-setup () | 3071 | (defun python-shell-completion-native-setup () |
| 3066 | "Try to setup native completion, return non-nil on success." | 3072 | "Try to setup native completion, return non-nil on success." |
| 3067 | (let ((process (python-shell-get-process))) | 3073 | (let ((process (python-shell-get-process))) |
| 3068 | (python-shell-send-string | 3074 | (python-shell-send-string " |
| 3069 | (funcall | 3075 | def __PYTHON_EL_native_completion_setup(): |
| 3070 | 'mapconcat | 3076 | try: |
| 3071 | #'identity | 3077 | import readline |
| 3072 | (list | 3078 | try: |
| 3073 | "try:" | 3079 | import __builtin__ |
| 3074 | " import readline, rlcompleter" | 3080 | except ImportError: |
| 3075 | ;; Remove parens on callables as it breaks completion on | 3081 | # Python 3 |
| 3076 | ;; arguments (e.g. str(Ari<tab>)). | 3082 | import builtins as __builtin__ |
| 3077 | " class Completer(rlcompleter.Completer):" | 3083 | builtins = dir(__builtin__) |
| 3078 | " def _callable_postfix(self, val, word):" | 3084 | is_ipython = ('__IPYTHON__' in builtins or |
| 3079 | " return word" | 3085 | '__IPYTHON__active' in builtins) |
| 3080 | " readline.set_completer(Completer().complete)" | 3086 | class __PYTHON_EL_Completer: |
| 3081 | " if readline.__doc__ and 'libedit' in readline.__doc__:" | 3087 | PYTHON_EL_WRAPPED = True |
| 3082 | " readline.parse_and_bind('bind ^I rl_complete')" | 3088 | def __init__(self, completer): |
| 3083 | " else:" | 3089 | self.completer = completer |
| 3084 | " readline.parse_and_bind('tab: complete')" | 3090 | self.last_completion = None |
| 3085 | " print ('python.el: readline is available')" | 3091 | def __call__(self, text, state): |
| 3086 | "except:" | 3092 | if state == 0: |
| 3087 | " print ('python.el: readline not available')") | 3093 | # The first completion is always a dummy completion. This |
| 3088 | "\n") | 3094 | # ensures proper output for sole completions and a current |
| 3095 | # input safeguard when no completions are available. | ||
| 3096 | self.last_completion = None | ||
| 3097 | completion = '0__dummy_completion__' | ||
| 3098 | else: | ||
| 3099 | completion = self.completer(text, state - 1) | ||
| 3100 | if not completion: | ||
| 3101 | if state == 1: | ||
| 3102 | # When no completions are available, two non-sharing | ||
| 3103 | # prefix strings are returned just to ensure output | ||
| 3104 | # while preventing changes to current input. | ||
| 3105 | completion = '1__dummy_completion__' | ||
| 3106 | elif self.last_completion != '~~~~__dummy_completion__': | ||
| 3107 | # This marks the end of output. | ||
| 3108 | completion = '~~~~__dummy_completion__' | ||
| 3109 | elif completion.endswith('('): | ||
| 3110 | # Remove parens on callables as it breaks completion on | ||
| 3111 | # arguments (e.g. str(Ari<tab>)). | ||
| 3112 | completion = completion[:-1] | ||
| 3113 | self.last_completion = completion | ||
| 3114 | return completion | ||
| 3115 | completer = readline.get_completer() | ||
| 3116 | if not completer: | ||
| 3117 | # Used as last resort to avoid breaking customizations. | ||
| 3118 | import rlcompleter | ||
| 3119 | completer = readline.get_completer() | ||
| 3120 | if completer and not getattr(completer, 'PYTHON_EL_WRAPPED', False): | ||
| 3121 | # Wrap the existing completer function only once. | ||
| 3122 | new_completer = __PYTHON_EL_Completer(completer) | ||
| 3123 | if not is_ipython: | ||
| 3124 | readline.set_completer(new_completer) | ||
| 3125 | else: | ||
| 3126 | # IPython hacks readline such that `readline.set_completer` | ||
| 3127 | # won't work. This workaround injects the new completer | ||
| 3128 | # function into the existing instance directly. | ||
| 3129 | instance = getattr(completer, 'im_self', completer.__self__) | ||
| 3130 | instance.rlcomplete = new_completer | ||
| 3131 | if readline.__doc__ and 'libedit' in readline.__doc__: | ||
| 3132 | readline.parse_and_bind('bind ^I rl_complete') | ||
| 3133 | else: | ||
| 3134 | readline.parse_and_bind('tab: complete') | ||
| 3135 | # Require just one tab to send output. | ||
| 3136 | readline.parse_and_bind('set show-all-if-ambiguous on') | ||
| 3137 | print ('python.el: readline is available') | ||
| 3138 | except IOError: | ||
| 3139 | print ('python.el: readline not available') | ||
| 3140 | __PYTHON_EL_native_completion_setup()" | ||
| 3089 | process) | 3141 | process) |
| 3090 | (python-shell-accept-process-output process) | 3142 | (python-shell-accept-process-output process) |
| 3091 | (when (save-excursion | 3143 | (when (save-excursion |
| @@ -3163,9 +3215,8 @@ completion." | |||
| 3163 | (original-filter-fn (process-filter process)) | 3215 | (original-filter-fn (process-filter process)) |
| 3164 | (redirect-buffer (get-buffer-create | 3216 | (redirect-buffer (get-buffer-create |
| 3165 | python-shell-completion-native-redirect-buffer)) | 3217 | python-shell-completion-native-redirect-buffer)) |
| 3166 | (separators (python-rx | 3218 | (separators (python-rx (or whitespace open-paren close-paren))) |
| 3167 | (or whitespace open-paren close-paren))) | 3219 | (trigger "\t") |
| 3168 | (trigger "\t\t\t") | ||
| 3169 | (new-input (concat input trigger)) | 3220 | (new-input (concat input trigger)) |
| 3170 | (input-length | 3221 | (input-length |
| 3171 | (save-excursion | 3222 | (save-excursion |
| @@ -3187,7 +3238,8 @@ completion." | |||
| 3187 | (comint-redirect-insert-matching-regexp nil) | 3238 | (comint-redirect-insert-matching-regexp nil) |
| 3188 | ;; Feed it some regex that will never match. | 3239 | ;; Feed it some regex that will never match. |
| 3189 | (comint-redirect-finished-regexp "^\\'$") | 3240 | (comint-redirect-finished-regexp "^\\'$") |
| 3190 | (comint-redirect-output-buffer redirect-buffer)) | 3241 | (comint-redirect-output-buffer redirect-buffer) |
| 3242 | (current-time (float-time))) | ||
| 3191 | ;; Compatibility with Emacs 24.x. Comint changed and | 3243 | ;; Compatibility with Emacs 24.x. Comint changed and |
| 3192 | ;; now `comint-redirect-filter' gets 3 args. This | 3244 | ;; now `comint-redirect-filter' gets 3 args. This |
| 3193 | ;; checks which version of `comint-redirect-filter' is | 3245 | ;; checks which version of `comint-redirect-filter' is |
| @@ -3200,22 +3252,22 @@ completion." | |||
| 3200 | #'comint-redirect-filter original-filter-fn)) | 3252 | #'comint-redirect-filter original-filter-fn)) |
| 3201 | (set-process-filter process #'comint-redirect-filter)) | 3253 | (set-process-filter process #'comint-redirect-filter)) |
| 3202 | (process-send-string process input-to-send) | 3254 | (process-send-string process input-to-send) |
| 3203 | (accept-process-output | 3255 | ;; Grab output until our dummy completion used as |
| 3204 | process | 3256 | ;; output end marker is found. Output is accepted |
| 3205 | python-shell-completion-native-output-timeout) | 3257 | ;; *very* quickly to keep the shell super-responsive. |
| 3206 | ;; XXX: can't use `python-shell-accept-process-output' | 3258 | (while (and (not (re-search-backward "~~~~__dummy_completion__" nil t)) |
| 3207 | ;; here because there are no guarantees on how output | 3259 | (< (- current-time (float-time)) |
| 3208 | ;; ends. The workaround here is to call | 3260 | python-shell-completion-native-output-timeout)) |
| 3209 | ;; `accept-process-output' until we don't find anything | 3261 | (accept-process-output process 0.01)) |
| 3210 | ;; else to accept. | ||
| 3211 | (while (accept-process-output | ||
| 3212 | process | ||
| 3213 | python-shell-completion-native-output-timeout)) | ||
| 3214 | (cl-remove-duplicates | 3262 | (cl-remove-duplicates |
| 3215 | (split-string | 3263 | (cl-remove-if |
| 3216 | (buffer-substring-no-properties | 3264 | (lambda (c) |
| 3217 | (point-min) (point-max)) | 3265 | (string-match "__dummy_completion__" c)) |
| 3218 | separators t)))) | 3266 | (split-string |
| 3267 | (buffer-substring-no-properties | ||
| 3268 | (point-min) (point-max)) | ||
| 3269 | separators t)) | ||
| 3270 | :test #'string=))) | ||
| 3219 | (set-process-filter process original-filter-fn)))))) | 3271 | (set-process-filter process original-filter-fn)))))) |
| 3220 | 3272 | ||
| 3221 | (defun python-shell-completion-get-completions (process import input) | 3273 | (defun python-shell-completion-get-completions (process import input) |