diff options
| author | Fabián Ezequiel Gallina | 2015-08-22 20:42:04 -0300 |
|---|---|---|
| committer | Fabián Ezequiel Gallina | 2015-08-22 20:42:04 -0300 |
| commit | 24ae05251587fbba4687544ec57565c8bc48071a (patch) | |
| tree | 17d37e47080f0dcc1a7b84971c7025c6751fc2f8 /lisp/progmodes/python.el | |
| parent | 0a3ed5f70c6025fbc2a7e3ca53f11770e4fabe61 (diff) | |
| download | emacs-24ae05251587fbba4687544ec57565c8bc48071a.tar.gz emacs-24ae05251587fbba4687544ec57565c8bc48071a.zip | |
python.el: fallback completion, ffap and eldoc setup enhancements
Setup codes are now sent continuously so that the current frame is
always taken into account. This allows working within debuggers
and always keeping a fresh version of setup codes that will return
proper results.
* lisp/progmodes/python.el (python-shell-setup-codes): Cleanup.
(python-shell-send-setup-code): Send code only when
python-shell-setup-codes is non-nil.
(python-shell-completion-string-code): Cleanup trailing newline.
(python-shell-completion-get-completions): Always use
python-shell-completion-setup-code.
(python-ffap-setup-code): Work with any object, not only modules.
(python-ffap-string-code): Cleanup trailing newline.
(python-ffap-module-path): Always use python-ffap-setup-code.
(python-eldoc-string-code): Cleanup trailing newline.
(python-eldoc--get-doc-at-point): Always use
python-eldoc-setup-code. Return non-nil only if docstring is
found.
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 125 |
1 files changed, 67 insertions, 58 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index f65380be34f..3bfc5cf4b6f 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -2008,9 +2008,7 @@ virtualenv." | |||
| 2008 | (define-obsolete-variable-alias | 2008 | (define-obsolete-variable-alias |
| 2009 | 'python-shell-virtualenv-path 'python-shell-virtualenv-root "25.1") | 2009 | 'python-shell-virtualenv-path 'python-shell-virtualenv-root "25.1") |
| 2010 | 2010 | ||
| 2011 | (defcustom python-shell-setup-codes '(python-shell-completion-setup-code | 2011 | (defcustom python-shell-setup-codes nil |
| 2012 | python-ffap-setup-code | ||
| 2013 | python-eldoc-setup-code) | ||
| 2014 | "List of code run by `python-shell-send-setup-codes'." | 2012 | "List of code run by `python-shell-send-setup-codes'." |
| 2015 | :type '(repeat symbol) | 2013 | :type '(repeat symbol) |
| 2016 | :group 'python) | 2014 | :group 'python) |
| @@ -3118,18 +3116,18 @@ t when called interactively." | |||
| 3118 | "Send all setup code for shell. | 3116 | "Send all setup code for shell. |
| 3119 | This function takes the list of setup code to send from the | 3117 | This function takes the list of setup code to send from the |
| 3120 | `python-shell-setup-codes' list." | 3118 | `python-shell-setup-codes' list." |
| 3121 | (let ((process (python-shell-get-process)) | 3119 | (when python-shell-setup-codes |
| 3122 | (code (concat | 3120 | (let ((process (python-shell-get-process)) |
| 3123 | (mapconcat | 3121 | (code (concat |
| 3124 | (lambda (elt) | 3122 | (mapconcat |
| 3125 | (cond ((stringp elt) elt) | 3123 | (lambda (elt) |
| 3126 | ((symbolp elt) (symbol-value elt)) | 3124 | (cond ((stringp elt) elt) |
| 3127 | (t ""))) | 3125 | ((symbolp elt) (symbol-value elt)) |
| 3128 | python-shell-setup-codes | 3126 | (t ""))) |
| 3129 | "\n\n") | 3127 | python-shell-setup-codes |
| 3130 | "\n\nprint ('python.el: sent setup code')"))) | 3128 | "\n\nprint ('python.el: sent setup code')")))) |
| 3131 | (python-shell-send-string code process) | 3129 | (python-shell-send-string code process) |
| 3132 | (python-shell-accept-process-output process))) | 3130 | (python-shell-accept-process-output process)))) |
| 3133 | 3131 | ||
| 3134 | (add-hook 'inferior-python-mode-hook | 3132 | (add-hook 'inferior-python-mode-hook |
| 3135 | #'python-shell-send-setup-code) | 3133 | #'python-shell-send-setup-code) |
| @@ -3187,7 +3185,7 @@ else: | |||
| 3187 | :group 'python) | 3185 | :group 'python) |
| 3188 | 3186 | ||
| 3189 | (defcustom python-shell-completion-string-code | 3187 | (defcustom python-shell-completion-string-code |
| 3190 | "';'.join(__PYTHON_EL_get_completions('''%s'''))\n" | 3188 | "';'.join(__PYTHON_EL_get_completions('''%s'''))" |
| 3191 | "Python code used to get a string of completions separated by semicolons. | 3189 | "Python code used to get a string of completions separated by semicolons. |
| 3192 | The string passed to the function is the current python name or | 3190 | The string passed to the function is the current python name or |
| 3193 | the full statement in the case of imports." | 3191 | the full statement in the case of imports." |
| @@ -3490,28 +3488,22 @@ completion." | |||
| 3490 | ;; Check whether a prompt matches a pdb string, an import | 3488 | ;; Check whether a prompt matches a pdb string, an import |
| 3491 | ;; statement or just the standard prompt and use the | 3489 | ;; statement or just the standard prompt and use the |
| 3492 | ;; correct python-shell-completion-*-code string | 3490 | ;; correct python-shell-completion-*-code string |
| 3493 | (cond ((and (string-match | 3491 | (when (string-match python-shell--prompt-calculated-input-regexp prompt) |
| 3494 | (concat "^" python-shell-prompt-pdb-regexp) prompt)) | 3492 | ;; Since there are no guarantees the user will remain |
| 3495 | ;; Since there are no guarantees the user will remain | 3493 | ;; in the same context where completion code was sent |
| 3496 | ;; in the same context where completion code was sent | 3494 | ;; (e.g. user steps into a function), safeguard |
| 3497 | ;; (e.g. user steps into a function), safeguard | 3495 | ;; resending completion setup continuously. |
| 3498 | ;; resending completion setup continuously. | 3496 | (concat python-shell-completion-setup-code |
| 3499 | (concat python-shell-completion-setup-code | 3497 | "\nprint (" python-shell-completion-string-code ")"))) |
| 3500 | "\nprint (" python-shell-completion-string-code ")")) | ||
| 3501 | ((string-match | ||
| 3502 | python-shell--prompt-calculated-input-regexp prompt) | ||
| 3503 | python-shell-completion-string-code) | ||
| 3504 | (t nil))) | ||
| 3505 | (subject (or import input))) | 3498 | (subject (or import input))) |
| 3506 | (and completion-code | 3499 | (when (and completion-code (> (length input) 0)) |
| 3507 | (> (length input) 0) | 3500 | (let ((completions |
| 3508 | (let ((completions | 3501 | (python-util-strip-string |
| 3509 | (python-util-strip-string | 3502 | (python-shell-send-string-no-output |
| 3510 | (python-shell-send-string-no-output | 3503 | (format completion-code subject) process)))) |
| 3511 | (format completion-code subject) process)))) | 3504 | (when (> (length completions) 2) |
| 3512 | (and (> (length completions) 2) | 3505 | (split-string completions |
| 3513 | (split-string completions | 3506 | "^'\\|^\"\\|;\\|'$\\|\"$" t))))))) |
| 3514 | "^'\\|^\"\\|;\\|'$\\|\"$" t))))))) | ||
| 3515 | 3507 | ||
| 3516 | (defun python-shell-completion-at-point (&optional process) | 3508 | (defun python-shell-completion-at-point (&optional process) |
| 3517 | "Function for `completion-at-point-functions' in `inferior-python-mode'. | 3509 | "Function for `completion-at-point-functions' in `inferior-python-mode'. |
| @@ -4055,13 +4047,22 @@ The skeleton will be bound to python-skeleton-NAME." | |||
| 4055 | ;;; FFAP | 4047 | ;;; FFAP |
| 4056 | 4048 | ||
| 4057 | (defcustom python-ffap-setup-code | 4049 | (defcustom python-ffap-setup-code |
| 4058 | "def __FFAP_get_module_path(module): | 4050 | " |
| 4051 | def __FFAP_get_module_path(objstr): | ||
| 4059 | try: | 4052 | try: |
| 4060 | import os | 4053 | import inspect |
| 4061 | path = __import__(module).__file__ | 4054 | import os.path |
| 4062 | if path[-4:] == '.pyc' and os.path.exists(path[0:-1]): | 4055 | # NameError exceptions are delayed until this point. |
| 4063 | path = path[:-1] | 4056 | obj = eval(objstr) |
| 4064 | return path | 4057 | module = inspect.getmodule(obj) |
| 4058 | filename = module.__file__ | ||
| 4059 | ext = os.path.splitext(filename)[1] | ||
| 4060 | if ext in ('.pyc', '.pyo'): | ||
| 4061 | # Point to the source file. | ||
| 4062 | filename = filename[:-1] | ||
| 4063 | if os.path.exists(filename): | ||
| 4064 | return filename | ||
| 4065 | return '' | ||
| 4065 | except: | 4066 | except: |
| 4066 | return ''" | 4067 | return ''" |
| 4067 | "Python code to get a module path." | 4068 | "Python code to get a module path." |
| @@ -4069,7 +4070,7 @@ The skeleton will be bound to python-skeleton-NAME." | |||
| 4069 | :group 'python) | 4070 | :group 'python) |
| 4070 | 4071 | ||
| 4071 | (defcustom python-ffap-string-code | 4072 | (defcustom python-ffap-string-code |
| 4072 | "__FFAP_get_module_path('''%s''')\n" | 4073 | "__FFAP_get_module_path('''%s''')" |
| 4073 | "Python code used to get a string with the path of a module." | 4074 | "Python code used to get a string with the path of a module." |
| 4074 | :type 'string | 4075 | :type 'string |
| 4075 | :group 'python) | 4076 | :group 'python) |
| @@ -4084,9 +4085,12 @@ The skeleton will be bound to python-skeleton-NAME." | |||
| 4084 | nil | 4085 | nil |
| 4085 | (let ((module-file | 4086 | (let ((module-file |
| 4086 | (python-shell-send-string-no-output | 4087 | (python-shell-send-string-no-output |
| 4087 | (format python-ffap-string-code module) process))) | 4088 | (concat |
| 4088 | (when module-file | 4089 | python-ffap-setup-code |
| 4089 | (substring-no-properties module-file 1 -1)))))) | 4090 | "\nprint (" (format python-ffap-string-code module) ")") |
| 4091 | process))) | ||
| 4092 | (unless (zerop (length module-file)) | ||
| 4093 | (python-util-strip-string module-file)))))) | ||
| 4090 | 4094 | ||
| 4091 | (defvar ffap-alist) | 4095 | (defvar ffap-alist) |
| 4092 | 4096 | ||
| @@ -4172,13 +4176,13 @@ See `python-check-command' for the default." | |||
| 4172 | doc = doc.splitlines()[0] | 4176 | doc = doc.splitlines()[0] |
| 4173 | except: | 4177 | except: |
| 4174 | doc = '' | 4178 | doc = '' |
| 4175 | print (doc)" | 4179 | return doc" |
| 4176 | "Python code to setup documentation retrieval." | 4180 | "Python code to setup documentation retrieval." |
| 4177 | :type 'string | 4181 | :type 'string |
| 4178 | :group 'python) | 4182 | :group 'python) |
| 4179 | 4183 | ||
| 4180 | (defcustom python-eldoc-string-code | 4184 | (defcustom python-eldoc-string-code |
| 4181 | "__PYDOC_get_help('''%s''')\n" | 4185 | "__PYDOC_get_help('''%s''')" |
| 4182 | "Python code used to get a string with the documentation of an object." | 4186 | "Python code used to get a string with the documentation of an object." |
| 4183 | :type 'string | 4187 | :type 'string |
| 4184 | :group 'python) | 4188 | :group 'python) |
| @@ -4204,15 +4208,20 @@ returns will be used. If not FORCE-PROCESS is passed what | |||
| 4204 | `python-shell-get-process' returns is used." | 4208 | `python-shell-get-process' returns is used." |
| 4205 | (let ((process (or force-process (python-shell-get-process)))) | 4209 | (let ((process (or force-process (python-shell-get-process)))) |
| 4206 | (when process | 4210 | (when process |
| 4207 | (let ((input (or force-input | 4211 | (let* ((input (or force-input |
| 4208 | (python-eldoc--get-symbol-at-point)))) | 4212 | (python-eldoc--get-symbol-at-point))) |
| 4209 | (and input | 4213 | (docstring |
| 4210 | ;; Prevent resizing the echo area when iPython is | 4214 | (when input |
| 4211 | ;; enabled. Bug#18794. | 4215 | ;; Prevent resizing the echo area when iPython is |
| 4212 | (python-util-strip-string | 4216 | ;; enabled. Bug#18794. |
| 4213 | (python-shell-send-string-no-output | 4217 | (python-util-strip-string |
| 4214 | (format python-eldoc-string-code input) | 4218 | (python-shell-send-string-no-output |
| 4215 | process))))))) | 4219 | (concat |
| 4220 | python-eldoc-setup-code | ||
| 4221 | "\nprint(" (format python-eldoc-string-code input) ")") | ||
| 4222 | process))))) | ||
| 4223 | (unless (zerop (length docstring)) | ||
| 4224 | docstring))))) | ||
| 4216 | 4225 | ||
| 4217 | (defun python-eldoc-function () | 4226 | (defun python-eldoc-function () |
| 4218 | "`eldoc-documentation-function' for Python. | 4227 | "`eldoc-documentation-function' for Python. |