diff options
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 229 |
1 files changed, 214 insertions, 15 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 8a85763f765..c46c5d68019 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -69,7 +69,7 @@ | |||
| 69 | ;; Besides that only the standard CPython (2.x and 3.x) shell and | 69 | ;; Besides that only the standard CPython (2.x and 3.x) shell and |
| 70 | ;; IPython are officially supported out of the box, the interaction | 70 | ;; IPython are officially supported out of the box, the interaction |
| 71 | ;; should support any other readline based Python shells as well | 71 | ;; should support any other readline based Python shells as well |
| 72 | ;; (e.g. Jython and Pypy have been reported to work). You can change | 72 | ;; (e.g. Jython and PyPy have been reported to work). You can change |
| 73 | ;; your default interpreter and commandline arguments by setting the | 73 | ;; your default interpreter and commandline arguments by setting the |
| 74 | ;; `python-shell-interpreter' and `python-shell-interpreter-args' | 74 | ;; `python-shell-interpreter' and `python-shell-interpreter-args' |
| 75 | ;; variables. This example enables IPython globally: | 75 | ;; variables. This example enables IPython globally: |
| @@ -119,18 +119,24 @@ | |||
| 119 | ;; modify its behavior. | 119 | ;; modify its behavior. |
| 120 | 120 | ||
| 121 | ;; Shell completion: hitting tab will try to complete the current | 121 | ;; Shell completion: hitting tab will try to complete the current |
| 122 | ;; word. Shell completion is implemented in such way that if you | 122 | ;; word. The two built-in mechanisms depend on Python's readline |
| 123 | ;; change the `python-shell-interpreter' it should be possible to | 123 | ;; module: the "native" completion is tried first and is activated |
| 124 | ;; integrate custom logic to calculate completions. To achieve this | 124 | ;; when `python-shell-completion-native-enable' is non-nil, the |
| 125 | ;; you just need to set `python-shell-completion-setup-code' and | 125 | ;; current `python-shell-interpreter' is not a member of the |
| 126 | ;; `python-shell-completion-string-code'. The default provided code, | 126 | ;; `python-shell-completion-native-disabled-interpreters' variable and |
| 127 | ;; enables autocompletion for both CPython and IPython (and ideally | 127 | ;; `python-shell-completion-native-setup' succeeds; the "fallback" or |
| 128 | ;; any readline based Python shell). This code depends on the | 128 | ;; "legacy" mechanism works by executing Python code in the background |
| 129 | ;; readline module, so if you are using some Operating System that | 129 | ;; and enables auto-completion for shells that do not support |
| 130 | ;; bundles Python without it (like Windows), installing pyreadline | 130 | ;; receiving escape sequences (with some limitations, i.e. completion |
| 131 | ;; from URL `http://ipython.scipy.org/moin/PyReadline/Intro' should | 131 | ;; in blocks does not work). The code executed for the "fallback" |
| 132 | ;; suffice. To troubleshoot why you are not getting any completions | 132 | ;; completion can be found in `python-shell-completion-setup-code' and |
| 133 | ;; you can try the following in your Python shell: | 133 | ;; `python-shell-completion-string-code' variables. Their default |
| 134 | ;; values enable completion for both CPython and IPython, and probably | ||
| 135 | ;; any readline based shell (it's known to work with PyPy). If your | ||
| 136 | ;; Python installation lacks readline (like CPython for Windows), | ||
| 137 | ;; installing pyreadline (URL `http://ipython.org/pyreadline.html') | ||
| 138 | ;; should suffice. To troubleshoot why you are not getting any | ||
| 139 | ;; completions, you can try the following in your Python shell: | ||
| 134 | 140 | ||
| 135 | ;; >>> import readline, rlcompleter | 141 | ;; >>> import readline, rlcompleter |
| 136 | 142 | ||
| @@ -256,6 +262,7 @@ | |||
| 256 | (defvar outline-heading-end-regexp) | 262 | (defvar outline-heading-end-regexp) |
| 257 | 263 | ||
| 258 | (autoload 'comint-mode "comint") | 264 | (autoload 'comint-mode "comint") |
| 265 | (autoload 'help-function-arglist "help-fns") | ||
| 259 | 266 | ||
| 260 | ;;;###autoload | 267 | ;;;###autoload |
| 261 | (add-to-list 'auto-mode-alist (cons (purecopy "\\.py\\'") 'python-mode)) | 268 | (add-to-list 'auto-mode-alist (cons (purecopy "\\.py\\'") 'python-mode)) |
| @@ -2997,6 +3004,194 @@ the full statement in the case of imports." | |||
| 2997 | "25.1" | 3004 | "25.1" |
| 2998 | "Completion string code must work for (i)pdb.") | 3005 | "Completion string code must work for (i)pdb.") |
| 2999 | 3006 | ||
| 3007 | (defcustom python-shell-completion-native-disabled-interpreters | ||
| 3008 | ;; PyPy's readline cannot handle some escape sequences yet. | ||
| 3009 | (list "pypy") | ||
| 3010 | "List of disabled interpreters. | ||
| 3011 | When a match is found, native completion is disabled." | ||
| 3012 | :type '(repeat string)) | ||
| 3013 | |||
| 3014 | (defcustom python-shell-completion-native-enable t | ||
| 3015 | "Enable readline based native completion." | ||
| 3016 | :type 'boolean) | ||
| 3017 | |||
| 3018 | (defcustom python-shell-completion-native-output-timeout 0.01 | ||
| 3019 | "Time in seconds to wait for completion output before giving up." | ||
| 3020 | :type 'float) | ||
| 3021 | |||
| 3022 | (defvar python-shell-completion-native-redirect-buffer | ||
| 3023 | " *Python completions redirect*" | ||
| 3024 | "Buffer to be used to redirect output of readline commands.") | ||
| 3025 | |||
| 3026 | (defun python-shell-completion-native-interpreter-disabled-p () | ||
| 3027 | "Return non-nil if interpreter has native completion disabled." | ||
| 3028 | (when python-shell-completion-native-disabled-interpreters | ||
| 3029 | (string-match | ||
| 3030 | (regexp-opt python-shell-completion-native-disabled-interpreters) | ||
| 3031 | (file-name-nondirectory python-shell-interpreter)))) | ||
| 3032 | |||
| 3033 | (defun python-shell-completion-native-try () | ||
| 3034 | "Return non-nil if can trigger native completion." | ||
| 3035 | (let ((python-shell-completion-native-enable t)) | ||
| 3036 | (python-shell-completion-native-get-completions | ||
| 3037 | (get-buffer-process (current-buffer)) | ||
| 3038 | nil "int"))) | ||
| 3039 | |||
| 3040 | (defun python-shell-completion-native-setup () | ||
| 3041 | "Try to setup native completion, return non-nil on success." | ||
| 3042 | (let ((process (python-shell-get-process))) | ||
| 3043 | (python-shell-send-string | ||
| 3044 | (funcall | ||
| 3045 | 'mapconcat | ||
| 3046 | #'identity | ||
| 3047 | (list | ||
| 3048 | "try:" | ||
| 3049 | " import readline, rlcompleter" | ||
| 3050 | ;; Remove parens on callables as it breaks completion on | ||
| 3051 | ;; arguments (e.g. str(Ari<tab>)). | ||
| 3052 | " class Completer(rlcompleter.Completer):" | ||
| 3053 | " def _callable_postfix(self, val, word):" | ||
| 3054 | " return word" | ||
| 3055 | " readline.set_completer(Completer().complete)" | ||
| 3056 | " if readline.__doc__ and 'libedit' in readline.__doc__:" | ||
| 3057 | " readline.parse_and_bind('bind ^I rl_complete')" | ||
| 3058 | " else:" | ||
| 3059 | " readline.parse_and_bind('tab: complete')" | ||
| 3060 | " print ('python.el: readline is available')" | ||
| 3061 | "except:" | ||
| 3062 | " print ('python.el: readline not available')") | ||
| 3063 | "\n") | ||
| 3064 | process) | ||
| 3065 | (python-shell-accept-process-output process) | ||
| 3066 | (when (save-excursion | ||
| 3067 | (re-search-backward | ||
| 3068 | (regexp-quote "python.el: readline is available") nil t 1)) | ||
| 3069 | (python-shell-completion-native-try)))) | ||
| 3070 | |||
| 3071 | (defun python-shell-completion-native-turn-off (&optional msg) | ||
| 3072 | "Turn off shell native completions. | ||
| 3073 | With argument MSG show deactivation message." | ||
| 3074 | (interactive "p") | ||
| 3075 | (python-shell-with-shell-buffer | ||
| 3076 | (set (make-local-variable 'python-shell-completion-native-enable) nil) | ||
| 3077 | (when msg | ||
| 3078 | (message "Shell native completion is disabled, using fallback")))) | ||
| 3079 | |||
| 3080 | (defun python-shell-completion-native-turn-on (&optional msg) | ||
| 3081 | "Turn on shell native completions. | ||
| 3082 | With argument MSG show deactivation message." | ||
| 3083 | (interactive "p") | ||
| 3084 | (python-shell-with-shell-buffer | ||
| 3085 | (set (make-local-variable 'python-shell-completion-native-enable) t) | ||
| 3086 | (python-shell-completion-native-turn-on-maybe msg))) | ||
| 3087 | |||
| 3088 | (defun python-shell-completion-native-turn-on-maybe (&optional msg) | ||
| 3089 | "Turn on native completions if enabled and available. | ||
| 3090 | With argument MSG show activation/deactivation message." | ||
| 3091 | (interactive "p") | ||
| 3092 | (python-shell-with-shell-buffer | ||
| 3093 | (when python-shell-completion-native-enable | ||
| 3094 | (cond | ||
| 3095 | ((python-shell-completion-native-interpreter-disabled-p) | ||
| 3096 | (python-shell-completion-native-turn-off msg)) | ||
| 3097 | ((python-shell-completion-native-setup) | ||
| 3098 | (when msg | ||
| 3099 | (message "Shell native completion is enabled."))) | ||
| 3100 | (t (lwarn | ||
| 3101 | '(python python-shell-completion-native-turn-on-maybe) | ||
| 3102 | :warning | ||
| 3103 | (concat | ||
| 3104 | "Your `python-shell-interpreter' doesn't seem to " | ||
| 3105 | "support readline, yet `python-shell-completion-native' " | ||
| 3106 | (format "was `t' and %S is not part of the " | ||
| 3107 | (file-name-nondirectory python-shell-interpreter)) | ||
| 3108 | "`python-shell-completion-native-disabled-interpreters' " | ||
| 3109 | "list. Native completions have been disabled locally. ")) | ||
| 3110 | (python-shell-completion-native-turn-off msg)))))) | ||
| 3111 | |||
| 3112 | (defun python-shell-completion-native-turn-on-maybe-with-msg () | ||
| 3113 | "Like `python-shell-completion-native-turn-on-maybe' but force messages." | ||
| 3114 | (python-shell-completion-native-turn-on-maybe t)) | ||
| 3115 | |||
| 3116 | (add-hook 'inferior-python-mode-hook | ||
| 3117 | #'python-shell-completion-native-turn-on-maybe-with-msg) | ||
| 3118 | |||
| 3119 | (defun python-shell-completion-native-toggle (&optional msg) | ||
| 3120 | "Toggle shell native completion. | ||
| 3121 | With argument MSG show activation/deactivation message." | ||
| 3122 | (interactive "p") | ||
| 3123 | (python-shell-with-shell-buffer | ||
| 3124 | (if python-shell-completion-native-enable | ||
| 3125 | (python-shell-completion-native-turn-off msg) | ||
| 3126 | (python-shell-completion-native-turn-on msg)) | ||
| 3127 | python-shell-completion-native-enable)) | ||
| 3128 | |||
| 3129 | (defun python-shell-completion-native-get-completions (process import input) | ||
| 3130 | "Get completions using native readline for PROCESS. | ||
| 3131 | When IMPORT is non-nil takes precedence over INPUT for | ||
| 3132 | completion." | ||
| 3133 | (when (and python-shell-completion-native-enable | ||
| 3134 | (python-util-comint-last-prompt) | ||
| 3135 | (>= (point) (cdr (python-util-comint-last-prompt)))) | ||
| 3136 | (let* ((input (or import input)) | ||
| 3137 | (original-filter-fn (process-filter process)) | ||
| 3138 | (redirect-buffer (get-buffer-create | ||
| 3139 | python-shell-completion-native-redirect-buffer)) | ||
| 3140 | (separators (python-rx | ||
| 3141 | (or whitespace open-paren close-paren))) | ||
| 3142 | (trigger "\t\t\t") | ||
| 3143 | (new-input (concat input trigger)) | ||
| 3144 | (input-length | ||
| 3145 | (save-excursion | ||
| 3146 | (+ (- (point-max) (comint-bol)) (length new-input)))) | ||
| 3147 | (delete-line-command (make-string input-length ?\b)) | ||
| 3148 | (input-to-send (concat new-input delete-line-command))) | ||
| 3149 | ;; Ensure restoring the process filter, even if the user quits | ||
| 3150 | ;; or there's some other error. | ||
| 3151 | (unwind-protect | ||
| 3152 | (with-current-buffer redirect-buffer | ||
| 3153 | ;; Cleanup the redirect buffer | ||
| 3154 | (delete-region (point-min) (point-max)) | ||
| 3155 | ;; Mimic `comint-redirect-send-command', unfortunately it | ||
| 3156 | ;; can't be used here because it expects a newline in the | ||
| 3157 | ;; command and that's exactly what we are trying to avoid. | ||
| 3158 | (let ((comint-redirect-echo-input nil) | ||
| 3159 | (comint-redirect-verbose nil) | ||
| 3160 | (comint-redirect-perform-sanity-check nil) | ||
| 3161 | (comint-redirect-insert-matching-regexp nil) | ||
| 3162 | ;; Feed it some regex that will never match. | ||
| 3163 | (comint-redirect-finished-regexp "^\\'$") | ||
| 3164 | (comint-redirect-output-buffer redirect-buffer)) | ||
| 3165 | ;; Compatibility with Emacs 24.x. Comint changed and | ||
| 3166 | ;; now `comint-redirect-filter' gets 3 args. This | ||
| 3167 | ;; checks which version of `comint-redirect-filter' is | ||
| 3168 | ;; in use based on its args and uses `apply-partially' | ||
| 3169 | ;; to make it up for the 3 args case. | ||
| 3170 | (if (= (length | ||
| 3171 | (help-function-arglist 'comint-redirect-filter)) 3) | ||
| 3172 | (set-process-filter | ||
| 3173 | process (apply-partially | ||
| 3174 | #'comint-redirect-filter original-filter-fn)) | ||
| 3175 | (set-process-filter process #'comint-redirect-filter)) | ||
| 3176 | (process-send-string process input-to-send) | ||
| 3177 | (accept-process-output | ||
| 3178 | process | ||
| 3179 | python-shell-completion-native-output-timeout) | ||
| 3180 | ;; XXX: can't use `python-shell-accept-process-output' | ||
| 3181 | ;; here because there are no guarantees on how output | ||
| 3182 | ;; ends. The workaround here is to call | ||
| 3183 | ;; `accept-process-output' until we don't find anything | ||
| 3184 | ;; else to accept. | ||
| 3185 | (while (accept-process-output | ||
| 3186 | process | ||
| 3187 | python-shell-completion-native-output-timeout)) | ||
| 3188 | (cl-remove-duplicates | ||
| 3189 | (split-string | ||
| 3190 | (buffer-substring-no-properties | ||
| 3191 | (point-min) (point-max)) | ||
| 3192 | separators t)))) | ||
| 3193 | (set-process-filter process original-filter-fn))))) | ||
| 3194 | |||
| 3000 | (defun python-shell-completion-get-completions (process import input) | 3195 | (defun python-shell-completion-get-completions (process import input) |
| 3001 | "Do completion at point using PROCESS for IMPORT or INPUT. | 3196 | "Do completion at point using PROCESS for IMPORT or INPUT. |
| 3002 | When IMPORT is non-nil takes precedence over INPUT for | 3197 | When IMPORT is non-nil takes precedence over INPUT for |
| @@ -3054,11 +3249,15 @@ using that one instead of current buffer's process." | |||
| 3054 | last-prompt-end | 3249 | last-prompt-end |
| 3055 | (forward-char (length (match-string-no-properties 0))) | 3250 | (forward-char (length (match-string-no-properties 0))) |
| 3056 | (point)))) | 3251 | (point)))) |
| 3057 | (end (point))) | 3252 | (end (point)) |
| 3253 | (completion-fn | ||
| 3254 | (if python-shell-completion-native-enable | ||
| 3255 | #'python-shell-completion-native-get-completions | ||
| 3256 | #'python-shell-completion-get-completions))) | ||
| 3058 | (list start end | 3257 | (list start end |
| 3059 | (completion-table-dynamic | 3258 | (completion-table-dynamic |
| 3060 | (apply-partially | 3259 | (apply-partially |
| 3061 | #'python-shell-completion-get-completions | 3260 | completion-fn |
| 3062 | process import-statement))))) | 3261 | process import-statement))))) |
| 3063 | 3262 | ||
| 3064 | (define-obsolete-function-alias | 3263 | (define-obsolete-function-alias |