commit d01d150f369b7b45843bbefc73e90d2be8a79b3a Author: lixulun Date: Thu May 21 11:17:30 2026 +0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..24a1b63 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +# emacs +*~ +\#*\# +.#* + +/elpa +/eshell +/tree-sitter \ No newline at end of file diff --git a/custom-file.el b/custom-file.el new file mode 100644 index 0000000..98c6e14 --- /dev/null +++ b/custom-file.el @@ -0,0 +1,19 @@ +(custom-set-variables + ;; custom-set-variables was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + '(custom-safe-themes + '("e13beeb34b932f309fb2c360a04a460821ca99fe58f69e65557d6c1b10ba18c7" + default)) + '(inhibit-startup-screen t) + '(package-selected-packages + '(ace-window dimmer dune dune-format elixir-mode gruber-darker-theme + neocaml ocamlformat use-package-treesit))) + +(custom-set-faces + ;; custom-set-faces was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + ) diff --git a/init.el b/init.el new file mode 100644 index 0000000..b04c251 --- /dev/null +++ b/init.el @@ -0,0 +1,69 @@ +;; package sources +(require 'package) +(setq package-archives '(("gnu" . "https://mirrors.tuna.tsinghua.edu.cn/elpa/gnu/") + ("nongnu" . "https://mirrors.tuna.tsinghua.edu.cn/elpa/nongnu/") + ("melpa" . "https://mirrors.tuna.tsinghua.edu.cn/elpa/melpa/"))) +(package-initialize) + +;; load local config script (not git controlled, like .env file) +(setq local-file (expand-file-name "local.el" user-emacs-directory)) +(when (file-exists-p local-file) + (load-file local-file)) + +;; handy settings +(tool-bar-mode -1) +(scroll-bar-mode -1) +(global-display-line-numbers-mode 1) +(global-auto-revert-mode t) + +(setq mac-command-modifier 'meta) +(setq confirm-kill-emacs 'y-or-n-p) +(setq-default cursor-type '(bar . 2)) + +(add-to-list 'default-frame-alist '(fullscreen . maximized)) + +(global-unset-key (kbd "C-SPC")) +(global-set-key (kbd "M-SPC") 'set-mark-command) +(global-set-key (kbd "C-x C-b") 'bs-show) + +(windmove-default-keybindings 'meta) + +(let ((font (face-attribute 'default :font))) + (when font + (set-face-attribute 'default nil :height 160))) + +(setq custom-file (expand-file-name "custom-file.el" user-emacs-directory)) +(load custom-file) +;; end handy settings + +;; treesit +(setq treesit-language-source-alist + '((c3 "https://github.com/c3lang/tree-sitter-c3"))) + +;; packages +(use-package use-package-treesit + :ensure t) + +(use-package gruber-darker-theme + :ensure t + :init + (load-theme 'gruber-darker t)) + +(use-package dimmer + :ensure t + :init + (setq dimmer-fraction 0.3) ; 调整变暗的程度(0.0 到 1.0,越大越暗,0.3 刚刚好) + :config + (dimmer-mode 1)) + +(use-package ace-window + :ensure t + :bind ("M-o" . ace-window)) + + +;; vendor +(add-to-list 'load-path (expand-file-name "vendor/c3-ts-mode" user-emacs-directory)) +(require 'c3-ts-mode) + + + diff --git a/vendor/c3-ts-mode/c3-ts-mode.el b/vendor/c3-ts-mode/c3-ts-mode.el new file mode 100644 index 0000000..cc60d61 --- /dev/null +++ b/vendor/c3-ts-mode/c3-ts-mode.el @@ -0,0 +1,683 @@ +;;; c3-ts-mode.el --- Major mode for C3 using tree-sitter -*- lexical-binding: t -*- + +;; Author: Christian Buttner +;; URL: https://github.com/c3lang/c3-ts-mode +;; Keywords: c3 languages tree-sitter +;; Version: 0.9.0 +;; Package-Requires : ((emacs "29.1")) + +;;; License: + +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation; either version 3, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, see . + +;;; Commentary: + +;; This tree-sitter powered Emacs 29+ major mode provides syntax highlighting, indentation, imenu and which-function support for C3. +;; It's built against the tree-sitter grammar located at . + +;;; Code: + +(require 'treesit) +(require 'c-ts-common) +(require 'compile) + +(eval-when-compile (require 'rx)) + +(declare-function treesit-node-child-by-field-name "treesit.c") +(declare-function treesit-node-type "treesit.c") +(declare-function treesit-node-text "treesit.c") +(declare-function treesit-parser-create "treesit.c") + +(defgroup c3-ts nil + "Major mode for editing C3 files." + :prefix "c3-ts-" + :group 'languages) + +(defcustom c3-ts-mode-indent-offset 2 + "Number of spaces for each indentation step in `c3-ts-mode'." + :version "29.1" + :type 'integer + :safe 'integerp + :group 'c3-ts) + +(defcustom c3-ts-mode-highlight-variable 't + "Enable highlighting of variables in `c3-ts-mode'." + :version "29.1" + :type 'boolean + :safe 'booleanp + :group 'c3-ts) + +(defcustom c3-ts-mode-highlight-property 't + "Enable highlighting of members in `c3-ts-mode'." + :version "29.1" + :type 'boolean + :safe 'booleanp + :group 'c3-ts) + +(defcustom c3-ts-mode-highlight-assignment 't + "Enable highlighting of assignments in `c3-ts-mode'." + :version "29.1" + :type 'boolean + :safe 'booleanp + :group 'c3-ts) + +(defcustom c3-ts-mode-highlight-punctuation 't + "Enable highlighting of punctuation in `c3-ts-mode'." + :version "29.1" + :type 'boolean + :safe 'booleanp + :group 'c3-ts) + +(defcustom c3-ts-mode-module-path-face '@font-lock-constant-face + "The face to use for highlighting module paths in `c3-ts-mode'." + :version "29.1" + :type 'symbol + :group 'c3-ts) + +(defcustom c3-ts-mode-assignment-face '@font-lock-variable-name-face + "The face to use for highlighting assignments in `c3-ts-mode'." + :version "29.1" + :type 'symbol + :group 'c3-ts) + +(defcustom c3-ts-mode-hook nil + "Hook run after entering `c3-ts-mode'." + :version "29.1" + :type 'hook + :group 'c3-ts) + +(defvar c3-ts-mode--syntax-table + (let ((table (make-syntax-table))) + ;; Adapted from c-ts-mode.el + (modify-syntax-entry ?_ "_" table) + (modify-syntax-entry ?\\ "\\" table) + (modify-syntax-entry ?+ "." table) + (modify-syntax-entry ?- "." table) + (modify-syntax-entry ?= "." table) + (modify-syntax-entry ?% "." table) + (modify-syntax-entry ?< ". 1" table) ; C3: the first character of a comment-start sequence + (modify-syntax-entry ?> ". 4" table) ; C3: the second character of a comment-end sequence + (modify-syntax-entry ?@ "w" table) ; C3: identifiers starting with @ + (modify-syntax-entry ?& "." table) + (modify-syntax-entry ?| "." table) + (modify-syntax-entry ?\' "\"" table) + (modify-syntax-entry ?` "\"" table) + (modify-syntax-entry ?\240 "." table) + (modify-syntax-entry ?/ ". 124b" table) + (modify-syntax-entry ?* ". 23" table) + (modify-syntax-entry ?\n "> b" table) + (modify-syntax-entry ?\^m "> b" table) + table) + "Syntax table for `c3-ts-mode'.") + +(defvar c3-ts-mode--keywords + ;; From "c3c --list-keywords", without base types + '("alias" + "assert" + "asm" + "attrdef" + "bitstruct" + "break" + "case" + "catch" + "const" + "continue" + "default" + "defer" + "do" + "else" + "enum" + "extern" + ;; "false" ;; NOTE Treated as constant + "faultdef" + "for" + "foreach" + "foreach_r" + "fn" + "tlocal" + "if" + "inline" + "import" + "macro" + "module" + "nextcase" + ;; "null" ;; NOTE Treated as constant + "interface" + "return" + "static" + "struct" + "switch" + ;; "true" ;; NOTE Treated as constant + "try" + "typedef" + "union" + "var" + "while" + + "$alignof" + "$assert" + "$assignable" + "$case" + "$default" + "$defined" + "$echo" + "$else" + "$embed" + "$endfor" + "$endforeach" + "$endif" + "$endswitch" + "$eval" + "$evaltype" + "$error" + "$exec" + "$extnameof" + "$feature" + "$for" + "$foreach" + "$if" + "$include" + "$is_const" + "$kindof" + "$nameof" + "$offsetof" + "$qnameof" + "$sizeof" + "$stringify" + "$switch" + "$typefrom" + "$typeof" + "$vacount" + "$vatype" + "$vaconst" + "$vaarg" + "$vaexpr" + "$vasplat")) + +(defvar c3-ts-mode--type-properties + ;; From "c3c --list-type-properties" + '("alignof" + "associated" + "elements" + "extnameof" + "from_ordinal" + "get" + "inf" + "is_eq" + "is_ordered" + "is_substruct" + "len" + "lookup" + "lookup_field" + "max" + "membersof" + "methodsof" + "min" + "nan" + "inner" + "kindof" + "names" + "nameof" + "params" + "paramsof" + "parentof" + "qnameof" + "returns" + "sizeof" + "set" + "tagof" + "has_tagof" + "values" + ;; Separate token in c3c + "typeid")) + + +(defvar c3-ts-mode--operators + ;; From "c3c --list-operators" + '("&" + "!" + "~" + "|" + "^" + ":" + ;; "," + ;; ";" + "=" + ">" + "/" + "." + ;; "#" + "<" + ;; "{" + ;; "[" + ;; "(" + "-" + "%" + "+" + "?" + ;; "}" + ;; "]" + ;; ")" + "*" + ;; "_" + "&&" + ;; "->" + "!!" + "&=" + "|=" + "^=" + "/=" + ".." + "?:" + "==" + ">=" + "=>" + "<=" + ;; "[<" + "-=" + "--" + "%=" + "*=" + "!=" + "||" + "+=" + "++" + ;; ">]" + "??" + ;; "::" + "<<" + ">>" + "..." + "<<=" + ">>=" + "&&&" + "+++" + "|||" + "???" + "+++=")) + +(defvar c3-ts-mode--feature-list + `((comment definition) + (keyword string type) + ;; TODO Not clear if assignment should go in level 4 or not (3 is the default level). + ,(append + '(builtin attribute escape-sequence literal constant assembly module function doc-comment) + (when c3-ts-mode-highlight-assignment '(assignment))) + ,(append + '(type-property operator bracket) + (when c3-ts-mode-highlight-punctuation '(punctuation)) + (when c3-ts-mode-highlight-variable '(variable)) + (when c3-ts-mode-highlight-property '(property))) + ;; (error) ;; Disabled by default + ) + "`treesit-font-lock-feature-list' for `c3-ts-mode'.") + +(defvar c3-ts-mode--font-lock-settings + ;; NOTE Earlier rules have precedence over later rules + (treesit-font-lock-rules + :language 'c3 + :feature 'doc-comment + '((doc_comment_contract name: (at_ident) @font-lock-builtin-face) + (doc_comment_contract mutability_contract: (_) @font-lock-constant-face) + (doc_comment ["<*" "*>"] @font-lock-doc-face) + (doc_comment_text) @font-lock-doc-face + ;; (doc_comment_contract parameter: ([(ident) (ct_ident) (hash_ident)]) @font-lock-variable-name-face) + (doc_comment_contract [":" "?"] @font-lock-doc-face) + (doc_comment_contract description: (_) @font-lock-doc-face) + ) + + :language 'c3 + :feature 'comment + '((line_comment) @font-lock-comment-face + (block_comment) @font-lock-comment-face + (doc_comment) @font-lock-doc-face) + + :language 'c3 + :feature 'literal + '((integer_literal) @font-lock-number-face + (real_literal) @font-lock-number-face + (char_literal) @font-lock-constant-face + (bytes_literal) @font-lock-constant-face) + + :language 'c3 + :feature 'string + '((string_literal) @font-lock-string-face + (raw_string_literal) @font-lock-string-face) + + :language 'c3 + :feature 'escape-sequence + :override t + '((escape_sequence) @font-lock-escape-face) + + :language 'c3 + :feature 'keyword + `([,@c3-ts-mode--keywords] @font-lock-keyword-face) + + :language 'c3 + :feature 'builtin + '([(builtin) (builtin_const)] @font-lock-builtin-face) + + :language 'c3 + :feature 'type-property + `((type_access_expr (access_ident (ident) @font-lock-constant-face (:match ,(rx-to-string `(: bos (or ,@c3-ts-mode--type-properties) eos)) @font-lock-constant-face)))) + + :language 'c3 + :feature 'constant + '((const_ident) @font-lock-constant-face + ["true" "false" "null"] @font-lock-constant-face) + + :language 'c3 + :feature 'assembly + '((asm_instr [(ident) "int"] @font-lock-function-call-face) + (asm_expr [(ct_ident) (ct_const_ident)] @font-lock-variable-use-face)) + + :language 'c3 + :feature 'module + `((module_resolution (ident) ,c3-ts-mode-module-path-face) + (module_declaration (path_ident (ident) ,c3-ts-mode-module-path-face)) + (import_path (path_ident (ident) ,c3-ts-mode-module-path-face))) + + :language 'c3 + :feature 'attribute + '((attribute name: (at_ident) @font-lock-builtin-face) + (at_type_ident) @font-lock-builtin-face + (call_inline_attributes (at_ident) @font-lock-builtin-face) + (type_suffix (at_ident) @font-lock-builtin-face)) + + :language 'c3 + :feature 'type + '((type_ident) @font-lock-type-face + (ct_type_ident) @font-lock-type-face + (base_type_name) @font-lock-type-face + + ;; TODO Probably don't want these + ;; (type_suffix ["[" "[<" ">]" "]"] @font-lock-type-face) + ;; (type "!" @font-lock-type-face :anchor) + ) + + :language 'c3 + :feature 'definition + '((func_header name: (_) @font-lock-function-name-face) + (macro_header name: (_) @font-lock-function-name-face)) + + :language 'c3 + :feature 'function + '((call_expr function: (ident_expr [(ident) (at_ident)] @font-lock-function-call-face)) + (call_expr function: (trailing_generic_expr argument: (ident_expr [(ident) (at_ident)] @font-lock-function-call-face))) + ;; Method call + (call_expr function: (field_expr field: (access_ident [(ident) (at_ident)] @font-lock-function-call-face))) ; NOTE Ambiguous, could be calling a method or function pointer + ;; Method on type + (call_expr function: (type_access_expr field: (access_ident [(ident) (at_ident)] @font-lock-function-call-face)))) + + :language 'c3 + :feature 'assignment + `((assignment_expr left: (ident_expr (ident) ,c3-ts-mode-assignment-face)) + (assignment_expr left: (field_expr field: (_) ,c3-ts-mode-assignment-face)) + (assignment_expr left: (unary_expr operator: "*" ,c3-ts-mode-assignment-face)) + (assignment_expr left: (subscript_expr ["[" "]"] ,c3-ts-mode-assignment-face)) + (assignment_expr left: (maybe_deref_expr ["[" "]"] ,c3-ts-mode-assignment-face)) + + (update_expr argument: (ident_expr (ident) ,c3-ts-mode-assignment-face)) + (update_expr argument: (field_expr field: (_) ,c3-ts-mode-assignment-face)) + (update_expr argument: (unary_expr operator: "*" ,c3-ts-mode-assignment-face)) + (update_expr argument: (subscript_expr ["[" "]"] ,c3-ts-mode-assignment-face)) + + (unary_expr operator: ["--" "++"] argument: (ident_expr (ident) ,c3-ts-mode-assignment-face)) + (unary_expr operator: ["--" "++"] argument: (field_expr field: (access_ident (ident)) ,c3-ts-mode-assignment-face)) + (unary_expr operator: ["--" "++"] argument: (subscript_expr ["[" "]"] ,c3-ts-mode-assignment-face))) + + :language 'c3 + :feature 'operator + `(([,@c3-ts-mode--operators]) @font-lock-operator-face) + + :language 'c3 + :feature 'property + '(;; Member + (field_expr field: (access_ident (ident) @font-lock-property-use-face)) + (struct_member_declaration (ident) @font-lock-property-name-face) + (struct_member_declaration (identifier_list (ident) @font-lock-property-name-face)) + (bitstruct_member_declaration (ident) @font-lock-property-name-face) + (initializer_list (initializer_element (param_path (param_path_element (access_ident (ident) @font-lock-property-name-face)))))) + + :language 'c3 + :feature 'variable + '([(ident) (ct_ident)] @font-lock-variable-use-face + ;; Parameter + (param name: (_) @font-lock-variable-name-face) + (trailing_block_param (at_ident) @font-lock-variable-name-face) + (call_arg_list (call_arg name: (_) @font-lock-variable-name-face)) + (enum_param (ident) @font-lock-variable-name-face) + ;; Declaration + (declaration (identifier_list [(ident) (ct_ident)] @font-lock-variable-name-face)) + (declaration name: [(ident) (ct_ident)] @font-lock-variable-name-face) + (var_declaration name: [(ident) (ct_ident)] @font-lock-variable-name-face) + (try_unwrap (ident) @font-lock-variable-name-face) + (catch_unwrap (ident) @font-lock-variable-name-face)) + + :language 'c3 + :feature 'bracket + '((["(" ")" "[" "]" "{" "}" "[<" ">]"]) @font-lock-bracket-face) + + :language 'c3 + :feature 'punctuation + '(([";" "," "::"]) @font-lock-punctuation-face) + + :language 'c3 + :feature 'error + :override t + '((ERROR) @font-lock-warning-face)) + "Tree-sitter font-lock settings for `c3-ts-mode'.") + +(defvar c3-ts-mode--simple-indent-rules + `((c3 + ((parent-is "source_file") column-0 0) + + ((node-is "else") parent-bol 0) ;; Also matches $else + ((node-is "^\\(case\\|ct_case\\|default\\|ct_default\\)_stmt$") parent-bol c3-ts-mode-indent-offset) + ((node-is "ct_stmt_body") parent-bol c3-ts-mode-indent-offset) + ((parent-is "ct_stmt_body") standalone-parent 0) + ((node-is "$endif") parent-bol 0) + ((node-is "$endfor") parent-bol 0) + ((node-is "$endswitch") parent-bol 0) + + ((and (parent-is "block_comment_text") c-ts-common-looking-at-star) + c-ts-common-comment-start-after-first-star -1) + + ;; NOTE This only indents the first line of a doc comment text. This way we preserve identation on subsequent lines, such as list item indentation. TODO Indent to a minimum of 1? Can still ruin formatting + ((node-is "doc_comment_text") parent-bol 1) + ((node-is "doc_comment_contract") parent-bol 1) + ((node-is "*>") parent-bol 0) + + ((node-is "}") standalone-parent 0) + ((node-is ")") standalone-parent 0) + + ((match "while" "do_stmt" nil nil nil) standalone-parent 0) + ((match "compound_stmt" "else_part" nil nil nil) standalone-parent 0) + + ;; Attributes + ((node-is "attributes") standalone-parent c3-ts-mode-indent-offset) + ((parent-is "attributes") parent 0) ;; Align attributes on same column + + ;; Body/block children + ((parent-is "enum_body") standalone-parent c3-ts-mode-indent-offset) + ((parent-is "struct_body") standalone-parent c3-ts-mode-indent-offset) + ((parent-is "bitstruct_body") standalone-parent c3-ts-mode-indent-offset) + ((parent-is "interface_body") standalone-parent c3-ts-mode-indent-offset) + ((parent-is "macro_func_body") standalone-parent c3-ts-mode-indent-offset) + ((parent-is "implies_body") standalone-parent c3-ts-mode-indent-offset) + + ((parent-is "compound_stmt") standalone-parent c3-ts-mode-indent-offset) + ((parent-is "initializer_list") standalone-parent c3-ts-mode-indent-offset) + ((parent-is "case_stmt") standalone-parent c3-ts-mode-indent-offset) + ((parent-is "default_stmt") standalone-parent c3-ts-mode-indent-offset) + + ;; if/switch/for/while/defer with block + ((match "compound_stmt" "\\(if\\|switch\\|for\\|foreach\\|while\\|do\\|defer\\)_stmt" nil nil nil) standalone-parent 0) + + ;; for/while/defer without block + ((parent-is "\\(for\\|foreach\\|while\\|defer\\)_stmt") standalone-parent c3-ts-mode-indent-offset) + + ;; Body not handled so far + ((field-is "body") standalone-parent 0) + ((field-is "lambda_body") standalone-parent 0) + + ;; Trailing macro block + ((match "compound_stmt" nil "trailing" nil nil) parent 0) + + ((match nil "field_expr" "field" nil nil) parent-bol c3-ts-mode-indent-offset) + ((n-p-gp "." "field_expr" nil) parent-bol c3-ts-mode-indent-offset) ;; Field access beginning with "." + ((match nil "type_access_expr" "field" nil nil) parent-bol c3-ts-mode-indent-offset) + ((match nil "assignment_expr" "right" nil nil) parent-bol c3-ts-mode-indent-offset) + ((match nil "const_declaration" "right" nil nil) parent-bol c3-ts-mode-indent-offset) + ((match nil "declaration" "right" nil nil) parent-bol c3-ts-mode-indent-offset) + + ;; Multi line declarations + ((parent-is "identifier_list") parent 0) + ((parent-is "^for_cond") parent 1) + ((parent-is "^foreach_cond") parent 1) + ((parent-is "ct_for_cond") parent 0) + ((parent-is "ct_foreach_cond") parent 0) + ((parent-is "paren_cond") parent 1) + ((parent-is "catch_unwrap_list") parent 0) + ((parent-is "comma_decl_or_expr") parent 0) + + ;; First parameter/argument + ((match "^\\(call_\\|attribute_\\)?arg\\|param\\|enum_param_declaration\\|trailing_block_param$" nil nil 1 1) parent-bol c3-ts-mode-indent-offset) + ;; Subsequent params/arguments + ((match "^\\(call_\\|attribute_\\)?arg\\|param\\|enum_param_declaration\\|trailing_block_param$" nil nil 2 nil) (nth-sibling 1) 0) + + ;; String/bytes literals + ((node-is "raw_string_literal") no-indent) + ((match "string_literal" "string_expr" nil 0 0) parent 0) + ((match "string_literal" "string_expr" nil 1 nil) (nth-sibling 0) 0) + ((match "bytes_literal" "bytes_expr" nil 0 0) parent 0) + ((match "bytes_literal" "bytes_expr" nil 1 nil) (nth-sibling 0) 0) + + ((parent-is "paren") parent 1) + ((parent-is "binary") parent 0) + ((parent-is "range") parent 0) + ((parent-is "elvis_orelse") parent 0) + ((parent-is "ternary") parent c3-ts-mode-indent-offset) + ((parent-is "subscript") parent c3-ts-mode-indent-offset) + ((parent-is "update") parent c3-ts-mode-indent-offset) + ((parent-is "call") parent c3-ts-mode-indent-offset) + ((parent-is "cast") parent c3-ts-mode-indent-offset) + + ((parent-is "func_declaration") standalone-parent 0) + ((parent-is "func_header") standalone-parent 0) + ((parent-is "macro_declaration") standalone-parent 0) + ((parent-is "macro_header") standalone-parent 0) + + ((node-is "initializer_list") parent 0) + + ;; ((parent-is "ERROR") no-indent 0) + ))) + +(defun c3-ts-mode--defun-name (node) + "Return the name of the defun NODE." + (let () + (treesit-node-text + (treesit-node-child-by-field-name + (pcase (treesit-node-type node) + ("func_definition" + (car + (treesit-filter-child node + (lambda (ch) + (string-equal (treesit-node-type ch) "func_header")) + t))) + ("macro_declaration" + (car + (treesit-filter-child node + (lambda (ch) + (string-equal (treesit-node-type ch) "macro_header")) + t))) + (_ node)) + "name") + t))) + + +;;;###autoload +(define-derived-mode c3-ts-mode prog-mode "C3" + "Major mode for editing C3 files, powered by tree-sitter." + :group 'c3-ts + :syntax-table c3-ts-mode--syntax-table + + ;; Comment + (c-ts-common-comment-setup) + + ;; Electric + (setq-local electric-indent-chars + (append "{}():;," electric-indent-chars)) + + (when (treesit-ready-p 'c3) + (treesit-parser-create 'c3) + + ;; Font-lock + (setq-local treesit-font-lock-settings c3-ts-mode--font-lock-settings) + (setq-local treesit-font-lock-feature-list c3-ts-mode--feature-list) + + ;; Indent + (setq-local treesit-simple-indent-rules c3-ts-mode--simple-indent-rules) + + ;; Navigation + (setq-local treesit-defun-name-function #'c3-ts-mode--defun-name) + (setq-local treesit-defun-type-regexp + (rx bos + (or "struct_declaration" + "bitstruct_declaration" + "enum_declaration" + "interface_declaration" + "func_definition" + "macro_declaration" + "const_declaration" + "alias_declaration" + "typedef_declaration" + "faultdef_declaration" + "attrdef_declaration") + eos)) + + ;; Imenu + (setq-local treesit-simple-imenu-settings + `(("Struct" "\\`struct_declaration\\'" nil nil) + ("Bitstruct" "\\`bitstruct_declaration\\'" nil nil) + ("Enum" "\\`enum_declaration\\'" nil nil) + ("Interface" "\\`interface_declaration\\'" nil nil) + ("Function" "\\`func_definition\\'" nil nil) + ("Macro" "\\`macro_declaration\\'" nil nil) + ("Const" "\\`const_declaration\\'" nil nil) + ("Alias" "\\`alias_declaration\\'" nil nil) + ("Type" "\\`typedef_declaration\\'" nil nil) + ("Fault" "\\`faultdef_declaration\\'" nil nil) + ("Attribute" "\\`attrdef_declaration\\'" nil nil))) + + ;; Which-function + (setq-local which-func-functions (treesit-defun-at-point)) + + (treesit-major-mode-setup))) + +(when (treesit-ready-p 'c3) + (add-to-list 'auto-mode-alist '("\\.c3[it]?\\'" . c3-ts-mode))) + +(eval-after-load 'compile + (lambda() + (add-to-list 'compilation-error-regexp-alist-alist + '(c3 + "^(\\([^:]*\\):\\([0-9]+\\):\\([0-9]+\\)) \\(Warning\\)?.*$" + 1 2 3 (4))) + (add-to-list 'compilation-error-regexp-alist 'c3))) + +(provide 'c3-ts-mode) + + +;;; c3-ts-mode.el ends here