branch: externals/csharp-mode commit 0ebd21ac7b8a2497402c3a56c563c3ae87aee695 Author: Theodor Thornhill <t...@thornhill.no> Commit: Theodor Thornhill <t...@thornhill.no>
Remove CC Mode and add tree-sitter-indent :O This mode is small now :D This is not on MELPA yet, so use with caution and install manually. https://codeberg.org/FelipeLema/tree-sitter-indent.el Also note that I opened: https://codeberg.org/FelipeLema/tree-sitter-indent.el/issues/1 --- csharp-mode.el | 547 ++++----------------------------------------------------- 1 file changed, 32 insertions(+), 515 deletions(-) diff --git a/csharp-mode.el b/csharp-mode.el index ff034ae..8a37801 100644 --- a/csharp-mode.el +++ b/csharp-mode.el @@ -25,17 +25,9 @@ ;;; Code: - -;; (when (version< emacs-version "25.1") -;; (require 'cl)) -;; (require 'cc-mode) -;; (require 'cc-langs) - -;; (eval-when-compile -;; (require 'cc-fonts)) - (require 'tree-sitter) (require 'tree-sitter-hl) +(require 'tree-sitter-indent) (require 'compile) @@ -43,340 +35,6 @@ "Major mode for editing C# code." :group 'prog-mode) -(eval-and-compile - (defconst csharp--regex-identifier - "[A-Za-z][A-Za-z0-9_]*" - "Regex describing an dentifier in C#.") - - (defconst csharp--regex-identifier-matcher - (concat "\\(" csharp--regex-identifier "\\)") - "Regex matching an identifier in C#.") - - (defconst csharp--regex-type-name - "[A-Z][A-Za-z0-9_]*" - "Regex describing a type identifier in C#.") - - (defconst csharp--regex-type-name-matcher - (concat "\\(" csharp--regex-type-name "\\)") - "Regex matching a type identifier in C#.") - - (defconst csharp--regex-using-or-namespace - (concat "^using" "\\|" "namespace" - "\\s *" - csharp--regex-type-name-matcher) - "Regex matching identifiers after a using or namespace - declaration.")) - -;; (eval-and-compile -;; (c-add-language 'csharp-mode 'java-mode)) - -;; (c-lang-defconst c-make-mode-syntax-table -;; csharp `(lambda () -;; (let ((table (make-syntax-table))) -;; (c-populate-syntax-table table) -;; (modify-syntax-entry ?@ "_" table) -;; table))) - -;; (c-lang-defconst c-identifier-syntax-modifications -;; csharp (append '((?@ . "w")) -;; (c-lang-const c-identifier-syntax-modifications))) - -;; (c-lang-defconst c-symbol-start -;; csharp (concat "[" c-alpha "_@]")) - -;; (c-lang-defconst c-opt-type-suffix-key -;; csharp (concat "\\(\\[" (c-lang-const c-simple-ws) "*\\]\\|\\?\\)")) - -;; (c-lang-defconst c-identifier-ops -;; csharp '((left-assoc "."))) - -;; (c-lang-defconst c-overloadable-operators -;; csharp '("+" "-" "*" "/" "%" "&" "|" "^" "<<" ">>" "==" -;; "!=" ">" "<" ">=" "<=")) - -;; (c-lang-defconst c-multiline-string-start-char -;; csharp ?@) - -;; (c-lang-defconst c-type-prefix-kwds -;; csharp '("class" "interface" "struct")) - -;; (c-lang-defconst c-class-decl-kwds -;; csharp '("class" "interface" "struct")) - -;; ;;; Keyword lists - -;; (c-lang-defconst c-primitive-type-kwds -;; csharp '("bool" "byte" "sbyte" "char" "decimal" "double" "float" "int" "uint" -;; "long" "ulong" "short" "ushort" "void" "object" "string" "var")) - -;; (c-lang-defconst c-other-decl-kwds -;; csharp nil) - -;; (c-lang-defconst c-type-list-kwds -;; csharp nil) - -;; (c-lang-defconst c-other-block-decl-kwds -;; csharp nil) - -;; (c-lang-defconst c-return-kwds -;; csharp '("return")) - -;; (c-lang-defconst c-typedef-kwds -;; csharp nil) - -;; (c-lang-defconst c-typeof-kwds -;; csharp '("typeof" "is" "as")) - -;; (c-lang-defconst c-type-modifier-prefix-kwds -;; csharp '("volatile")) - -;; (c-lang-defconst c-type-modifier-kwds -;; csharp '("readonly" "new")) - -;; (c-lang-defconst c-brace-list-decl-kwds -;; csharp '("enum" "new")) - -;; (c-lang-defconst c-recognize-post-brace-list-type-p -;; csharp t) - -;; (c-lang-defconst c-ref-list-kwds -;; csharp nil) - -;; (c-lang-defconst c-using-kwds -;; csharp '("using")) - -;; (c-lang-defconst c-equals-type-clause-kwds -;; csharp '("using")) - -;; (defun csharp-at-vsemi-p (&optional pos) -;; (if pos (goto-char pos)) -;; (save-excursion -;; (beginning-of-line) -;; (c-forward-syntactic-ws) -;; (looking-at "using\\s *("))) - -;; (c-lang-defconst c-at-vsemi-p-fn -;; csharp 'csharp-at-vsemi-p) - -;; (defun csharp-vsemi-status-unknown () t) - -;; (c-lang-defconst c-vsemi-status-unknown-p-fn -;; csharp 'csharp-vsemi-status-unknown-p) - - -;; (c-lang-defconst c-modifier-kwds -;; csharp '("abstract" "default" "final" "native" "private" "protected" -;; "public" "partial" "internal" "readonly" "static" "event" "transient" -;; "volatile" "sealed" "ref" "out" "virtual" "implicit" "explicit" -;; "fixed" "override" "params" "async" "await" "extern" "unsafe" -;; "get" "set" "this" "const" "delegate")) - -;; (c-lang-defconst c-other-kwds -;; csharp '("select" "from" "where" "join" "in" "on" "equals" "into" -;; "orderby" "ascending" "descending" "group" "when" -;; "let" "by" "namespace")) - -;; (c-lang-defconst c-colon-type-list-kwds -;; csharp '("class" "struct" "interface")) - -;; (c-lang-defconst c-block-stmt-1-kwds -;; csharp '("do" "else" "finally" "try")) - -;; (c-lang-defconst c-block-stmt-1-2-kwds -;; csharp '("try")) - -;; (c-lang-defconst c-block-stmt-2-kwds -;; csharp '("for" "if" "switch" "while" "catch" "foreach" "fixed" "checked" -;; "unchecked" "using" "lock")) - -;; (c-lang-defconst c-simple-stmt-kwds -;; csharp '("break" "continue" "goto" "throw" "return" "yield")) - -;; (c-lang-defconst c-constant-kwds -;; csharp '("true" "false" "null" "value")) - -;; (c-lang-defconst c-primary-expr-kwds -;; csharp '("this" "base" "operator")) - -;; (c-lang-defconst c-inexpr-class-kwds -;; csharp nil) - -;; (c-lang-defconst c-class-decl-kwds -;; csharp '("class" "struct" "interface")) - -;; (c-lang-defconst c-std-abbrev-keywords -;; csharp (append (c-lang-const c-std-abbrev-keywords) '("catch" "finally"))) - -;; (c-lang-defconst c-decl-prefix-re -;; csharp "\\([{}(;,<]+\\)") - -;; (c-lang-defconst c-recognize-typeless-decls -;; csharp t) - -;; (c-lang-defconst c-recognize-<>-arglists -;; csharp t) - -;; (c-lang-defconst c-opt-cpp-prefix -;; csharp "\\s *#\\s *") - -;; (c-lang-defconst c-opt-cpp-macro-define -;; csharp (if (c-lang-const c-opt-cpp-prefix) -;; "define")) - -;; (c-lang-defconst c-cpp-message-directives -;; csharp '("error" "warning" "region")) - -;; (c-lang-defconst c-cpp-expr-directives -;; csharp '("if" "elif")) - -;; (c-lang-defconst c-other-op-syntax-tokens -;; csharp (append '("#") -;; (c-lang-const c-other-op-syntax-tokens))) - -;; (c-lang-defconst c-line-comment-starter -;; csharp "//") - -;; (c-lang-defconst c-doc-comment-start-regexp -;; csharp "///") - -;; (c-add-style "csharp" -;; '("java" -;; (c-basic-offset . 4) -;; (c-comment-only-line-offset . (0 . 0)) -;; (c-offsets-alist . ((inline-open . 0) -;; (arglist-intro . +) -;; (arglist-close . 0) -;; (inexpr-class . 0) -;; (case-label . +) -;; (cpp-macro . c-lineup-dont-change) -;; (substatement-open . 0))))) - -;; (eval-and-compile -;; (unless (assoc 'csharp-mode c-default-style) -;; (setq c-default-style -;; (cons '(csharp-mode . "csharp") -;; c-default-style)))) - -;; (defun csharp--color-forwards (font-lock-face) -;; (let (id-beginning) -;; (goto-char (match-beginning 0)) -;; (forward-word) -;; (while (and (not (or (eq (char-after) ?\;) -;; (eq (char-after) ?\{))) -;; (progn -;; (forward-char) -;; (c-forward-syntactic-ws) -;; (setq id-beginning (point)) -;; (> (skip-chars-forward -;; (c-lang-const c-symbol-chars)) -;; 0)) -;; (not (get-text-property (point) 'face))) -;; (c-put-font-lock-face id-beginning (point) font-lock-face) -;; (c-forward-syntactic-ws)))) - -;; (c-lang-defconst c-basic-matchers-before -;; csharp `( -;; ;; Warning face on unclosed strings -;; ,@(if (version< emacs-version "27.0") -;; ;; Taken from 26.1 branch -;; `(,(c-make-font-lock-search-function -;; (concat ".\\(" c-string-limit-regexp "\\)") -;; '((c-font-lock-invalid-string)))) -;; `(("\\s|" 0 font-lock-warning-face t nil))) - -;; ;; Invalid single quotes -;; c-font-lock-invalid-single-quotes - -;; ;; Keyword constants -;; ,@(when (c-lang-const c-constant-kwds) -;; (let ((re (c-make-keywords-re nil (c-lang-const c-constant-kwds)))) -;; `((eval . (list ,(concat "\\<\\(" re "\\)\\>") -;; 1 c-constant-face-name))))) - -;; ;; Keywords except the primitive types. -;; ,`(,(concat "\\<" (c-lang-const c-regular-keywords-regexp)) -;; 1 font-lock-keyword-face) - -;; ;; Chained identifiers in using/namespace statements -;; ,`(,(c-make-font-lock-search-function -;; csharp--regex-using-or-namespace -;; `((csharp--color-forwards font-lock-variable-name-face) -;; nil -;; (goto-char (match-end 0))))) - - -;; ;; Negation character -;; (eval . (list "\\(!\\)[^=]" 1 c-negation-char-face-name)) - -;; ;; Types after 'new' -;; (eval . (list (concat "\\<new\\> *" csharp--regex-type-name-matcher) -;; 1 font-lock-type-face)) - -;; ;; Single identifier in attribute -;; (eval . (list (concat "\\[" csharp--regex-type-name-matcher "\\][^;]") -;; 1 font-lock-variable-name-face t)) - -;; ;; Function names -;; (eval . (list "\\([A-Za-z0-9_]+\\)\\(<[a-zA-Z0-9, ]+>\\)?(" -;; 1 font-lock-function-name-face)) - -;; ;; Nameof -;; (eval . (list (concat "\\(\\<nameof\\>\\) *(") -;; 1 font-lock-function-name-face)) - -;; (eval . (list (concat "\\<nameof\\> *( *" -;; csharp--regex-identifier-matcher -;; " *) *") -;; 1 font-lock-variable-name-face)) - -;; ;; Catch statements with type only -;; (eval . (list (concat "\\<catch\\> *( *" -;; csharp--regex-type-name-matcher -;; " *) *") -;; 1 font-lock-type-face)) -;; )) - -;; (c-lang-defconst c-basic-matchers-after -;; csharp (append -;; ;; Merge with cc-mode defaults - enables us to add more later -;; (c-lang-const c-basic-matchers-after))) - -;; (defcustom csharp-codedoc-tag-face 'c-doc-markup-face-name -;; "Face to be used on the codedoc docstring tags. - -;; Should be one of the font lock faces, such as -;; `font-lock-variable-name-face' and friends. - -;; Needs to be set before `csharp-mode' is loaded, because of -;; compilation and evaluation time conflicts." -;; :type 'symbol -;; :group 'csharp) - -;; (defcustom csharp-font-lock-extra-types -;; (list csharp--regex-type-name) -;; (c-make-font-lock-extra-types-blurb "C#" "csharp-mode" (concat)) -;; :type 'c-extra-types-widget -;; :group 'c) - -;; (defconst csharp-font-lock-keywords-1 (c-lang-const c-matchers-1 csharp) -;; "Minimal font locking for C# mode.") - -;; (defconst csharp-font-lock-keywords-2 (c-lang-const c-matchers-2 csharp) -;; "Fast normal font locking for C# mode.") - -;; (defconst csharp-font-lock-keywords-3 (c-lang-const c-matchers-3 csharp) -;; "Accurate normal font locking for C# mode.") - -;; (defvar csharp-font-lock-keywords csharp-font-lock-keywords-3 -;; "Default expressions to highlight in C# mode.") - -;; (defun csharp-font-lock-keywords-2 () -;; (c-compose-keywords-list csharp-font-lock-keywords-2)) -;; (defun csharp-font-lock-keywords-3 () -;; (c-compose-keywords-list csharp-font-lock-keywords-3)) -;; (defun csharp-font-lock-keywords () -;; (c-compose-keywords-list csharp-font-lock-keywords)) - ;;; Compilation support ;; When invoked by MSBuild, csc’s errors look like this: ;; subfolder\file.cs(6,18): error CS1006: Name of constructor must @@ -490,170 +148,12 @@ (add-to-list 'compilation-error-regexp-alist-alist regexp) (add-to-list 'compilation-error-regexp-alist (car regexp))))) -;;; Doc comments - -;; (defconst codedoc-font-lock-doc-comments -;; ;; Most of this is taken from the javadoc example, however, we don't use the -;; ;; '@foo' syntax, so I removed that. Supports the XML tags only -;; `((,(concat "</?\\sw" ; XML tags. -;; "\\(" -;; (concat "\\sw\\|\\s \\|[=\n\r*.:]\\|" -;; "\"[^\"]*\"\\|'[^']*'") -;; "\\)*/?>") -;; 0 ,csharp-codedoc-tag-face prepend nil) -;; ;; ("\\([a-zA-Z0-9_]+\\)=" 0 font-lock-variable-name-face prepend nil) -;; ;; ("\".*\"" 0 font-lock-string-face prepend nil) -;; ("&\\(\\sw\\|[.:]\\)+;" ; XML entities. -;; 0 ,csharp-codedoc-tag-face prepend nil))) - -;; (defconst codedoc-font-lock-keywords -;; `((,(lambda (limit) -;; (c-font-lock-doc-comments "///" limit -;; codedoc-font-lock-doc-comments))))) - -;;; End of doc comments - -;;; Adding syntax constructs - -;; (advice-add 'c-looking-at-inexpr-block -;; :around 'csharp-looking-at-inexpr-block) - -;; (defun csharp-looking-at-inexpr-block (orig-fun &rest args) -;; (let ((res (csharp-at-lambda-header))) -;; (if res -;; res -;; (apply orig-fun args)))) - -;; (defun csharp-at-lambda-header () -;; (save-excursion -;; (c-backward-syntactic-ws) -;; (unless (bobp) -;; (backward-char) -;; (c-safe (goto-char (scan-sexps (point) -1))) -;; (when (or (looking-at "([[:alnum:][:space:]_,]*)[ \t\n]*=>[ \t\n]*{") -;; (looking-at "[[:alnum:]_]+[ \t\n]*=>[ \t\n]*{")) -;; ;; If we are at a C# lambda header -;; (cons 'inexpr (point)))))) - -;; (advice-add 'c-guess-basic-syntax -;; :around 'csharp-guess-basic-syntax) - -;; (defun csharp-guess-basic-syntax (orig-fun &rest args) -;; (cond -;; (;; Attributes -;; (save-excursion -;; (goto-char (c-point 'iopl)) -;; (and -;; (eq (char-after) ?\[) -;; (save-excursion -;; (c-go-list-forward) -;; (and (eq (char-before) ?\]) -;; (not (eq (char-after) ?\;)))))) -;; `((annotation-top-cont ,(c-point 'iopl)))) - -;; ((and -;; ;; Heuristics to find object initializers -;; (save-excursion -;; ;; Next non-whitespace character should be '{' -;; (goto-char (c-point 'boi)) -;; (eq (char-after) ?{)) -;; (save-excursion -;; ;; 'new' should be part of the line -;; (goto-char (c-point 'iopl)) -;; (looking-at ".*\\s *new\\s *.*")) -;; ;; Line should not already be terminated -;; (save-excursion -;; (goto-char (c-point 'eopl)) -;; (or (not (eq (char-before) ?\;)) -;; (not (eq (char-before) ?\{))))) -;; (if (save-excursion -;; ;; if we have a hanging brace on line before -;; (goto-char (c-point 'eopl)) -;; (eq (char-before) ?\{)) -;; `((brace-list-intro ,(c-point 'iopl))) -;; `((block-open) (statement ,(c-point 'iopl))))) -;; (t -;; (apply orig-fun args)))) - -;; ;;; End of new syntax constructs - - - -;; ;;; Fix for strings on version 27.1 - -;; (when (version= emacs-version "27.1") -;; ;; See: -;; ;; https://github.com/josteink/csharp-mode/issues/175 -;; ;; https://github.com/josteink/csharp-mode/issues/151 -;; ;; for the full story. -;; (defun c-pps-to-string-delim (end) -;; (let* ((start (point)) -;; (no-st-s `(0 nil nil ?\" nil nil 0 nil ,start nil nil)) -;; (st-s `(0 nil nil t nil nil 0 nil ,start nil nil)) -;; no-st-pos st-pos -;; ) -;; (parse-partial-sexp start end nil nil no-st-s 'syntax-table) -;; (setq no-st-pos (point)) -;; (goto-char start) -;; (while (progn -;; (parse-partial-sexp (point) end nil nil st-s 'syntax-table) -;; (unless (bobp) -;; (c-clear-syn-tab (1- (point)))) -;; (setq st-pos (point)) -;; (and (< (point) end) -;; (not (eq (char-before) ?\"))))) -;; (goto-char (min no-st-pos st-pos)) -;; nil)) - -;; (defun c-multiline-string-check-final-quote () -;; (let (pos-ll pos-lt) -;; (save-excursion -;; (goto-char (point-max)) -;; (skip-chars-backward "^\"") -;; (while -;; (and -;; (not (bobp)) -;; (cond -;; ((progn -;; (setq pos-ll (c-literal-limits) -;; pos-lt (c-literal-type pos-ll)) -;; (memq pos-lt '(c c++))) -;; ;; In a comment. -;; (goto-char (car pos-ll))) -;; ((save-excursion -;; (backward-char) ; over " -;; (c-is-escaped (point))) -;; ;; At an escaped string. -;; (backward-char) -;; t) -;; (t -;; ;; At a significant " -;; (c-clear-syn-tab (1- (point))) -;; (setq pos-ll (c-literal-limits) -;; pos-lt (c-literal-type pos-ll)) -;; nil))) -;; (skip-chars-backward "^\"")) -;; (cond -;; ((bobp)) -;; ((eq pos-lt 'string) -;; (c-put-syn-tab (1- (point)) '(15))) -;; (t nil)))))) - -;; ;;; End of fix for strings on version 27.1 - - - -;; (defvar csharp-mode-syntax-table -;; (funcall (c-lang-const c-make-mode-syntax-table csharp)) -;; "Syntax table used in csharp-mode buffers.") - -;; (defvar csharp-mode-map -;; (let ((map (c-make-inherited-keymap))) -;; map) -;; "Keymap used in csharp-mode buffers.") - -;; (easy-menu-define csharp-mode-menu csharp-mode-map "C# Mode Commands" -;; (cons "C#" (c-lang-const c-mode-menu csharp))) +(defcustom csharp-indent-offset 4 + "Indent offset for csharp-mode") + +(defcustom tree-sitter-indent-csharp-scopes nil + "Scopes for indenting in C#." + :type 'sexp) ;;;###autoload (add-to-list 'auto-mode-alist '("\\.cs\\'" . csharp-mode)) @@ -671,13 +171,30 @@ Key bindings: \\{csharp-mode-map}" - ;; :after-hook (c-update-modeline) - ;; (c-initialize-cc-mode t) - ;; (c-init-language-vars csharp-mode) - ;; (c-common-init 'csharp-mode) - ;; (easy-menu-add csharp-mode-menu) - ;; (setq-local c-doc-comment-style '((csharp-mode . codedoc))) - ;; (c-run-mode-hooks 'c-mode-common-hook 'csharp-mode-hook) + (setq tree-sitter-indent-csharp-scopes + '((indent-all . ;; these nodes are always indented + ()) + (indent-rest . ;; if parent node is one of these and node is not first → indent + ()) + (indent-body . ;; if parent node is one of these and current node is in middle → indent + (declaration_list)) + + (paren-indent . ;; if parent node is one of these → indent to paren opener + ()) + (align-char-to . ;; chaining char → node types we move parentwise to find the first chaining char + ()) + (aligned-siblings . ;; siblings (nodes with same parent) should be aligned to the first child + ()) + + (multi-line-text . ;; if node is one of these, then don't modify the indent + ;; this is basically a peaceful way out by saying "this looks like something + ;; that cannot be indented using AST, so best I leave it as-is" + ()) + (outdent . ;; these nodes always outdent (1 shift in opposite direction) + ()) + ) + ) + (setq-local indent-line-function #'tree-sitter-debug-indent-line) (setq tree-sitter-hl-default-patterns [(comment) @comment (modifier) @keyword @@ -687,7 +204,7 @@ Key bindings: "default" "typeof" "try" "catch" "finally" "foreach" "in" ] @keyword - ;; Literals + ;; Literals [(real_literal) (integer_literal)] @number (null_literal) @constant (boolean_literal) @constant