branch: externals/matlab-mode commit f0b14e5e84ab39e3903ae52e75e29bdefa1093e4 Author: John Ciolfi <john.ciolfi...@gmail.com> Commit: John Ciolfi <john.ciolfi...@gmail.com>
matlab-ts-mode: update next line matcher to handle error context only This avoid incorrect handling when code parses correctly. For example function a = foo a = 1; end ^ <== RET on prior line after 'end' should go here. --- matlab-ts-mode.el | 123 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 74 insertions(+), 49 deletions(-) diff --git a/matlab-ts-mode.el b/matlab-ts-mode.el index 505afe538a..1fa9e1b9a6 100644 --- a/matlab-ts-mode.el +++ b/matlab-ts-mode.el @@ -1235,8 +1235,8 @@ incomplete statements where NODE is nil and PARENT is line_continuation." (defvar matlab-ts-mode--i-next-line-pair) -(defun matlab-ts-mode--i-next-line-matcher (node parent _bol &rest _) - "Matcher for indent on a newline being inserted. +(cl-defun matlab-ts-mode--i-next-line-matcher (node parent _bol &rest _) + "Matcher for indent on a newline being inserted when in presence of errors. If so, set `matlab-ts-mode--i-next-line-pair'. NODE may or may not be nil. PARENT will be a newline, so Example: in this case NODE will be nil and PARENT is a newline. Example: @@ -1257,54 +1257,79 @@ Prev-siblings: (string= (treesit-node-type node) "ERROR")) (string= (treesit-node-type parent) "\n")) - (let* ((node-to-examine (if node node parent)) - (anchors-rx (rx (seq bos (or "function_definition" - "classdef" - "properties" - "property" - "methods" - "[" - "{") + (let ((anchors-rx (rx (seq bos (or "function_definition" + "classdef" + "properties" + "property" + "methods" + "[" + "{") eos))) - (anchor-node (or - ;; Look to previous siblings to see if they match anchors-rx - (let ((prev-sibling (treesit-node-prev-sibling node-to-examine))) - (while (and prev-sibling - (not (string-match-p anchors-rx - (treesit-node-type prev-sibling)))) - (setq prev-sibling (treesit-node-prev-sibling prev-sibling))) - prev-sibling) - ;; Look to ancestors siblings to see if they match anchors-rx, except - ;; when node is defined (an error node), in which case we can't look - ;; at ancestors. - (let* ((ancestor (when (not node) - (treesit-node-parent parent))) - (ancestor-type (when ancestor (treesit-node-type ancestor)))) - (while (and ancestor - (not (string-match-p anchors-rx ancestor-type))) - (setq ancestor (if (string= ancestor-type "ERROR") - nil - (treesit-node-parent ancestor)))) - ancestor)))) - (when anchor-node - (let ((indent-level (pcase (treesit-node-type anchor-node) - ("property" 0) - ((rx (seq bos (or "[" "{" eos))) matlab-ts-mode--array-indent-level) - ("function_definition" matlab-ts-mode--function-indent-level) - (_ matlab-ts-mode--indent-level)))) - (setq matlab-ts-mode--i-next-line-pair - (cons (treesit-node-start anchor-node) indent-level)) - - ;; TODO Rough sketch of electric-ends - ;; We need to look at the parse tree to see if we should insert it. - ;; Also, we should verify this doesn't happen with indent-region, only on RET. - ;; (when matlab-ts-mode-electric-ends - ;; (save-excursion - ;; (let ((insert-column (save-excursion - ;; (goto-char (treesit-node-start anchor-node)) - ;; (current-column)))) - ;; (insert "\n" (make-string insert-column ?\ ) "end\n"))) - t))))) + (node-to-check (or node parent)) + in-error ;; is node, parent, or one of it's ancestors an ERROR? + prev-sibling-has-error ;; is a previous sibliling an ERROR? + prev-sibling-to-check + ancestor-to-check) + + ;; ancestor-to-check + (let ((ancestor node-to-check)) + (while (and ancestor (not in-error)) + (let ((ancestor-type (treesit-node-type ancestor))) + (cond + + ((string= ancestor-type "ERROR") + (setq in-error t)) + + ((and (not ancestor-to-check) + (string-match-p anchors-rx ancestor-type)) + (setq ancestor-to-check ancestor))) + + (setq ancestor (if in-error + nil + (treesit-node-parent ancestor)))))) + + ;; prev-sibling-to-check + + (let ((prev-sibling (treesit-node-prev-sibling node-to-check))) + (while (and prev-sibling (not prev-sibling-has-error)) + (let ((prev-sibling-type (treesit-node-type prev-sibling))) + (cond + ((string= prev-sibling-type "ERROR") + (setq prev-sibling-has-error t)) + + ((and (not prev-sibling-to-check) + (string-match-p anchors-rx prev-sibling-type)) + (setq prev-sibling-to-check prev-sibling))) + + (setq prev-sibling (if prev-sibling-has-error + nil + (treesit-node-prev-sibling prev-sibling)))))) + + (when (and (not in-error) + (not prev-sibling-has-error)) + (cl-return-from matlab-ts-mode--i-next-line-matcher nil)) + + (let ((anchor-node (or ancestor-to-check + prev-sibling-to-check))) + (when anchor-node + (let ((indent-level (pcase (treesit-node-type anchor-node) + ("property" 0) + ((rx (seq bos (or "[" "{" eos))) matlab-ts-mode--array-indent-level) + ("function_definition" matlab-ts-mode--function-indent-level) + (_ matlab-ts-mode--indent-level)))) + (setq matlab-ts-mode--i-next-line-pair + (cons (treesit-node-start anchor-node) indent-level)) + + ;; TODO Rough sketch of electric-ends + ;; We need to look at the parse tree to see if we should insert it. + ;; Also, we should verify this doesn't happen with indent-region, only on RET. + ;; (when matlab-ts-mode-electric-ends + ;; (save-excursion + ;; (let ((insert-column (save-excursion + ;; (goto-char (treesit-node-start anchor-node)) + ;; (current-column)))) + ;; (insert "\n" (make-string insert-column ?\ ) "end\n"))) + t)))))) (defun matlab-ts-mode--i-next-line-anchor (&rest _) "Return the anchor computed by `matlab-ts-mode--i-next-line-matcher'."