From 4932d26b5df14af01ae757b2a5232d157df69008 Mon Sep 17 00:00:00 2001 From: Augusto Stoffel Date: Sun, 4 Sep 2022 13:13:57 +0200 Subject: Python shells dedicated to a project * lisp/progmodes/python.el: Require 'seq' and (optionally) 'compat' and 'project' libraries. (python-shell-dedicated): New user option (python-shell-get-process-name): Adapt to project-dedicated shells. (run-python): Offer possibility to create a project-dedicated shell, or use 'python-shell-dedicated' as the default behavior. (python-shell-get-buffer): Adapt to project-dedicated shells (bug#56997). --- lisp/progmodes/python.el | 78 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 24 deletions(-) (limited to 'lisp/progmodes/python.el') diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index d3ffc2db2c9..6020d52b91f 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -5,7 +5,7 @@ ;; Author: Fabián E. Gallina ;; URL: https://github.com/fgallina/python.el ;; Version: 0.28 -;; Package-Requires: ((emacs "24.4") (cl-lib "1.0")) +;; Package-Requires: ((emacs "24.4") (compat "28.1.2.1") (seq "2.23")) ;; Maintainer: emacs-devel@gnu.org ;; Created: Jul 2010 ;; Keywords: languages @@ -245,6 +245,9 @@ (require 'ansi-color) (require 'cl-lib) (require 'comint) +(require 'compat nil 'noerror) +(require 'project nil 'noerror) +(require 'seq) (eval-when-compile (require 'subr-x)) ;For `string-empty-p'. ;; Avoid compiler warnings @@ -2304,6 +2307,16 @@ virtualenv." "`compilation-error-regexp-alist' for inferior Python." :type '(alist regexp)) +(defcustom python-shell-dedicated nil + "Whether to make Python shells dedicated by default. +This option influences `run-python' when called without a prefix +argument. If `buffer' or `project', create a Python shell +dedicated to the current buffer or its project (if one is found)." + :version "29.1" + :type '(choice (const :tag "To buffer" buffer) + (const :tag "To project" project) + (const :tag "Not dedicated" nil))) + (defvar python-shell-output-filter-in-progress nil) (defvar python-shell-output-filter-buffer nil) @@ -2666,12 +2679,19 @@ from `python-shell-prompt-regexp', (defun python-shell-get-process-name (dedicated) "Calculate the appropriate process name for inferior Python process. -If DEDICATED is t returns a string with the form -`python-shell-buffer-name'[`buffer-name'] else returns the value -of `python-shell-buffer-name'." - (if dedicated - (format "%s[%s]" python-shell-buffer-name (buffer-name)) - python-shell-buffer-name)) +If DEDICATED is nil, this is simply `python-shell-buffer-name'. +If DEDICATED is `buffer' or `project', append the current buffer +name respectively the current project name." + (pcase dedicated + ('nil python-shell-buffer-name) + ('project + (if-let ((proj (and (featurep 'project) + (project-current)))) + (format "%s[%s]" python-shell-buffer-name (file-name-nondirectory + (directory-file-name + (project-root proj)))) + python-shell-buffer-name)) + (_ (format "%s[%s]" python-shell-buffer-name (buffer-name))))) (defun python-shell-internal-get-process-name () "Calculate the appropriate process name for Internal Python process. @@ -3129,8 +3149,8 @@ killed." Argument CMD defaults to `python-shell-calculate-command' return value. When called interactively with `prefix-arg', it allows the user to edit such value and choose whether the interpreter -should be DEDICATED for the current buffer. When numeric prefix -arg is other than 0 or 4 do not SHOW. +should be DEDICATED to the current buffer or project. When +numeric prefix arg is other than 0 or 4 do not SHOW. For a given buffer and same values of DEDICATED, if a process is already running for it, it will do nothing. This means that if @@ -3144,13 +3164,25 @@ process buffer for a list of commands.)" (if current-prefix-arg (list (read-shell-command "Run Python: " (python-shell-calculate-command)) - (y-or-n-p "Make dedicated process? ") + (alist-get (car (read-multiple-choice "Make dedicated process?" + '((?b "to buffer") + (?p "to project") + (?n "no")))) + '((?b . buffer) (?p . project))) (= (prefix-numeric-value current-prefix-arg) 4)) - (list (python-shell-calculate-command) nil t))) - (let ((buffer - (python-shell-make-comint - (or cmd (python-shell-calculate-command)) - (python-shell-get-process-name dedicated) show))) + (list (python-shell-calculate-command) + python-shell-dedicated + t))) + (let* ((project (and (eq 'project dedicated) + (featurep 'project) + (project-current t))) + (default-directory (if project + (project-root project) + default-directory)) + (buffer (python-shell-make-comint + (or cmd (python-shell-calculate-command)) + (python-shell-get-process-name dedicated) + show))) (get-buffer-process buffer))) (defun run-python-internal () @@ -3180,15 +3212,13 @@ startup." If current buffer is in `inferior-python-mode', return it." (if (derived-mode-p 'inferior-python-mode) (current-buffer) - (let* ((dedicated-proc-name (python-shell-get-process-name t)) - (dedicated-proc-buffer-name (format "*%s*" dedicated-proc-name)) - (global-proc-name (python-shell-get-process-name nil)) - (global-proc-buffer-name (format "*%s*" global-proc-name)) - (dedicated-running (comint-check-proc dedicated-proc-buffer-name)) - (global-running (comint-check-proc global-proc-buffer-name))) - ;; Always prefer dedicated - (or (and dedicated-running dedicated-proc-buffer-name) - (and global-running global-proc-buffer-name))))) + (seq-some + (lambda (dedicated) + (let* ((proc-name (python-shell-get-process-name dedicated)) + (buffer-name (format "*%s*" proc-name))) + (when (comint-check-proc buffer-name) + buffer-name))) + '(buffer project nil)))) (defun python-shell-get-process () "Return inferior Python process for current buffer." -- cgit v1.2.1 From 4d50d413e67dd8ae183af8b68f315a667ebf2add Mon Sep 17 00:00:00 2001 From: Augusto Stoffel Date: Sun, 4 Sep 2022 13:14:58 +0200 Subject: Add Python import management commands * lisp/progmodes/python.el (python-interpreter): New variable (python-mode-map): Keybindings and menu entries for new commands (python--list-imports, python-import-history, python--query-import) (python--do-isort): New variables and helper functions. (python-add-import, python-import-symbol-at-point) (python-remove-import, python-sort-imports, python-fix-imports): New interactive commands (bug#57574). --- lisp/progmodes/python.el | 270 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 265 insertions(+), 5 deletions(-) (limited to 'lisp/progmodes/python.el') diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 6020d52b91f..147c5f248d2 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -34,7 +34,8 @@ ;; Implements Syntax highlighting, Indentation, Movement, Shell ;; interaction, Shell completion, Shell virtualenv support, Shell ;; package support, Shell syntax highlighting, Pdb tracking, Symbol -;; completion, Skeletons, FFAP, Code Check, ElDoc, Imenu. +;; completion, Skeletons, FFAP, Code Check, ElDoc, Imenu, Flymake, +;; Import management. ;; Syntax highlighting: Fontification of code is provided and supports ;; python's triple quoted strings properly. @@ -69,7 +70,7 @@ ;; variables. This example enables IPython globally: ;; (setq python-shell-interpreter "ipython" -;; python-shell-interpreter-args "-i") +;; python-shell-interpreter-args "--simple-prompt") ;; Using the "console" subcommand to start IPython in server-client ;; mode is known to fail intermittently due a bug on IPython itself @@ -240,6 +241,21 @@ ;; I'd recommend the first one since you'll get the same behavior for ;; all modes out-of-the-box. +;; Flymake: A Flymake backend, using the pyflakes program by default, +;; is provided. You can also use flake8 or pylint by customizing +;; `python-flymake-command'. + +;; Import management: The commands `python-sort-imports', +;; `python-add-import', `python-remove-import', and +;; `python-fix-imports' automate the editing of import statements at +;; the top of the buffer, which tend to be a tedious task in larger +;; projects. These commands require that the isort library is +;; available to the interpreter pointed at by `python-interpreter'. +;; The last command also requires pyflakes. These dependencies can be +;; installed, among other methods, with the following command: +;; +;; pip install isort pyflakes + ;;; Code: (require 'ansi-color) @@ -268,6 +284,12 @@ :version "24.3" :link '(emacs-commentary-link "python")) +(defcustom python-interpreter "python" + "Python interpreter for noninteractive use. +To customize the Python shell, modify `python-shell-interpreter' +instead." + :version "29.1" + :type 'string) ;;; Bindings @@ -306,6 +328,11 @@ (define-key map "\C-c\C-v" #'python-check) (define-key map "\C-c\C-f" #'python-eldoc-at-point) (define-key map "\C-c\C-d" #'python-describe-at-point) + ;; Import management + (define-key map "\C-c\C-ia" #'python-add-import) + (define-key map "\C-c\C-if" #'python-fix-imports) + (define-key map "\C-c\C-ir" #'python-remove-import) + (define-key map "\C-c\C-is" #'python-sort-imports) ;; Utilities (substitute-key-definition #'complete-symbol #'completion-at-point map global-map) @@ -351,7 +378,17 @@ ["Help on symbol" python-eldoc-at-point :help "Get help on symbol at point"] ["Complete symbol" completion-at-point - :help "Complete symbol before point"])) + :help "Complete symbol before point"] + "-----" + ["Add import" python-add-import + :help "Add an import statement to the top of this buffer"] + ["Remove import" python-remove-import + :help "Remove an import statement from the top of this buffer"] + ["Sort imports" python-sort-imports + :help "Sort the import statements at the top of this buffer"] + ["Fix imports" python-fix-imports + :help "Add missing imports and remove unused ones from the current buffer"] + )) map) "Keymap for `python-mode'.") @@ -5852,6 +5889,225 @@ REPORT-FN is Flymake's callback function." (process-send-eof python--flymake-proc)))) +;;; Import management +(defconst python--list-imports "\ +from isort import find_imports_in_stream, find_imports_in_paths +from sys import argv, stdin + +query, files, result = argv[1] or None, argv[2:], {} + +if files: + imports = find_imports_in_paths(files, top_only=True) +else: + imports = find_imports_in_stream(stdin, top_only=True) + +for imp in imports: + if query is None or query == (imp.alias or imp.attribute or imp.module): + key = (imp.module, imp.attribute or '', imp.alias or '') + if key not in result: + result[key] = imp.statement() + +for key in sorted(result): + print(result[key]) +" + "Script to list import statements in Python code.") + +(defvar python-import-history nil + "History variable for `python-import' commands.") + +(defun python--import-sources () + "List files containing Python imports that may be useful in the current buffer." + (if-let (((featurep 'project)) ;For compatibility with Emacs < 26 + (proj (project-current))) + (seq-filter (lambda (s) (string-match-p "\\.py[ciw]?\\'" s)) + (project-files proj)) + (list default-directory))) + +(defun python--list-imports (name source) + "List all Python imports matching NAME in SOURCE. +If NAME is nil, list all imports. SOURCE can be a buffer or a +list of file names or directories; the latter are searched +recursively." + (let ((buffer (current-buffer))) + (with-temp-buffer + (let* ((temp (current-buffer)) + (status (if (bufferp source) + (with-current-buffer source + (call-process-region (point-min) (point-max) + python-interpreter + nil (list temp nil) nil + "-c" python--list-imports + (or name ""))) + (with-current-buffer buffer + (apply #'call-process + python-interpreter + nil (list temp nil) nil + "-c" python--list-imports + (or name "") + (mapcar #'file-local-name source))))) + lines) + (unless (eq 0 status) + (error "%s exited with status %s (maybe isort is missing?)" + python-interpreter status)) + (goto-char (point-min)) + (while (not (eobp)) + (push (buffer-substring-no-properties (point) (pos-eol)) + lines) + (forward-line 1)) + (nreverse lines))))) + +(defun python--query-import (name source prompt) + "Read a Python import statement defining NAME. +A list of candidates is produced by `python--list-imports' using +the NAME and SOURCE arguments. An interactive query, using the +PROMPT string, is made unless there is a single candidate." + (let* ((cands (python--list-imports name source)) + ;; Don't use DEF argument of `completing-read', so it is able + ;; to return the empty string. + (minibuffer-default-add-function + (lambda () + (setq minibuffer-default (with-minibuffer-selected-window + (thing-at-point 'symbol))))) + (statement (cond ((and name (length= cands 1)) + (car cands)) + (prompt + (completing-read prompt + (or cands python-import-history) + nil nil nil + 'python-import-history))))) + (unless (string-empty-p statement) + statement))) + +(defun python--do-isort (&rest args) + "Edit the current buffer using isort called with ARGS. +Return non-nil if the buffer was actually modified." + (let ((buffer (current-buffer))) + (with-temp-buffer + (let ((temp (current-buffer))) + (with-current-buffer buffer + (let ((status (apply #'call-process-region + (point-min) (point-max) + python-interpreter + nil (list temp nil) nil + "-m" "isort" "-" args)) + (tick (buffer-chars-modified-tick))) + (unless (eq 0 status) + (error "%s exited with status %s (maybe isort is missing?)" + python-interpreter status)) + (replace-buffer-contents temp) + (not (eq tick (buffer-chars-modified-tick))))))))) + +;;;###autoload +(defun python-add-import (name) + "Add an import statement to the current buffer. + +Interactively, ask for an import statement using all imports +found in the current project as suggestions. With a prefix +argument, restrict the suggestions to imports defining the symbol +at point. If there is only one such suggestion, act without +asking. + +When calling from Lisp, use a non-nil NAME to restrict the +suggestions to imports defining NAME." + (interactive (list (when current-prefix-arg (thing-at-point 'symbol)))) + (when-let ((statement (python--query-import name + (python--import-sources) + "Add import: "))) + (if (python--do-isort "--add" statement) + (message "Added `%s'" statement) + (message "(No changes in Python imports needed)")))) + +;;;###autoload +(defun python-import-symbol-at-point () + "Add an import statement for the symbol at point to the current buffer. +This works like `python-add-import', but with the opposite +behavior regarding the prefix argument." + (interactive nil) + (python-add-import (unless current-prefix-arg (thing-at-point 'symbol)))) + +;;;###autoload +(defun python-remove-import (name) + "Remove an import statement from the current buffer. + +Interactively, ask for an import statement to remove, displaying +the imports of the current buffer as suggestions. With a prefix +argument, restrict the suggestions to imports defining the symbol +at point. If there is only one such suggestion, act without +asking." + (interactive (list (when current-prefix-arg (thing-at-point 'symbol)))) + (when-let ((statement (python--query-import name (current-buffer) + "Remove import: "))) + (if (python--do-isort "--rm" statement) + (message "Removed `%s'" statement) + (message "(No changes in Python imports needed)")))) + +;;;###autoload +(defun python-sort-imports () + "Sort Python imports in the current buffer." + (interactive) + (if (python--do-isort) + (message "Sorted imports") + (message "(No changes in Python imports needed)"))) + +;;;###autoload +(defun python-fix-imports () + "Add missing imports and remove unused ones from the current buffer." + (interactive) + (let ((buffer (current-buffer)) + undefined unused add remove) + ;; Compute list of undefined and unused names + (with-temp-buffer + (let ((temp (current-buffer))) + (with-current-buffer buffer + (call-process-region (point-min) (point-max) + python-interpreter + nil temp nil + "-m" "pyflakes")) + (goto-char (point-min)) + (when (looking-at-p ".* No module named pyflakes$") + (error "%s couldn't find pyflakes" python-interpreter)) + (while (not (eobp)) + (cond ((looking-at ".* undefined name '\\([^']+\\)'$") + (push (match-string 1) undefined)) + ((looking-at ".*'\\([^']+\\)' imported but unused$") + (push (match-string 1) unused))) + (forward-line 1)))) + ;; Compute imports to be added + (dolist (name (seq-uniq undefined)) + (when-let ((statement (python--query-import name + (python--import-sources) + (format "\ +Add import for undefined name `%s' (empty to skip): " + name)))) + (push statement add))) + ;; Compute imports to be removed + (dolist (name (seq-uniq unused)) + ;; The unused imported names, as provided by pyflakes, are of + ;; the form "module.var" or "module.var as alias", independently + ;; of style of import statement used. + (let* ((filter + (lambda (statement) + (string= name + (thread-last + statement + (replace-regexp-in-string "^\\(from\\|import\\) " "") + (replace-regexp-in-string " import " "."))))) + (statements (seq-filter filter (python--list-imports nil buffer)))) + (when (length= statements 1) + (push (car statements) remove)))) + ;; Edit buffer and say goodbye + (if (not (or add remove)) + (message "(No changes in Python imports needed)") + (apply #'python--do-isort + (append (mapcan (lambda (x) (list "--add" x)) add) + (mapcan (lambda (x) (list "--rm" x)) remove))) + (message "%s" (concat (when add "Added ") + (when add (string-join add ", ")) + (when remove (if add " and removed " "Removed ")) + (when remove (string-join remove ", " ))))))) + + +;;; Major mode (defun python-electric-pair-string-delimiter () (when (and electric-pair-mode (memq last-command-event '(?\" ?\')) @@ -5973,8 +6229,10 @@ REPORT-FN is Flymake's callback function." ;;; Completion predicates for M-x ;; Commands that only make sense when editing Python code -(dolist (sym '(python-check +(dolist (sym '(python-add-import + python-check python-fill-paragraph + python-fix-imports python-indent-dedent-line python-indent-dedent-line-backspace python-indent-guess-indent-offset @@ -5999,9 +6257,11 @@ REPORT-FN is Flymake's callback function." python-nav-forward-statement python-nav-if-name-main python-nav-up-list + python-remove-import python-shell-send-buffer python-shell-send-defun - python-shell-send-statement)) + python-shell-send-statement + python-sort-imports)) (put sym 'completion-predicate #'python--completion-predicate)) (defun python-shell--completion-predicate (_ buffer) -- cgit v1.2.1 From 969983ea1fe4ecca6c714c84b033fa5d0195b753 Mon Sep 17 00:00:00 2001 From: Laurence Warne Date: Tue, 6 Sep 2022 12:28:12 +0200 Subject: Apply syntax highlighting for all python f-strings * lisp/progmodes/python.el (python--f-string-p) (python--font-lock-f-strings): Edit functions to use a regular expression matching all f-strings (bug#56757). --- lisp/progmodes/python.el | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'lisp/progmodes/python.el') diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 147c5f248d2..3247d7ad507 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -546,11 +546,22 @@ The type returned can be `comment', `string' or `paren'." font-lock-string-face) font-lock-comment-face)) +(defconst python--f-string-start-regexp + (rx bow + (or "f" "F" "fr" "Fr" "fR" "FR" "rf" "rF" "Rf" "RF") + (or "\"" "\"\"\"" "'" "'''")) + "A regular expression matching the beginning of an f-string. + +See URL `https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals'.") + (defun python--f-string-p (ppss) "Return non-nil if the pos where PPSS was found is inside an f-string." (and (nth 3 ppss) - (let ((spos (1- (nth 8 ppss)))) - (and (memq (char-after spos) '(?f ?F)) + (let* ((spos (1- (nth 8 ppss))) + (before-quote + (buffer-substring-no-properties (max (- spos 4) (point-min)) + (min (+ spos 2) (point-max))))) + (and (string-match-p python--f-string-start-regexp before-quote) (or (< (point-min) spos) (not (memq (char-syntax (char-before spos)) '(?w ?_)))))))) @@ -569,7 +580,7 @@ the {...} holes that appear within f-strings." (while (progn (while (and (not (python--f-string-p ppss)) - (re-search-forward "\\: Delete defsubr. * lisp/subr.el (buffer-has-markers-at): Remove obsoletion of above deleted DEFUN. * etc/TODO: Doc fix; don't mention above deleted function. * admin/cus-test.el (cus-test-get-options): * lisp/pcomplete.el: Doc fixes; don't mention removed items. ; * etc/NEWS: List removed items. --- lisp/progmodes/python.el | 34 ---------------------------------- 1 file changed, 34 deletions(-) (limited to 'lisp/progmodes/python.el') diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 3247d7ad507..9f9439aac69 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -528,16 +528,6 @@ The type returned can be `comment', `string' or `paren'." (eql (syntax-class (syntax-after (point))) (syntax-class (string-to-syntax ")")))) -(define-obsolete-function-alias - 'python-info-ppss-context #'python-syntax-context "24.3") - -(define-obsolete-function-alias - 'python-info-ppss-context-type #'python-syntax-context-type "24.3") - -(define-obsolete-function-alias - 'python-info-ppss-comment-or-string-p - #'python-syntax-comment-or-string-p "24.3") - (defun python-font-lock-syntactic-face-function (state) "Return syntactic face given STATE." (if (nth 3 state) @@ -953,17 +943,11 @@ It makes underscores and dots word constituent chars.") ;;; Indentation -(define-obsolete-variable-alias - 'python-indent 'python-indent-offset "24.3") - (defcustom python-indent-offset 4 "Default indentation offset for Python." :type 'integer :safe 'integerp) -(define-obsolete-variable-alias - 'python-guess-indent 'python-indent-guess-indent-offset "24.3") - (defcustom python-indent-guess-indent-offset t "Non-nil tells Python mode to guess `python-indent-offset' value." :type 'boolean @@ -3307,17 +3291,11 @@ be asked for their values." "Instead call `python-shell-get-process' and create one if returns nil." "25.1") -(define-obsolete-variable-alias - 'python-buffer 'python-shell-internal-buffer "24.3") - (defvar python-shell-internal-buffer nil "Current internal shell buffer for the current buffer. This is really not necessary at all for the code to work but it's there for compatibility with CEDET.") -(define-obsolete-variable-alias - 'python-preoutput-result 'python-shell-internal-last-output "24.3") - (defvar python-shell-internal-last-output nil "Last output captured by the internal shell. This is really not necessary at all for the code to work but it's @@ -3330,9 +3308,6 @@ there for compatibility with CEDET.") (get-process proc-name) (run-python-internal)))) -(define-obsolete-function-alias - 'python-proc #'python-shell-internal-get-or-create-process "24.3") - (defun python-shell--save-temp-file (string) (let* ((temporary-file-directory (if (file-remote-p default-directory) @@ -3449,12 +3424,6 @@ Returns the output. See `python-shell-send-string-no-output'." (replace-regexp-in-string "_emacs_out +" "" string) (python-shell-internal-get-or-create-process)))) -(define-obsolete-function-alias - 'python-send-receive #'python-shell-internal-send-string "24.3") - -(define-obsolete-function-alias - 'python-send-string #'python-shell-internal-send-string "24.3") - (defun python-shell-buffer-substring (start end &optional nomain no-cookie) "Send buffer substring from START to END formatted for shell. This is a wrapper over `buffer-substring' that takes care of @@ -4620,9 +4589,6 @@ JUSTIFY should be used (if applicable) as in `fill-paragraph'." ;;; Skeletons -(define-obsolete-variable-alias - 'python-use-skeletons 'python-skeleton-autoinsert "24.3") - (defcustom python-skeleton-autoinsert nil "Non-nil means template skeletons will be automagically inserted. This happens when pressing \"if\", for example, to prompt for -- cgit v1.2.1 From af2a25aa19338ed8ce1984eeed25919761b1257e Mon Sep 17 00:00:00 2001 From: Augusto Stoffel Date: Sun, 18 Sep 2022 12:53:04 +0200 Subject: Add new command python-shell-restart * lisp/progmodes/python.el (python-shell-restart): New command (bug#57885). --- lisp/progmodes/python.el | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'lisp/progmodes/python.el') diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 9f9439aac69..6ef468d2cbe 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -3217,6 +3217,26 @@ process buffer for a list of commands.)" show))) (get-buffer-process buffer))) +(defun python-shell-restart (&optional show) + "Restart the Python shell. +Optional argument SHOW (interactively, the prefix argument), if +non-nil, means also display the Python shell buffer." + (interactive "P") + (with-current-buffer + (or (and (derived-mode-p 'inferior-python-mode) + (current-buffer)) + (seq-some (lambda (dedicated) + (get-buffer (format "*%s*" (python-shell-get-process-name + dedicated)))) + '(buffer project nil)) + (user-error "No Python shell")) + (when-let ((proc (get-buffer-process (current-buffer)))) + (kill-process proc) + (while (accept-process-output proc))) + (python-shell-make-comint (python-shell-calculate-command) + (string-trim (buffer-name) "\\*" "\\*") + show))) + (defun run-python-internal () "Run an inferior Internal Python process. Input and output via buffer named after -- cgit v1.2.1 From 06618e9435a65ff1c3be864d5433ec136c2ffc0e Mon Sep 17 00:00:00 2001 From: Augusto Stoffel Date: Sun, 18 Sep 2022 12:53:28 +0200 Subject: Remap 'up-list' in python-mode-map * lisp/progmodes/python.el (python-mode-map): Remap 'up-list' to 'python-nav-up-list' (bug#57885). --- lisp/progmodes/python.el | 1 + 1 file changed, 1 insertion(+) (limited to 'lisp/progmodes/python.el') diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 6ef468d2cbe..09f94f4b341 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -300,6 +300,7 @@ instead." (define-key map [remap backward-sentence] #'python-nav-backward-block) (define-key map [remap forward-sentence] #'python-nav-forward-block) (define-key map [remap backward-up-list] #'python-nav-backward-up-list) + (define-key map [remap up-list] #'python-nav-up-list) (define-key map [remap mark-defun] #'python-mark-defun) (define-key map "\C-c\C-j" #'imenu) ;; Indent specific -- cgit v1.2.1 From 616dcf27e57388403d4c28d441bf7310bb665241 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Tue, 20 Sep 2022 12:21:40 +0200 Subject: ; Fix typos in Lisp symbols --- lisp/progmodes/python.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lisp/progmodes/python.el') diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index f7f1784b172..d73c1d4b239 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -2909,8 +2909,8 @@ interpreter is run. Variables `python-shell-font-lock-enable', `python-shell-completion-setup-code', `python-shell-completion-string-code', -`python-eldoc-setup-code', `python-eldoc-string-code', -`python-ffap-setup-code' and `python-ffap-string-code' can +`python-eldoc-setup-code', +`python-ffap-setup-code' can customize this mode for different Python interpreters. This mode resets `comint-output-filter-functions' locally, so you -- cgit v1.2.1 From 419b873f3998c32493e8ec8d18571868613e6315 Mon Sep 17 00:00:00 2001 From: kobarity Date: Fri, 23 Sep 2022 17:39:53 +0200 Subject: Fix syntax check in python-info-looking-at-beginning-of-defun * lisp/progmodes/python.el (python-info-looking-at-beginning-of-defun): Check syntax after moving to the beginning of line. * test/lisp/progmodes/python-tests.el (python-nav-beginning-of-defun-6) (python-end-of-defun-1, python-info-looking-at-beginning-of-defun-3): New tests (bug#58023). --- lisp/progmodes/python.el | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lisp/progmodes/python.el') diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index d5ff059cc8e..80c5b31b6ea 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -5505,11 +5505,11 @@ operator." "Check if point is at `beginning-of-defun' using SYNTAX-PPSS. When CHECK-STATEMENT is non-nil, the current statement is checked instead of the current physical line." - (and (not (python-syntax-context-type (or syntax-ppss (syntax-ppss)))) - (save-excursion - (when check-statement - (python-nav-beginning-of-statement)) - (beginning-of-line 1) + (save-excursion + (when check-statement + (python-nav-beginning-of-statement)) + (beginning-of-line 1) + (and (not (python-syntax-context-type (or syntax-ppss (syntax-ppss)))) (looking-at python-nav-beginning-of-defun-regexp)))) (defun python-info-looking-at-beginning-of-block () -- cgit v1.2.1