From b3603b84bd9c0e2f0fbd6cc49d4d086e7b08735a Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Fri, 14 Apr 2023 12:52:46 -0700 Subject: Partial support for DEFUN in c-ts-mode (bug#62825) The DEFUN is hard to incorporate because it's made of two nodes rather than one, and most tree-sitter functionalities assume a defun is one node. I fixed the indent-defun and add-log functionality, but beginning/end-of-defun and imenu still don't recognize DEFUN. * lisp/progmodes/c-ts-mode.el (c-ts-mode-emacs-devel): New variable. (c-ts-mode--defun-name): Support DEFUN. (c-ts-mode--defun-valid-p): Support DEFUN. (c-ts-mode--emacs-defun-p) (c-ts-mode--emacs-defun-at-point): New functions. (c-ts-mode-indent-defun): Use c-ts-mode--emacs-defun-at-point. (c-ts-mode--emacs-current-defun-name): New function. (c-ts-mode, c++-ts-mode): Optionally setup custom defun-name function. --- lisp/progmodes/c-ts-mode.el | 126 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 101 insertions(+), 25 deletions(-) diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 2d54577cb09..f3c1dde10c0 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -192,6 +192,10 @@ To set the default indent style globally, use (c-ts-mode--get-indent-style (if (derived-mode-p 'c-ts-mode) 'c 'cpp)))))) +(defvar c-ts-mode-emacs-devel nil + "If the value is t, enable Emacs source-specific features. +This needs to be set before enabling `c-ts-mode'.") + ;;; Syntax table (defvar c-ts-mode--syntax-table @@ -802,7 +806,14 @@ Return nil if NODE is not a defun node or doesn't have a name." ((or "struct_specifier" "enum_specifier" "union_specifier" "class_specifier" "namespace_definition") - (treesit-node-child-by-field-name node "name"))) + (treesit-node-child-by-field-name node "name")) + ;; DEFUNs in Emacs source. + ("expression_statement" + (let* ((call-exp-1 (treesit-node-child node 0)) + (call-exp-2 (treesit-node-child call-exp-1 0)) + (arg-list (treesit-node-child call-exp-2 1)) + (name (treesit-node-child arg-list 1 t))) + name))) t)) ;;; Defun navigation @@ -810,28 +821,29 @@ Return nil if NODE is not a defun node or doesn't have a name." (defun c-ts-mode--defun-valid-p (node) "Return non-nil if NODE is a valid defun node. Ie, NODE is not nested." - (not (or (and (member (treesit-node-type node) - '("struct_specifier" - "enum_specifier" - "union_specifier" - "declaration")) - ;; If NODE's type is one of the above, make sure it is - ;; top-level. - (treesit-node-top-level - node (rx (or "function_definition" - "type_definition" - "struct_specifier" + (or (c-ts-mode--emacs-defun-p node) + (not (or (and (member (treesit-node-type node) + '("struct_specifier" "enum_specifier" "union_specifier" - "declaration")))) + "declaration")) + ;; If NODE's type is one of the above, make sure it is + ;; top-level. + (treesit-node-top-level + node (rx (or "function_definition" + "type_definition" + "struct_specifier" + "enum_specifier" + "union_specifier" + "declaration")))) - (and (equal (treesit-node-type node) "declaration") - ;; If NODE is a declaration, make sure it is not a - ;; function declaration. - (equal (treesit-node-type - (treesit-node-child-by-field-name - node "declarator")) - "function_declarator"))))) + (and (equal (treesit-node-type node) "declaration") + ;; If NODE is a declaration, make sure it is not a + ;; function declaration. + (equal (treesit-node-type + (treesit-node-child-by-field-name + node "declarator")) + "function_declarator")))))) (defun c-ts-mode--defun-for-class-in-imenu-p (node) "Check if NODE is a valid entry for the Class subindex. @@ -871,17 +883,73 @@ the semicolon. This function skips the semicolon." (setq parent (treesit-node-parent smallest-node))))) (list node parent bol))) +(defun c-ts-mode--emacs-defun-p (node) + "Return non-nil if NODE is a DEFUN in Emacs source files." + (and (equal (treesit-node-type node) "expression_statement") + (equal (treesit-node-text + (treesit-node-child-by-field-name + (treesit-node-child + (treesit-node-child node 0) 0) + "function") + t) + "DEFUN"))) + +(defun c-ts-mode--emacs-defun-at-point (&optional range) + "Return the current defun node. + +This function recognizes DEFUNs in Emacs source files. + +Note that for the case of a DEFUN, it is made of two separate +nodes, one for the declaration and one for the body, this +function returns the declaration node. + +If RANGE is non-nil, return (BEG . END) where BEG end END +encloses the whole defun. This solves the problem of only +returning the declaration part for DEFUN." + (or (when-let ((node (treesit-defun-at-point))) + (if range + (cons (treesit-node-start node) + (treesit-node-end node)) + node)) + (and c-ts-mode-emacs-devel + (let ((candidate-1 ; For when point is in the DEFUN statement. + (treesit-node-prev-sibling + (treesit-node-top-level + (treesit-node-at (point)) + "compound_statement"))) + (candidate-2 ; For when point is in the body. + (treesit-node-top-level + (treesit-node-at (point)) + "expression_statement"))) + (when-let + ((node (or (and (c-ts-mode--emacs-defun-p candidate-1) + candidate-1) + (and (c-ts-mode--emacs-defun-p candidate-2) + candidate-2)))) + (if range + (cons (treesit-node-start node) + (treesit-node-end + (treesit-node-next-sibling node))) + node)))))) + (defun c-ts-mode-indent-defun () "Indent the current top-level declaration syntactically. `treesit-defun-type-regexp' defines what constructs to indent." (interactive "*") (when-let ((orig-point (point-marker)) - (node (treesit-defun-at-point))) - (indent-region (treesit-node-start node) - (treesit-node-end node)) + (range (c-ts-mode--emacs-defun-at-point t))) + (indent-region (car range) (cdr range)) (goto-char orig-point))) +(defun c-ts-mode--emacs-current-defun-name () + "Return the name of the current defun. +This is used for `add-log-current-defun-function'. This +recognizes DEFUN in Emacs sources, in addition to normal function +definitions." + (or (treesit-add-log-current-defun) + (c-ts-mode--defun-name (c-ts-mode--emacs-defun-at-point)))) + ;;; Modes (defvar-keymap c-ts-base-mode-map @@ -996,7 +1064,11 @@ in your configuration." (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'c)) ;; Navigation. (setq-local treesit-defun-tactic 'top-level) - (treesit-major-mode-setup))) + (treesit-major-mode-setup) + + (when c-ts-mode-emacs-devel + (setq-local add-log-current-defun-function + #'c-ts-mode--emacs-current-defun-name)))) ;;;###autoload (define-derived-mode c++-ts-mode c-ts-base-mode "C++" @@ -1031,7 +1103,11 @@ recommended to enable `electric-pair-mode' with this mode." (c-ts-mode--get-indent-style 'cpp)) ;; Font-lock. (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'cpp)) - (treesit-major-mode-setup))) + (treesit-major-mode-setup) + + (when c-ts-mode-emacs-devel + (setq-local add-log-current-defun-function + #'c-ts-mode--emacs-current-defun-name)))) (easy-menu-define c-ts-mode-menu (list c-ts-mode-map c++-ts-mode-map) "Menu for `c-ts-mode' and `c++-ts-mode'." -- cgit v1.2.3 From adf9c956c28106f83f06bd150d01bced9b19c1c1 Mon Sep 17 00:00:00 2001 From: Jostein Kjønigsen Date: Fri, 14 Apr 2023 23:11:02 +0200 Subject: Add to Eglot support for additional language-servers. * lisp/progmodes/eglot.el (eglot-server-programs): Add 'vscode-markdown-language-server' for Markdown and 'dot-language-server' for GraphViz. (Bug#62844) --- lisp/progmodes/eglot.el | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index a0581126b28..4943b44107a 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -249,7 +249,11 @@ chosen (interactively or automatically)." ("csharp-ls")))) (purescript-mode . ("purescript-language-server" "--stdio")) ((perl-mode cperl-mode) . ("perl" "-MPerl::LanguageServer" "-e" "Perl::LanguageServer::run")) - (markdown-mode . ("marksman" "server"))) + (markdown-mode + . ,(eglot-alternatives + '(("marksman" "server") + ("vscode-markdown-language-server" "--stdio")))) + (graphviz-dot-mode . ("dot-language-server" "--stdio"))) "How the command `eglot' guesses the server to start. An association list of (MAJOR-MODE . CONTACT) pairs. MAJOR-MODE identifies the buffers that are to be managed by a specific -- cgit v1.2.3 From 3f71a2a0cf6cbbb6b3eb9f3f3a236daeb3420216 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 15 Apr 2023 13:12:20 +0300 Subject: ; * lisp/progmodes/c-ts-mode.el (treesit-node-next-sibling): Declare. --- lisp/progmodes/c-ts-mode.el | 1 + 1 file changed, 1 insertion(+) diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index f3c1dde10c0..c2d68086f33 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -79,6 +79,7 @@ (declare-function treesit-node-type "treesit.c") (declare-function treesit-node-prev-sibling "treesit.c") (declare-function treesit-node-first-child-for-pos "treesit.c") +(declare-function treesit-node-next-sibling "treesit.c") ;;; Custom variables -- cgit v1.2.3 From d9e96c029bb42ff96f4dd7f51a3e2b93ba71bfc8 Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Sat, 15 Apr 2023 11:00:38 +0000 Subject: * CONTRIBUTE: Fix a typo --- CONTRIBUTE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTE b/CONTRIBUTE index 82e5b0a1018..a9e2acfa92a 100644 --- a/CONTRIBUTE +++ b/CONTRIBUTE @@ -321,7 +321,7 @@ them right the first time, so here are guidelines for formatting them: ** Committing your changes. When you commit changes, Git invokes several scripts that test the -commit for validity, and may abort the commit of some of the tests +commit for validity, and may abort the commit if some of the tests fail. These scripts live in the '.git/hooks/' subdirectory of the top-level directory of the repository, and they perform the following tests: -- cgit v1.2.3 From b7023da6627f911c087961d9d476b3eafabb7ae7 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Sat, 15 Apr 2023 12:35:24 +0200 Subject: Make image-map bindings available on image links * lisp/net/shr.el (shr-map): Move shr-browse-image to "M-i". * lisp/net/eww.el (eww-image-link-keymap): Use shr-image-map. --- lisp/net/eww.el | 2 +- lisp/net/shr.el | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lisp/net/eww.el b/lisp/net/eww.el index eac47e592b2..d2b4575f963 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el @@ -326,7 +326,7 @@ parameter, and should return the (possibly) transformed URL." "" #'eww-follow-link) (defvar-keymap eww-image-link-keymap - :parent shr-map + :parent shr-image-map "RET" #'eww-follow-link) (defun eww-suggested-uris nil diff --git a/lisp/net/shr.el b/lisp/net/shr.el index 9c2ae98d77e..4e44dfbef03 100644 --- a/lisp/net/shr.el +++ b/lisp/net/shr.el @@ -276,7 +276,7 @@ and other things: (defvar-keymap shr-map "a" #'shr-show-alt-text - "i" #'shr-browse-image + "M-i" #'shr-browse-image "z" #'shr-zoom-image "TAB" #'shr-next-link "C-M-i" #'shr-previous-link -- cgit v1.2.3