diff options
| author | kobarity | 2022-08-17 12:44:56 +0200 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2022-08-17 12:44:56 +0200 |
| commit | af4cfb519415ed3c1d6d036aac908e4f9ee383eb (patch) | |
| tree | aa03cf5584fee7e15fa62743ee5852caac6d88b3 /lisp/progmodes/python.el | |
| parent | 8f784a27667fbebdf320388ef2ec46ae67f69230 (diff) | |
| download | emacs-af4cfb519415ed3c1d6d036aac908e4f9ee383eb.tar.gz emacs-af4cfb519415ed3c1d6d036aac908e4f9ee383eb.zip | |
Add Python blocks support for hideshow
* lisp/progmodes/python.el (python-nav-beginning-of-block-regexp):
New variable.
(python-hideshow-forward-sexp-function): Change to call
`python-nav-end-of-block'.
(python-hideshow-find-next-block): New function to be used as
FIND-NEXT-BLOCK-FUNC in `hs-special-modes-alist'.
(python-info-looking-at-beginning-of-block): New function to be
used as LOOKING-AT-BLOCK-START-P-FUNC in `hs-special-modes-alist'.
(python-mode): Change settings of `hs-special-modes-alist'.
* test/lisp/progmodes/python-tests.el
(python-hideshow-hide-levels-1): Fix to keep empty lines.
(python-info-looking-at-beginning-of-block-1)
(python-hideshow-hide-levels-3, python-hideshow-hide-levels-4)
(python-hideshow-hide-all-1, python-hideshow-hide-all-2)
(python-hideshow-hide-all-3, python-hideshow-hide-block-1): New
tests (bug#56635).
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 59 |
1 files changed, 53 insertions, 6 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 44df3186b27..afcfe1af53d 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -1504,6 +1504,10 @@ marks the next defun after the ones already marked." | |||
| 1504 | The name of the defun should be grouped so it can be retrieved | 1504 | The name of the defun should be grouped so it can be retrieved |
| 1505 | via `match-string'.") | 1505 | via `match-string'.") |
| 1506 | 1506 | ||
| 1507 | (defvar python-nav-beginning-of-block-regexp | ||
| 1508 | (python-rx line-start (* space) block-start) | ||
| 1509 | "Regexp matching block start.") | ||
| 1510 | |||
| 1507 | (defun python-nav--beginning-of-defun (&optional arg) | 1511 | (defun python-nav--beginning-of-defun (&optional arg) |
| 1508 | "Internal implementation of `python-nav-beginning-of-defun'. | 1512 | "Internal implementation of `python-nav-beginning-of-defun'. |
| 1509 | With positive ARG search backwards, else search forwards." | 1513 | With positive ARG search backwards, else search forwards." |
| @@ -4887,9 +4891,36 @@ Interactively, prompt for symbol." | |||
| 4887 | (defun python-hideshow-forward-sexp-function (_arg) | 4891 | (defun python-hideshow-forward-sexp-function (_arg) |
| 4888 | "Python specific `forward-sexp' function for `hs-minor-mode'. | 4892 | "Python specific `forward-sexp' function for `hs-minor-mode'. |
| 4889 | Argument ARG is ignored." | 4893 | Argument ARG is ignored." |
| 4890 | (python-nav-end-of-defun) | 4894 | (python-nav-end-of-block)) |
| 4891 | (unless (python-info-current-line-empty-p) | 4895 | |
| 4892 | (backward-char))) | 4896 | (defun python-hideshow-find-next-block (regexp maxp comments) |
| 4897 | "Python specific `hs-find-next-block' function for `hs-minor-mode'. | ||
| 4898 | Call `python-nav-forward-block' to find next block and check if | ||
| 4899 | block-start ends within MAXP. If COMMENTS is not nil, comments | ||
| 4900 | are also searched. REGEXP is passed to `looking-at' to set | ||
| 4901 | `match-data'." | ||
| 4902 | (let* ((next-block | ||
| 4903 | (save-excursion | ||
| 4904 | (or (and | ||
| 4905 | (python-info-looking-at-beginning-of-block) | ||
| 4906 | (re-search-forward (python-rx block-start) maxp t)) | ||
| 4907 | (and (python-nav-forward-block) | ||
| 4908 | (< (point) maxp) | ||
| 4909 | (re-search-forward (python-rx block-start) maxp t)) | ||
| 4910 | (1+ maxp)))) | ||
| 4911 | (next-comment | ||
| 4912 | (or (when comments | ||
| 4913 | (save-excursion | ||
| 4914 | (cl-loop while (re-search-forward "#" maxp t) | ||
| 4915 | if (python-syntax-context 'comment) | ||
| 4916 | return (point)))) | ||
| 4917 | (1+ maxp))) | ||
| 4918 | (next-block-or-comment (min next-block next-comment))) | ||
| 4919 | (when (<= next-block-or-comment maxp) | ||
| 4920 | (goto-char next-block-or-comment) | ||
| 4921 | (save-excursion | ||
| 4922 | (beginning-of-line) | ||
| 4923 | (looking-at regexp))))) | ||
| 4893 | 4924 | ||
| 4894 | 4925 | ||
| 4895 | ;;; Imenu | 4926 | ;;; Imenu |
| @@ -5386,6 +5417,19 @@ instead of the current physical line." | |||
| 5386 | (beginning-of-line 1) | 5417 | (beginning-of-line 1) |
| 5387 | (looking-at python-nav-beginning-of-defun-regexp)))) | 5418 | (looking-at python-nav-beginning-of-defun-regexp)))) |
| 5388 | 5419 | ||
| 5420 | (defun python-info-looking-at-beginning-of-block () | ||
| 5421 | "Check if point is at the beginning of block." | ||
| 5422 | (let* ((line-beg-pos (line-beginning-position)) | ||
| 5423 | (line-content-start (+ line-beg-pos (current-indentation))) | ||
| 5424 | (block-beg-pos (save-excursion | ||
| 5425 | (python-nav-beginning-of-block)))) | ||
| 5426 | (and block-beg-pos | ||
| 5427 | (= block-beg-pos line-content-start) | ||
| 5428 | (<= (point) line-content-start) | ||
| 5429 | (save-excursion | ||
| 5430 | (beginning-of-line) | ||
| 5431 | (looking-at python-nav-beginning-of-block-regexp))))) | ||
| 5432 | |||
| 5389 | (defun python-info-current-line-comment-p () | 5433 | (defun python-info-current-line-comment-p () |
| 5390 | "Return non-nil if current line is a comment line." | 5434 | "Return non-nil if current line is a comment line." |
| 5391 | (char-equal | 5435 | (char-equal |
| @@ -5835,14 +5879,17 @@ REPORT-FN is Flymake's callback function." | |||
| 5835 | 5879 | ||
| 5836 | (add-to-list | 5880 | (add-to-list |
| 5837 | 'hs-special-modes-alist | 5881 | 'hs-special-modes-alist |
| 5838 | '(python-mode | 5882 | `(python-mode |
| 5839 | "\\s-*\\_<\\(?:def\\|class\\)\\_>" | 5883 | ,python-nav-beginning-of-block-regexp |
| 5840 | ;; Use the empty string as end regexp so it doesn't default to | 5884 | ;; Use the empty string as end regexp so it doesn't default to |
| 5841 | ;; "\\s)". This way parens at end of defun are properly hidden. | 5885 | ;; "\\s)". This way parens at end of defun are properly hidden. |
| 5842 | "" | 5886 | "" |
| 5843 | "#" | 5887 | "#" |
| 5844 | python-hideshow-forward-sexp-function | 5888 | python-hideshow-forward-sexp-function |
| 5845 | nil)) | 5889 | nil |
| 5890 | python-nav-beginning-of-block | ||
| 5891 | python-hideshow-find-next-block | ||
| 5892 | python-info-looking-at-beginning-of-block)) | ||
| 5846 | 5893 | ||
| 5847 | (setq-local outline-regexp (python-rx (* space) block-start)) | 5894 | (setq-local outline-regexp (python-rx (* space) block-start)) |
| 5848 | (setq-local outline-heading-end-regexp ":[^\n]*\n") | 5895 | (setq-local outline-heading-end-regexp ":[^\n]*\n") |