>From e67e26f6d4dc39436b169b4fc026376d9f74b6b9 Mon Sep 17 00:00:00 2001 From: Theodor Thornhill Date: Mon, 12 Dec 2022 15:28:05 +0100 Subject: [PATCH] WIP forward-* implementation --- lisp/progmodes/java-ts-mode.el | 10 +++++ lisp/textmodes/paragraphs.el | 73 +++++++++++++++++++--------------- lisp/treesit.el | 50 ++++++++++++++++++++++- 3 files changed, 100 insertions(+), 33 deletions(-) diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el index d5f4f55fe0..e76380ec2a 100644 --- a/lisp/progmodes/java-ts-mode.el +++ b/lisp/progmodes/java-ts-mode.el @@ -336,6 +336,16 @@ java-ts-mode "package_declaration" "module_declaration"))) + (setq-local treesit-sentence-type-regexp + (regexp-opt '("declaration" + "statement"))) + + (setq-local treesit-sexp-type-regexp + (regexp-opt '("declaration" + "statement" + "formal_parameter" + "string_literal"))) + ;; Font-lock. (setq-local treesit-font-lock-settings java-ts-mode--font-lock-settings) (setq-local treesit-font-lock-feature-list diff --git a/lisp/textmodes/paragraphs.el b/lisp/textmodes/paragraphs.el index c500dc014f..b53fe66eee 100644 --- a/lisp/textmodes/paragraphs.el +++ b/lisp/textmodes/paragraphs.el @@ -441,6 +441,8 @@ end-of-paragraph-text (if (< (point) (point-max)) (end-of-paragraph-text)))))) +(defvar-local forward-sentence-function nil) + (defun forward-sentence (&optional arg) "Move forward to next end of sentence. With argument, repeat. When ARG is negative, move backward repeatedly to start of sentence. @@ -449,36 +451,40 @@ forward-sentence sentences. Also, every paragraph boundary terminates sentences as well." (interactive "^p") (or arg (setq arg 1)) - (let ((opoint (point)) - (sentence-end (sentence-end))) - (while (< arg 0) - (let ((pos (point)) - par-beg par-text-beg) - (save-excursion - (start-of-paragraph-text) - ;; Start of real text in the paragraph. - ;; We move back to here if we don't see a sentence-end. - (setq par-text-beg (point)) - ;; Start of the first line of the paragraph. - ;; We use this as the search limit - ;; to allow sentence-end to match if it is anchored at - ;; BOL and the paragraph starts indented. - (beginning-of-line) - (setq par-beg (point))) - (if (and (re-search-backward sentence-end par-beg t) - (or (< (match-end 0) pos) - (re-search-backward sentence-end par-beg t))) - (goto-char (match-end 0)) - (goto-char par-text-beg))) - (setq arg (1+ arg))) - (while (> arg 0) - (let ((par-end (save-excursion (end-of-paragraph-text) (point)))) - (if (re-search-forward sentence-end par-end t) - (skip-chars-backward " \t\n") - (goto-char par-end))) - (setq arg (1- arg))) - (let ((npoint (constrain-to-field nil opoint t))) - (not (= npoint opoint))))) + (cond + (forward-sentence-function + (funcall forward-sentence-function arg)) + (t + (let ((opoint (point)) + (sentence-end (sentence-end))) + (while (< arg 0) + (let ((pos (point)) + par-beg par-text-beg) + (save-excursion + (start-of-paragraph-text) + ;; Start of real text in the paragraph. + ;; We move back to here if we don't see a sentence-end. + (setq par-text-beg (point)) + ;; Start of the first line of the paragraph. + ;; We use this as the search limit + ;; to allow sentence-end to match if it is anchored at + ;; BOL and the paragraph starts indented. + (beginning-of-line) + (setq par-beg (point))) + (if (and (re-search-backward sentence-end par-beg t) + (or (< (match-end 0) pos) + (re-search-backward sentence-end par-beg t))) + (goto-char (match-end 0)) + (goto-char par-text-beg))) + (setq arg (1+ arg))) + (while (> arg 0) + (let ((par-end (save-excursion (end-of-paragraph-text) (point)))) + (if (re-search-forward sentence-end par-end t) + (skip-chars-backward " \t\n") + (goto-char par-end))) + (setq arg (1- arg))) + (let ((npoint (constrain-to-field nil opoint t))) + (not (= npoint opoint))))))) (defun count-sentences (start end) "Count sentences in current buffer from START to END." @@ -532,14 +538,17 @@ repunctuate-sentences (remove-function isearch-filter-predicate repunctuate-sentences-filter))))) - (defun backward-sentence (&optional arg) "Move backward to start of sentence. With ARG, do it ARG times. See `forward-sentence' for more information." (interactive "^p") (or arg (setq arg 1)) - (forward-sentence (- arg))) + (cond + (forward-sentence-function + (funcall forward-sentence-function (- arg))) + (t + (forward-sentence (- arg))))) (defun kill-sentence (&optional arg) "Kill from point to end of sentence. diff --git a/lisp/treesit.el b/lisp/treesit.el index 133564f6c8..4a1c10211e 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -1603,6 +1603,50 @@ treesit--defun-maybe-top-level node) finally return node)))) +(defvar-local treesit-sexp-type-regexp "\\`field_declaration\\'" + "A regexp that matches the node type of sexp nodes.") + +(defun treesit-forward-sexp (&optional arg) + "Tree-sitter `beginning-of-defun' function. +ARG is the same as in `beginning-of-defun'." + (let ((arg (or arg 1)) + (node (treesit-node-at (point)))) + (while (and (> arg 0) + (setq node (treesit-search-forward-goto + node + treesit-sexp-type-regexp))) + (setq arg (1- arg)) + (goto-char (treesit-node-end node))) + (while (and (< arg 0) + (setq node (treesit-search-forward-goto + node + treesit-sexp-type-regexp t t))) + (setq arg (1+ arg)) + (goto-char (treesit-node-start node))) + t)) + +(defvar-local treesit-sentence-type-regexp "\\`field_declaration\\'" + "A regexp that matches the node type of textual nodes.") + +(defun treesit-forward-sentence (&optional arg) + "Tree-sitter `beginning-of-defun' function. +ARG is the same as in `beginning-of-defun'." + (let ((arg (or arg 1)) + (node (treesit-node-at (point)))) + (while (and (> arg 0) + (setq node (treesit-search-forward-goto + node + treesit-sentence-type-regexp))) + (setq arg (1- arg)) + (goto-char (treesit-node-end node))) + (while (and (< arg 0) + (setq node (treesit-search-forward-goto + node + treesit-sentence-type-regexp t t))) + (setq arg (1+ arg)) + (goto-char (treesit-node-start node))) + t)) + (defun treesit-beginning-of-defun (&optional arg) "Tree-sitter `beginning-of-defun' function. ARG is the same as in `beginning-of-defun'." @@ -1730,7 +1774,11 @@ treesit-major-mode-setup ;; Navigation. (when treesit-defun-type-regexp (setq-local beginning-of-defun-function #'treesit-beginning-of-defun) - (setq-local end-of-defun-function #'treesit-end-of-defun))) + (setq-local end-of-defun-function #'treesit-end-of-defun)) + (when treesit-sentence-type-regexp + (setq-local forward-sentence-function #'treesit-forward-sentence)) + (when treesit-sexp-type-regexp + (setq-local forward-sexp-function #'treesit-forward-sexp))) ;;; Debugging -- 2.34.1