Compare commits

..

8 Commits

Author SHA1 Message Date
dc507dfc23 Make syntax highlighting smoother 2025-12-30 10:56:31 +00:00
26e0b06e24 Add strikethrough support 2025-12-30 10:55:32 +00:00
235eafb01c Rearrange code and cleanup 2025-12-30 01:19:50 +00:00
04179d1a4e Cleanup and add visible whitespaces. 2025-12-29 21:55:49 +00:00
c7068d33d7 Feat: add hover boxes and diagnostics from lsp 2025-12-29 15:56:51 +00:00
6108f78be3 Fix lsp bugs
- Fix: Incorrect setting of incremental edits for lsp and more
2025-12-27 09:53:46 +00:00
bfaba81317 Add lsp's for many different languages and minor fixes 2025-12-27 04:31:08 +00:00
a38ba1f813 Minor fixes and optimizations 2025-12-26 22:13:11 +00:00
97 changed files with 5966 additions and 3950 deletions

4
.clangd Normal file
View File

@@ -0,0 +1,4 @@
CompileFlags:
Add: [-I/home/syed/main/crib/include, -I/home/syed/main/crib/libs]
Remove: []
Compiler: clang++

6
.gitignore vendored
View File

@@ -7,9 +7,13 @@
.vscode .vscode
samples/t_* samples/tmp*
build build
bin bin
grammar/.*.scm
.thinlto-cache/
__old__ __old__

8
.gitmodules vendored
View File

@@ -130,3 +130,11 @@
path = libs/tree-sitter-markdown path = libs/tree-sitter-markdown
url = https://github.com/tree-sitter-grammars/tree-sitter-markdown.git url = https://github.com/tree-sitter-grammars/tree-sitter-markdown.git
ignore = dirty ignore = dirty
[submodule "libs/tree-sitter-typescript"]
path = libs/tree-sitter-typescript
url = https://github.com/tree-sitter/tree-sitter-typescript.git
ignore = dirty
[submodule "libs/tree-sitter-man"]
path = libs/tree-sitter-man
url = https://github.com/ribru17/tree-sitter-man.git
ignore = dirty

View File

@@ -13,14 +13,21 @@ CCACHE := ccache
CXX_DEBUG := $(CCACHE) g++ CXX_DEBUG := $(CCACHE) g++
CXX_RELEASE := $(CCACHE) clang++ CXX_RELEASE := $(CCACHE) clang++
CFLAGS_DEBUG := -std=c++20 -Wall -Wextra -O0 -fno-inline -gsplit-dwarf -g -fsanitize=address -fno-omit-frame-pointer CFLAGS_DEBUG := -std=c++20 -Wall -Wextra \
CFLAGS_RELEASE := -std=c++20 -O3 -march=native -flto=thin \ -O0 -fno-inline -gsplit-dwarf\
-g -fsanitize=address -fno-omit-frame-pointer\
-Wno-unused-command-line-argument \
-I./include -I./libs
CFLAGS_RELEASE := -std=c++20 -O3 -march=native \
-fno-exceptions -fno-rtti -fstrict-aliasing \ -fno-exceptions -fno-rtti -fstrict-aliasing \
-ffast-math -funroll-loops \ -ffast-math \
-fvisibility=hidden \ -fvisibility=hidden -fuse-ld=lld \
-flto=thin -Wl,--thinlto-cache-dir=.thinlto-cache \
-fomit-frame-pointer -DNDEBUG -s \ -fomit-frame-pointer -DNDEBUG -s \
-mllvm -vectorize-loops \ -mllvm -vectorize-loops \
-fno-unwind-tables -fno-asynchronous-unwind-tables -fno-unwind-tables -fno-asynchronous-unwind-tables\
-Wno-unused-command-line-argument \
-I./include -I./libs
PCH_CFLAGS_DEBUG := $(CFLAGS_DEBUG) -x c++-header PCH_CFLAGS_DEBUG := $(CFLAGS_DEBUG) -x c++-header
PCH_CFLAGS_RELEASE := $(CFLAGS_RELEASE) -x c++-header PCH_CFLAGS_RELEASE := $(CFLAGS_RELEASE) -x c++-header
@@ -34,6 +41,8 @@ TREE_SITTER_LIBS := $(wildcard libs/tree-sitter-*/libtree-sitter*.a)
PHP_LIB := libs/tree-sitter-php/php/libtree-sitter-php.a PHP_LIB := libs/tree-sitter-php/php/libtree-sitter-php.a
TSX_LIB := libs/tree-sitter-typescript/tsx/libtree-sitter-tsx.a
NGINX_OBJ_PARSER := libs/tree-sitter-nginx/build/Release/obj.target/tree_sitter_nginx_binding/src/parser.o NGINX_OBJ_PARSER := libs/tree-sitter-nginx/build/Release/obj.target/tree_sitter_nginx_binding/src/parser.o
GITIGNORE_OBJ_PARSER := libs/tree-sitter-gitignore/build/Release/obj.target/tree_sitter_ignore_binding/src/parser.o GITIGNORE_OBJ_PARSER := libs/tree-sitter-gitignore/build/Release/obj.target/tree_sitter_ignore_binding/src/parser.o
@@ -41,6 +50,9 @@ GITIGNORE_OBJ_PARSER := libs/tree-sitter-gitignore/build/Release/obj.target/tree
FISH_OBJ_PARSER := libs/tree-sitter-fish/build/Release/obj.target/tree_sitter_fish_binding/src/parser.o FISH_OBJ_PARSER := libs/tree-sitter-fish/build/Release/obj.target/tree_sitter_fish_binding/src/parser.o
FISH_OBJ_SCANNER := libs/tree-sitter-fish/build/Release/obj.target/tree_sitter_fish_binding/src/scanner.o FISH_OBJ_SCANNER := libs/tree-sitter-fish/build/Release/obj.target/tree_sitter_fish_binding/src/scanner.o
MAN_OBJ_PARSER := libs/tree-sitter-man/build/Release/obj.target/tree_sitter_man_binding/src/parser.o
MAN_OBJ_SCANNER := libs/tree-sitter-man/build/Release/obj.target/tree_sitter_man_binding/src/scanner.o
MD_OBJ_PARSER := libs/tree-sitter-markdown/build/Release/obj.target/tree_sitter_markdown_binding/tree-sitter-markdown/src/parser.o MD_OBJ_PARSER := libs/tree-sitter-markdown/build/Release/obj.target/tree_sitter_markdown_binding/tree-sitter-markdown/src/parser.o
MD_OBJ_SCANNER := libs/tree-sitter-markdown/build/Release/obj.target/tree_sitter_markdown_binding/tree-sitter-markdown/src/scanner.o MD_OBJ_SCANNER := libs/tree-sitter-markdown/build/Release/obj.target/tree_sitter_markdown_binding/tree-sitter-markdown/src/scanner.o
@@ -52,17 +64,20 @@ LIBS := \
libs/tree-sitter/libtree-sitter.a \ libs/tree-sitter/libtree-sitter.a \
$(TREE_SITTER_LIBS) \ $(TREE_SITTER_LIBS) \
$(PHP_LIB) \ $(PHP_LIB) \
$(TSX_LIB) \
$(NGINX_OBJ_PARSER) \ $(NGINX_OBJ_PARSER) \
$(GITIGNORE_OBJ_PARSER) \ $(GITIGNORE_OBJ_PARSER) \
$(FISH_OBJ_PARSER) \ $(FISH_OBJ_PARSER) \
$(FISH_OBJ_SCANNER) \ $(FISH_OBJ_SCANNER) \
$(MAN_OBJ_PARSER) \
$(MAN_OBJ_SCANNER) \
$(MD_OBJ_PARSER) \ $(MD_OBJ_PARSER) \
$(MD_OBJ_SCANNER) \ $(MD_OBJ_SCANNER) \
$(MD_I_OBJ_PARSER) \ $(MD_I_OBJ_PARSER) \
$(MD_I_OBJ_SCANNER) \ $(MD_I_OBJ_SCANNER) \
-lpcre2-8 -lmagic -lpcre2-8 -lmagic
SRC := $(wildcard $(SRC_DIR)/*.cc) SRC := $(wildcard $(SRC_DIR)/**/*.cc) $(wildcard $(SRC_DIR)/*.cc)
OBJ_DEBUG := $(patsubst $(SRC_DIR)/%.cc,$(OBJ_DIR)/debug/%.o,$(SRC)) OBJ_DEBUG := $(patsubst $(SRC_DIR)/%.cc,$(OBJ_DIR)/debug/%.o,$(SRC))
OBJ_RELEASE := $(patsubst $(SRC_DIR)/%.cc,$(OBJ_DIR)/release/%.o,$(SRC)) OBJ_RELEASE := $(patsubst $(SRC_DIR)/%.cc,$(OBJ_DIR)/release/%.o,$(SRC))

View File

@@ -6,21 +6,24 @@ A TUI IDE.
# TODO # TODO
- [ ] Get lsp warnings byte offsets/lengths and render them as background color. - [ ] Add status bar & RUNNER mode
- [ ] Fix indentation logic
- [ ] Fix bug where closing immediately while lsp is loading hangs and then segfaults.
- [ ] For `"insertTextFormat": 2` in `clangd` and similar use only the last word in the signature when replacing
- [ ] Keep a list of words in the current buffer. (for auto completion) (maybe?)
- [ ] Add ecma to js and make tsx
- [ ] Add support for LSP & autocomplete / snippets. - [ ] Add support for LSP & autocomplete / snippets.
- First research - First research
- `textDocument/documentHighlight` - for highlighting stuff (probably tree-sitter is enough) - `textDocument/documentHighlight` - for highlighting stuff (probably tree-sitter is enough)
- `textDocument/selectionRange` // - `textDocument/selectionRange` //
- `textDocument/completion` - Obviously - `textDocument/completion` - Obviously
- `textDocument/onTypeFormatting` - seems promising for auto formatting (indentation etc) - `textDocument/onTypeFormatting` - seems promising for auto formatting (indentation etc)
- `textDocument/inlayHint` & `textDocument/inlineHint` & `textDocument/codeLens`
- `textDocument/formatting` & `textDocument/rangeFormatting` - `textDocument/formatting` & `textDocument/rangeFormatting`
- `textDocument/semanticTokens/*` (probably tree-sitter is enough) - `textDocument/semanticTokens/*` (probably tree-sitter is enough)
- `textDocument/linkedEditingRange` - probably useful - `textDocument/linkedEditingRange` - probably useful
- `textDocument/foldingRange` - i will never use this for folding but it might be useful for other things. - `textDocument/foldingRange` - i will never use this for folding but it might be useful for other things.
- `textDocument/rename` & `textDocument/prepareRename` - probably useful - `textDocument/rename` & `textDocument/prepareRename` - probably useful
- And a lot more (just go through each for `clangd` and then expand to say `solargraph`). - And a lot more (just go through each for `clangd` and then expand to say `solargraph`).
- Make incremental edits apply. // make a bool field in LSP qhich says if it supports incremental and based on it apply edits
- Make a universal plug for lsp. So focus more on making a general purpose solid communication interface. Instead of something specific. - Make a universal plug for lsp. So focus more on making a general purpose solid communication interface. Instead of something specific.
- With a 4ish pass system. (more like each returned value from the lsp is used in 4 ways) - With a 4ish pass system. (more like each returned value from the lsp is used in 4 ways)
1. One for stuff like jump to x position. or rename symbol x to y. (stuff that explicitly requires user request to do something) 1. One for stuff like jump to x position. or rename symbol x to y. (stuff that explicitly requires user request to do something)
@@ -28,9 +31,6 @@ A TUI IDE.
2. One for stuff that only affects highlighting and styles . like symbol highlighting etc. 2. One for stuff that only affects highlighting and styles . like symbol highlighting etc.
3. One for Warnings/errors and inlay hints etc. (stuff that adds virtual text to the editor) 3. One for Warnings/errors and inlay hints etc. (stuff that adds virtual text to the editor)
4. One for fromatting and stuff like that. (stuff that edits the buffer text) 4. One for fromatting and stuff like that. (stuff that edits the buffer text)
- [ ] Make tree sitter spans truly incremental - or atleast make them pos based and not byte so minor changes only shifts inline
- And make inner trees incremental too
- [ ] Use LSP to add inlay hints in order to test virtual text. then make an iterator over screen that mimics the renderer for scrolling functions.
- [ ] Add codeium/copilot support for auto-completion (uses the VAI virtual text) as a test phase. - [ ] Add codeium/copilot support for auto-completion (uses the VAI virtual text) as a test phase.
- [ ] Add a whitespace highlighter (nerd font). for spaces and tabs at start/end of line. not as virtual but instead at render time. - [ ] Add a whitespace highlighter (nerd font). for spaces and tabs at start/end of line. not as virtual but instead at render time.
- [ ] Once renderer is proven to work well (i.e. redo this commit) merge `experimental` branch into `main`. commit `43f443e` on `experimental`. - [ ] Once renderer is proven to work well (i.e. redo this commit) merge `experimental` branch into `main`. commit `43f443e` on `experimental`.
@@ -42,9 +42,8 @@ A TUI IDE.
- [ ] Add alt + click to set multiple cursors. - [ ] Add alt + click to set multiple cursors.
- [ ] Add search / replace along with search / virtual cursors are searched pos. - [ ] Add search / replace along with search / virtual cursors are searched pos.
- [ ] Add support for undo/redo. - [ ] Add support for undo/redo.
- [ ] Add `.scm` files for all the supported languages. (2/14) Done.
- [ ] Add splash screen / minigame jumping. - [ ] Add splash screen / minigame jumping.
- [ ] Normalize / validate unicode on file open. - [ ] Normalize / validate unicode on file open. so use utf8 purely and fix other types of files
- [ ] Add git stuff. - [ ] Add git stuff.
- [ ] Add SQL support. (viewer and basic editor) - [ ] Add SQL support. (viewer and basic editor)
- [ ] Add color picker/palette for hex or other css colors. - [ ] Add color picker/palette for hex or other css colors.
@@ -55,5 +54,9 @@ A TUI IDE.
- [ ] Add the highlight of block edges when cursor is on a bracket (or in). (prolly from lsp) - [ ] Add the highlight of block edges when cursor is on a bracket (or in). (prolly from lsp)
- [ ] Add this thing where selection double click on a bracket selects whole block. - [ ] Add this thing where selection double click on a bracket selects whole block.
- (only on the first time) and sets mode to `WORD`. - (only on the first time) and sets mode to `WORD`.
- [ ] Redo cpp/c/h scm file . also pretty much all of them do manually
- [ ] Try making `lua-typed` and man pages `tree-sitter` grammar.
- [ ] Redo folding system and its relation to move_line_* functions. (Currently its a mess) - [ ] Redo folding system and its relation to move_line_* functions. (Currently its a mess)
- [ ] Make whole thing event driven and not clock driven. - [ ] Make whole thing event driven and not clock driven.
- [ ] Fix in kutu.rb such that windows arent focused on hover . they are only when they are true windows and not just popups . also popus are focused even without hover when they open.

View File

@@ -1,4 +1,4 @@
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
[ [
"(" "("
")" ")"
@@ -12,7 +12,7 @@
"))" "))"
] @punctuation.bracket ] @punctuation.bracket
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
[ [
";" ";"
";;" ";;"
@@ -21,7 +21,7 @@
"&" "&"
] @punctuation.delimiter ] @punctuation.delimiter
;; #F29668 #000000 0 1 0 1 ;; #F29668 #000000 0 1 0 0 1
[ [
">" ">"
">>" ">>"
@@ -49,7 +49,7 @@
"!" "!"
] @operator ] @operator
;; #AAD94C #000000 0 0 0 1 ;; #AAD94C #000000 0 0 0 0 1
[ [
(string) (string)
(raw_string) (raw_string)
@@ -57,7 +57,7 @@
(heredoc_body) (heredoc_body)
] @string ] @string
;; #E6C08A #000000 0 0 0 1 ;; #E6C08A #000000 0 0 0 0 1
[ [
(heredoc_start) (heredoc_start)
(heredoc_end) (heredoc_end)
@@ -72,7 +72,7 @@
(concatenation (concatenation
(word) @string) (word) @string)
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"if" "if"
"then" "then"
@@ -84,7 +84,7 @@
"esac" "esac"
] @keyword.conditional ] @keyword.conditional
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"for" "for"
"do" "do"
@@ -94,7 +94,7 @@
"while" "while"
] @keyword.repeat ] @keyword.repeat
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"declare" "declare"
"typeset" "typeset"
@@ -104,39 +104,39 @@
"unsetenv" "unsetenv"
] @keyword ] @keyword
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
"export" @keyword.import "export" @keyword.import
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
"function" @keyword.function "function" @keyword.function
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(special_variable_name) @constant (special_variable_name) @constant
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
((word) @constant.builtin ((word) @constant.builtin
(#match? @constant.builtin "^(SIGHUP|SIGINT|SIGQUIT|SIGILL|SIGTRAP|SIGABRT|SIGBUS|SIGFPE|SIGKILL|SIGUSR1|SIGSEGV|SIGUSR2|SIGPIPE|SIGALRM|SIGTERM|SIGSTKFLT|SIGCHLD|SIGCONT|SIGSTOP|SIGTSTP|SIGTTIN|SIGTTOU|SIGURG|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGIO|SIGPWR|SIGSYS|SIGRTMIN|SIGRTMIN\+1|SIGRTMIN\+2|SIGRTMIN\+3|SIGRTMIN\+4|SIGRTMIN\+5|SIGRTMIN\+6|SIGRTMIN\+7|SIGRTMIN\+8|SIGRTMIN\+9|SIGRTMIN\+10|SIGRTMIN\+11|SIGRTMIN\+12|SIGRTMIN\+13|SIGRTMIN\+14|SIGRTMIN\+15|SIGRTMAX\-14|SIGRTMAX\-13|SIGRTMAX\-12|SIGRTMAX\-11|SIGRTMAX\-10|SIGRTMAX\-9|SIGRTMAX\-8|SIGRTMAX\-7|SIGRTMAX\-6|SIGRTMAX\-5|SIGRTMAX\-4|SIGRTMAX\-3|SIGRTMAX\-2|SIGRTMAX\-1|SIGRTMAX)$")) (#match? @constant.builtin "^(SIGHUP|SIGINT|SIGQUIT|SIGILL|SIGTRAP|SIGABRT|SIGBUS|SIGFPE|SIGKILL|SIGUSR1|SIGSEGV|SIGUSR2|SIGPIPE|SIGALRM|SIGTERM|SIGSTKFLT|SIGCHLD|SIGCONT|SIGSTOP|SIGTSTP|SIGTTIN|SIGTTOU|SIGURG|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGIO|SIGPWR|SIGSYS|SIGRTMIN|SIGRTMIN\+1|SIGRTMIN\+2|SIGRTMIN\+3|SIGRTMIN\+4|SIGRTMIN\+5|SIGRTMIN\+6|SIGRTMIN\+7|SIGRTMIN\+8|SIGRTMIN\+9|SIGRTMIN\+10|SIGRTMIN\+11|SIGRTMIN\+12|SIGRTMIN\+13|SIGRTMIN\+14|SIGRTMIN\+15|SIGRTMAX\-14|SIGRTMAX\-13|SIGRTMAX\-12|SIGRTMAX\-11|SIGRTMAX\-10|SIGRTMAX\-9|SIGRTMAX\-8|SIGRTMAX\-7|SIGRTMAX\-6|SIGRTMAX\-5|SIGRTMAX\-4|SIGRTMAX\-3|SIGRTMAX\-2|SIGRTMAX\-1|SIGRTMAX)$"))
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
((word) @boolean.true ((word) @boolean.true
(#match? @boolean.true "^true$")) (#match? @boolean.true "^true$"))
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
((word) @boolean.false ((word) @boolean.false
(#match? @boolean.false "^false$")) (#match? @boolean.false "^false$"))
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment @spell (comment) @comment @spell
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
(test_operator) @operator (test_operator) @operator
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(command_substitution (command_substitution
"$(" @punctuation.special "$(" @punctuation.special
")" @punctuation.special) ")" @punctuation.special)
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(process_substitution (process_substitution
[ [
"<(" "<("
@@ -144,7 +144,7 @@
] @punctuation.special ] @punctuation.special
")" @punctuation.special) ")" @punctuation.special)
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(arithmetic_expansion (arithmetic_expansion
[ [
"$((" "$(("
@@ -152,43 +152,43 @@
] @punctuation.special ] @punctuation.special
"))" @punctuation.special) "))" @punctuation.special)
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
(arithmetic_expansion (arithmetic_expansion
"," @punctuation.delimiter) "," @punctuation.delimiter)
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
(ternary_expression (ternary_expression
[ [
"?" "?"
":" ":"
] @keyword.conditional.ternary) ] @keyword.conditional.ternary)
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
(binary_expression (binary_expression
operator: _ @operator) operator: _ @operator)
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
(unary_expression (unary_expression
operator: _ @operator) operator: _ @operator)
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
(postfix_expression (postfix_expression
operator: _ @operator) operator: _ @operator)
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(function_definition (function_definition
name: (word) @function) name: (word) @function)
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(command_name (command_name
(word) @function.call) (word) @function.call)
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(command_name (command_name
(word) @function.builtin (word) @function.builtin
(#match? @function.builtin "^(\.|\:|alias|bg|bind|break|builtin|caller|cd|command|compgen|complete|compopt|continue|coproc|dirs|disown|echo|enable|eval|exec|exit|false|fc|fg|getopts|hash|help|history|jobs|kill|let|logout|mapfile|popd|printf|pushd|pwd|read|readarray|return|set|shift|shopt|source|suspend|test|time|times|trap|true|type|typeset|ulimit|umask|unalias|wait)$")) (#match? @function.builtin "^(\.|\:|alias|bg|bind|break|builtin|caller|cd|command|compgen|complete|compopt|continue|coproc|dirs|disown|echo|enable|eval|exec|exit|false|fc|fg|getopts|hash|help|history|jobs|kill|let|logout|mapfile|popd|printf|pushd|pwd|read|readarray|return|set|shift|shopt|source|suspend|test|time|times|trap|true|type|typeset|ulimit|umask|unalias|wait)$"))
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(command (command
argument: [ argument: [
(word) @variable.parameter (word) @variable.parameter
@@ -196,76 +196,76 @@
(word) @variable.parameter) (word) @variable.parameter)
]) ])
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(declaration_command (declaration_command
(word) @variable.parameter) (word) @variable.parameter)
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(unset_command (unset_command
(word) @variable.parameter) (word) @variable.parameter)
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
(number) @number (number) @number
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
((word) @number ((word) @number
(#match? @number "^[0-9]+$")) (#match? @number "^[0-9]+$"))
;; #AAD94C #000000 0 0 0 1 ;; #AAD94C #000000 0 0 0 0 1
(file_redirect (file_redirect
(word) @string.special.path) (word) @string.special.path)
;; #AAD94C #000000 0 0 0 1 ;; #AAD94C #000000 0 0 0 0 1
(herestring_redirect (herestring_redirect
(word) @string) (word) @string)
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
(file_descriptor) @operator (file_descriptor) @operator
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(simple_expansion (simple_expansion
"$" @punctuation.special) @none "$" @punctuation.special) @none
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(expansion (expansion
"${" @punctuation.special "${" @punctuation.special
"}" @punctuation.special) @none "}" @punctuation.special) @none
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(expansion (expansion
operator: _ @punctuation.special) operator: _ @punctuation.special)
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(expansion (expansion
"@" "@"
. .
operator: _ @character.special) operator: _ @character.special)
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
((expansion ((expansion
(subscript (subscript
index: (word) @character.special)) index: (word) @character.special))
(#any-of? @character.special "@" "*")) (#any-of? @character.special "@" "*"))
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
"``" @punctuation.special "``" @punctuation.special
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(variable_name) @variable (variable_name) @variable
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
((variable_name) @constant ((variable_name) @constant
(#match? @constant "^[A-Z][A-Z_0-9]*$")) (#match? @constant "^[A-Z][A-Z_0-9]*$"))
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
((variable_name) @variable.builtin ((variable_name) @variable.builtin
(#match? @variable.builtin "^(CDPATH|HOME|IFS|MAIL|MAILPATH|OPTARG|OPTIND|PATH|PS1|PS2|_|BASH|BASHOPTS|BASHPID|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_ARGV0|BASH_CMDS|BASH_COMMAND|BASH_COMPAT|BASH_ENV|BASH_EXECUTION_STRING|BASH_LINENO|BASH_LOADABLES_PATH|BASH_REMATCH|BASH_SOURCE|BASH_SUBSHELL|BASH_VERSINFO|BASH_VERSION|BASH_XTRACEFD|CHILD_MAX|COLUMNS|COMP_CWORD|COMP_LINE|COMP_POINT|COMP_TYPE|COMP_KEY|COMP_WORDBREAKS|COMP_WORDS|COMPREPLY|COPROC|DIRSTACK|EMACS|ENV|EPOCHREALTIME|EPOCHSECONDS|EUID|EXECIGNORE|FCEDIT|FIGNORE|FUNCNAME|FUNCNEST|GLOBIGNORE|GROUPS|histchars|HISTCMD|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTIGNORE|HISTSIZE|HISTTIMEFORMAT|HOSTFILE|HOSTNAME|HOSTTYPE|IGNOREEOF|INPUTRC|INSIDE_EMACS|LANG|LC_ALL|LC_COLLATE|LC_CTYPE|LC_MESSAGES|LC_NUMERIC|LC_TIME|LINENO|LINES|MACHTYPE|MAILCHECK|MAPFILE|OLDPWD|OPTERR|OSTYPE|PIPESTATUS|POSIXLY_CORRECT|PPID|PROMPT_COMMAND|PROMPT_DIRTRIM|PS0|PS3|PS4|PWD|RANDOM|READLINE_ARGUMENT|READLINE_LINE|READLINE_MARK|READLINE_POINT|REPLY|SECONDS|SHELL|SHELLOPTS|SHLVL|SRANDOM|TIMEFORMAT|TMOUT|TMPDIR|UID)$")) (#match? @variable.builtin "^(CDPATH|HOME|IFS|MAIL|MAILPATH|OPTARG|OPTIND|PATH|PS1|PS2|_|BASH|BASHOPTS|BASHPID|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_ARGV0|BASH_CMDS|BASH_COMMAND|BASH_COMPAT|BASH_ENV|BASH_EXECUTION_STRING|BASH_LINENO|BASH_LOADABLES_PATH|BASH_REMATCH|BASH_SOURCE|BASH_SUBSHELL|BASH_VERSINFO|BASH_VERSION|BASH_XTRACEFD|CHILD_MAX|COLUMNS|COMP_CWORD|COMP_LINE|COMP_POINT|COMP_TYPE|COMP_KEY|COMP_WORDBREAKS|COMP_WORDS|COMPREPLY|COPROC|DIRSTACK|EMACS|ENV|EPOCHREALTIME|EPOCHSECONDS|EUID|EXECIGNORE|FCEDIT|FIGNORE|FUNCNAME|FUNCNEST|GLOBIGNORE|GROUPS|histchars|HISTCMD|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTIGNORE|HISTSIZE|HISTTIMEFORMAT|HOSTFILE|HOSTNAME|HOSTTYPE|IGNOREEOF|INPUTRC|INSIDE_EMACS|LANG|LC_ALL|LC_COLLATE|LC_CTYPE|LC_MESSAGES|LC_NUMERIC|LC_TIME|LINENO|LINES|MACHTYPE|MAILCHECK|MAPFILE|OLDPWD|OPTERR|OSTYPE|PIPESTATUS|POSIXLY_CORRECT|PPID|PROMPT_COMMAND|PROMPT_DIRTRIM|PS0|PS3|PS4|PWD|RANDOM|READLINE_ARGUMENT|READLINE_LINE|READLINE_MARK|READLINE_POINT|REPLY|SECONDS|SHELL|SHELLOPTS|SHLVL|SRANDOM|TIMEFORMAT|TMOUT|TMPDIR|UID)$"))
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(case_item (case_item
value: (word) @variable.parameter) value: (word) @variable.parameter)
;; #AAD94C #000000 0 0 0 3 ;; #AAD94C #000000 0 0 0 0 3
((program ((program
. .
(comment) @keyword.directive @nospell) (comment) @keyword.directive @nospell)

View File

@@ -2,45 +2,45 @@
; Identifiers ; Identifiers
; ============================================================ ; ============================================================
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
((identifier) @variable) ((identifier) @variable)
;; #FFB870 #000000 0 0 0 9 ;; #FFB870 #000000 0 0 0 0 9
(function_declarator (function_declarator
declarator: (identifier) @function) declarator: (identifier) @function)
;; #C4B5FF #000000 0 0 0 2 ;; #C4B5FF #000000 0 0 0 0 2
((identifier) @constant ((identifier) @constant
(#match? @constant "^[A-Z][A-Z0-9_]+$")) (#match? @constant "^[A-Z][A-Z0-9_]+$"))
;; #C4B5FF #000000 0 0 0 2 ;; #C4B5FF #000000 0 0 0 0 2
(preproc_def (preproc_def
(preproc_arg) @constant (preproc_arg) @constant
(#match? @constant "^[A-Z][A-Z0-9_]+$")) (#match? @constant "^[A-Z][A-Z0-9_]+$"))
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
((identifier) @constant.builtin ((identifier) @constant.builtin
(#match? @constant.builtin "^(stderr|stdin|stdout|__FILE__|__LINE__|__DATE__|__TIME__|__STDC__|__STDC_VERSION__|__STDC_HOSTED__|__cplusplus|__OBJC__|__ASSEMBLER__|__BASE_FILE__|__FILE_NAME__|__INCLUDE_LEVEL__|__TIMESTAMP__|__clang__|__clang_major__|__clang_minor__|__clang_patchlevel__|__clang_version__|__clang_literal_encoding__|__clang_wide_literal_encoding__|__FUNCTION__|__func__|__PRETTY_FUNCTION__|__VA_ARGS__|__VA_OPT__)$")) (#match? @constant.builtin "^(stderr|stdin|stdout|__FILE__|__LINE__|__DATE__|__TIME__|__STDC__|__STDC_VERSION__|__STDC_HOSTED__|__cplusplus|__OBJC__|__ASSEMBLER__|__BASE_FILE__|__FILE_NAME__|__INCLUDE_LEVEL__|__TIMESTAMP__|__clang__|__clang_major__|__clang_minor__|__clang_patchlevel__|__clang_version__|__clang_literal_encoding__|__clang_wide_literal_encoding__|__FUNCTION__|__func__|__PRETTY_FUNCTION__|__VA_ARGS__|__VA_OPT__)$"))
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_def (preproc_def
(preproc_arg) @constant.builtin (preproc_arg) @constant.builtin
(#match? @constant.builtin "^(stderr|stdin|stdout|__FILE__|__LINE__|__DATE__|__TIME__|__STDC__|__STDC_VERSION__|__STDC_HOSTED__|__cplusplus|__OBJC__|__ASSEMBLER__|__BASE_FILE__|__FILE_NAME__|__INCLUDE_LEVEL__|__TIMESTAMP__|__clang__|__clang_major__|__clang_minor__|__clang_patchlevel__|__clang_version__|__clang_literal_encoding__|__clang_wide_literal_encoding__|__FUNCTION__|__func__|__PRETTY_FUNCTION__|__VA_ARGS__|__VA_OPT__)$")) (#match? @constant.builtin "^(stderr|stdin|stdout|__FILE__|__LINE__|__DATE__|__TIME__|__STDC__|__STDC_VERSION__|__STDC_HOSTED__|__cplusplus|__OBJC__|__ASSEMBLER__|__BASE_FILE__|__FILE_NAME__|__INCLUDE_LEVEL__|__TIMESTAMP__|__clang__|__clang_major__|__clang_minor__|__clang_patchlevel__|__clang_version__|__clang_literal_encoding__|__clang_wide_literal_encoding__|__FUNCTION__|__func__|__PRETTY_FUNCTION__|__VA_ARGS__|__VA_OPT__)$"))
;; #8AD5FF #000000 0 0 0 2 ;; #8AD5FF #000000 0 0 0 0 2
(preproc_def (preproc_def
(preproc_arg) @variable) (preproc_arg) @variable)
;; #8AD5FF #000000 0 0 0 2 ;; #8AD5FF #000000 0 0 0 0 2
(statement_identifier) @label (statement_identifier) @label
;; #8AD5FF #000000 0 0 0 2 ;; #8AD5FF #000000 0 0 0 0 2
(declaration (declaration
type: (type_identifier) @_type type: (type_identifier) @_type
declarator: (identifier) @label declarator: (identifier) @label
(#match? @_type "^__label__$")) (#match? @_type "^__label__$"))
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
((identifier) @variable.member ((identifier) @variable.member
(#match? @variable.member "^m_.*$")) (#match? @variable.member "^m_.*$"))
@@ -48,7 +48,7 @@
; Keywords ; Keywords
; ============================================================ ; ============================================================
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"default" "default"
"goto" "goto"
@@ -56,7 +56,7 @@
"__asm__" "__asm__"
] @keyword ] @keyword
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"enum" "enum"
"struct" "struct"
@@ -64,21 +64,21 @@
"typedef" "typedef"
] @keyword.type ] @keyword.type
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
[ [
"sizeof" "sizeof"
"offsetof" "offsetof"
] @keyword.operator ] @keyword.operator
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(alignof_expression (alignof_expression
. .
_ @keyword.operator) _ @keyword.operator)
;; #FFB870 #000000 0 0 0 2 ;; #FFB870 #000000 0 0 0 0 2
"return" @keyword.return "return" @keyword.return
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"while" "while"
"for" "for"
@@ -87,7 +87,7 @@
"break" "break"
] @keyword.repeat ] @keyword.repeat
;; #FFB870 #000000 0 0 0 2 ;; #FFB870 #000000 0 0 0 0 2
[ [
"if" "if"
"else" "else"
@@ -95,14 +95,14 @@
"switch" "switch"
] @keyword.conditional ] @keyword.conditional
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
(conditional_expression (conditional_expression
[ [
"?" "?"
":" ":"
] @keyword.conditional.ternary) ] @keyword.conditional.ternary)
;; #8AD5FF #000000 0 0 0 2 ;; #8AD5FF #000000 0 0 0 0 2
[ [
"#if" "#if"
"#ifdef" "#ifdef"
@@ -115,13 +115,13 @@
(preproc_directive) (preproc_directive)
] @keyword.directive ] @keyword.directive
;; #8AD5FF #000000 0 0 0 2 ;; #8AD5FF #000000 0 0 0 0 2
"#define" @keyword.directive.define "#define" @keyword.directive.define
;; #8AD5FF #000000 0 0 0 2 ;; #8AD5FF #000000 0 0 0 0 2
"#include" @keyword.import "#include" @keyword.import
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"try" "try"
"catch" "catch"
@@ -129,7 +129,7 @@
"throw" "throw"
] @keyword.exception ] @keyword.exception
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"decltype" "decltype"
"explicit" "explicit"
@@ -140,7 +140,7 @@
"constexpr" "constexpr"
] @keyword ] @keyword
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"class" "class"
"namespace" "namespace"
@@ -149,14 +149,14 @@
"concept" "concept"
] @keyword.type ] @keyword.type
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"co_await" "co_await"
"co_yield" "co_yield"
"co_return" "co_return"
] @keyword.coroutine ] @keyword.coroutine
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
[ [
"public" "public"
"private" "private"
@@ -165,21 +165,21 @@
"virtual" "virtual"
] @keyword.modifier ] @keyword.modifier
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(storage_class_specifier) @keyword.modifier (storage_class_specifier) @keyword.modifier
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
[ [
(type_qualifier) (type_qualifier)
(gnu_asm_qualifier) (gnu_asm_qualifier)
"__extension__" "__extension__"
] @keyword.modifier ] @keyword.modifier
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(linkage_specification (linkage_specification
"extern" @keyword.modifier) "extern" @keyword.modifier)
;; #F29668 #000000 0 0 0 2 ;; #F29668 #000000 0 0 0 0 2
[ [
"new" "new"
"delete" "delete"
@@ -196,54 +196,39 @@
"or" "or"
] @keyword.operator ] @keyword.operator
;; #F29668 #000000 0 1 0 2 ;; #F29668 #000000 0 1 0 0 2
"<=>" @operator "<=>" @operator
; ============================================================ ; ============================================================
; Types & modules ; Types & modules
; ============================================================ ; ============================================================
;; #C4B5FF #000000 0 0 0 2 ;; #C4B5FF #000000 0 0 0 0 2
[ [
(type_identifier) (type_identifier)
(type_descriptor) (type_descriptor)
] @type ] @type
;; #C4B5FF #000000 0 0 0 2 ;; #C4B5FF #000000 0 0 0 0 2
(type_definition (type_definition
declarator: (type_identifier) @type.definition) declarator: (type_identifier) @type.definition)
;; #C4B5FF #000000 0 0 0 2 ;; #C4B5FF #000000 0 0 0 0 2
(primitive_type) @type.builtin (primitive_type) @type.builtin
;; #C4B5FF #000000 0 0 0 2 ;; #C4B5FF #000000 0 0 0 0 2
(sized_type_specifier (sized_type_specifier
_ @type.builtin _ @type.builtin
type: _?) type: _?)
;; #C4B5FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
(type_definition declarator: (type_identifier) @name) @definition.type
;; #C4B5FF #000000 0 0 0 2
(enum_specifier name: (type_identifier) @name) @definition.type
;; #C4B5FF #000000 0 0 0 2
(class_specifier name: (type_identifier) @name) @definition.class
;; #C4B5FF #000000 0 0 0 2
(struct_specifier name: (type_identifier) @name body:(_)) @definition.class
;; #C4B5FF #000000 0 0 0 2
(declaration type: (union_specifier name: (type_identifier) @name)) @definition.class
;; #9AD4FF #000000 0 0 0 2
(namespace_identifier) @module (namespace_identifier) @module
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
((namespace_identifier) @type ((namespace_identifier) @type
(#match? @type "^[A-Z]")) (#match? @type "^[A-Z]"))
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
(using_declaration (using_declaration
. .
"using" "using"
@@ -259,22 +244,22 @@
; Functions & calls ; Functions & calls
; ============================================================ ; ============================================================
;; #FFB870 #000000 0 0 0 1 ;; #FFB870 #000000 0 0 0 0 1
(operator_name) @function (operator_name) @function
;; #FFB870 #000000 0 0 0 3 ;; #FFB870 #000000 0 0 0 0 3
"operator" @function "operator" @function
;; #78C2FF #000000 0 0 0 2 ;; #78C2FF #000000 0 0 0 0 2
(call_expression (call_expression
function: (identifier) @function.call) function: (identifier) @function.call)
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
((call_expression ((call_expression
function: (identifier) @function.builtin) function: (identifier) @function.builtin)
(#match? @function.builtin "^__builtin_")) (#match? @function.builtin "^__builtin_"))
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
((call_expression ((call_expression
function: (identifier) @function.builtin)) function: (identifier) @function.builtin))
@@ -282,30 +267,30 @@
; Constructors & methods ; Constructors & methods
; ============================================================ ; ============================================================
;; #59C2FF #000000 0 0 0 2 ;; #59C2FF #000000 0 0 0 0 2
((call_expression ((call_expression
function: (identifier) @constructor) function: (identifier) @constructor)
(#match? @constructor "^[A-Z]")) (#match? @constructor "^[A-Z]"))
;; #59C2FF #000000 0 0 0 2 ;; #59C2FF #000000 0 0 0 0 2
((call_expression ((call_expression
function: (qualified_identifier function: (qualified_identifier
name: (identifier) @constructor)) name: (identifier) @constructor))
(#match? @constructor "^[A-Z]")) (#match? @constructor "^[A-Z]"))
;; #59C2FF #000000 0 0 0 2 ;; #59C2FF #000000 0 0 0 0 2
((call_expression ((call_expression
function: (field_expression function: (field_expression
field: (field_identifier) @constructor)) field: (field_identifier) @constructor))
(#match? @constructor "^[A-Z]")) (#match? @constructor "^[A-Z]"))
;; #59C2FF #000000 0 0 0 2 ;; #59C2FF #000000 0 0 0 0 2
((field_initializer ((field_initializer
(field_identifier) @constructor (field_identifier) @constructor
(argument_list)) (argument_list))
(#match? @constructor "^[A-Z]")) (#match? @constructor "^[A-Z]"))
;; #59C2FF #000000 0 0 0 4 ;; #59C2FF #000000 0 0 0 0 4
(destructor_name (destructor_name
(identifier) @function.method) (identifier) @function.method)
@@ -313,7 +298,7 @@
; Properties & members ; Properties & members
; ============================================================ ; ============================================================
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
((field_expression ((field_expression
(field_identifier) @property) @_parent) (field_identifier) @property) @_parent)
@@ -324,7 +309,7 @@
(field_initializer (field_initializer
(field_identifier) @property) (field_identifier) @property)
;; #F29CC3 #000000 0 0 1 2 ;; #F29CC3 #000000 0 0 1 0 2
(field_declaration (field_declaration
(field_identifier) @variable.member) (field_identifier) @variable.member)
@@ -332,32 +317,32 @@
; Parameters ; Parameters
; ============================================================ ; ============================================================
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(parameter_declaration (parameter_declaration
declarator: (identifier) @variable.parameter) declarator: (identifier) @variable.parameter)
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(parameter_declaration (parameter_declaration
declarator: (array_declarator) @variable.parameter) declarator: (array_declarator) @variable.parameter)
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(parameter_declaration (parameter_declaration
declarator: (pointer_declarator) @variable.parameter) declarator: (pointer_declarator) @variable.parameter)
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(preproc_params (preproc_params
(identifier) @variable.parameter) (identifier) @variable.parameter)
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(parameter_declaration (parameter_declaration
declarator: (reference_declarator) @variable.parameter) declarator: (reference_declarator) @variable.parameter)
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(variadic_parameter_declaration (variadic_parameter_declaration
declarator: (variadic_declarator declarator: (variadic_declarator
(_) @variable.parameter)) (_) @variable.parameter))
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(optional_parameter_declaration (optional_parameter_declaration
declarator: (_) @variable.parameter) declarator: (_) @variable.parameter)
@@ -365,7 +350,7 @@
; Attributes & specifiers ; Attributes & specifiers
; ============================================================ ; ============================================================
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
[ [
"__attribute__" "__attribute__"
"__declspec" "__declspec"
@@ -380,12 +365,12 @@
(attribute_declaration) (attribute_declaration)
] @attribute ] @attribute
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(attribute_specifier (attribute_specifier
(argument_list (argument_list
(identifier) @variable.builtin)) (identifier) @variable.builtin))
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(attribute_specifier (attribute_specifier
(argument_list (argument_list
(call_expression (call_expression
@@ -395,7 +380,7 @@
; Operators & punctuation ; Operators & punctuation
; ============================================================ ; ============================================================
;; #F29668 #000000 0 1 0 1 ;; #F29668 #000000 0 1 0 0 1
[ [
"=" "="
"-" "-"
@@ -433,11 +418,11 @@
"++" "++"
] @operator ] @operator
;; #F29668 #000000 0 1 0 1 ;; #F29668 #000000 0 1 0 0 1
(comma_expression (comma_expression
"," @operator) "," @operator)
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
[ [
";" ";"
":" ":"
@@ -446,13 +431,13 @@
"::" "::"
] @punctuation.delimiter ] @punctuation.delimiter
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
"::" @punctuation.delimiter "::" @punctuation.delimiter
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
"..." @punctuation.special "..." @punctuation.special
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
[ [
"(" "("
")" ")"
@@ -462,14 +447,14 @@
"}" "}"
] @punctuation.bracket ] @punctuation.bracket
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
(template_argument_list (template_argument_list
[ [
"<" "<"
">" ">"
] @punctuation.bracket) ] @punctuation.bracket)
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
(template_parameter_list (template_parameter_list
[ [
"<" "<"
@@ -480,40 +465,40 @@
; Literals ; Literals
; ============================================================ ; ============================================================
;; #C2E8FF #000000 0 0 0 2 ;; #C2E8FF #000000 0 0 0 0 2
[ [
(true) (true)
(false) (false)
] @boolean ] @boolean
;; #C2E8FF #000000 0 0 0 2 ;; #C2E8FF #000000 0 0 0 0 2
(true) @boolean_true (true) @boolean_true
;; #C2E8FF #000000 0 0 0 2 ;; #C2E8FF #000000 0 0 0 0 2
(false) @boolean_false (false) @boolean_false
;; #A6E3A1 #000000 0 0 0 2 ;; #A6E3A1 #000000 0 0 0 0 2
(string_literal) @string (string_literal) @string
;; #A6E3A1 #000000 0 0 0 2 ;; #A6E3A1 #000000 0 0 0 0 2
(system_lib_string) @string (system_lib_string) @string
;; #A6E3A1 #000000 0 0 0 2 ;; #A6E3A1 #000000 0 0 0 0 2
(raw_string_literal) @string (raw_string_literal) @string
;; #A6E3A1 #000000 0 0 0 2 ;; #A6E3A1 #000000 0 0 0 0 2
(escape_sequence) @string.escape (escape_sequence) @string.escape
;; #B8E986 #000000 0 0 0 2 ;; #B8E986 #000000 0 0 0 0 2
(number_literal) @number (number_literal) @number
;; #B8E986 #000000 0 0 0 2 ;; #B8E986 #000000 0 0 0 0 2
(char_literal) @character (char_literal) @character
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(null) @constant.builtin (null) @constant.builtin
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(null (null
"nullptr" @constant.builtin) "nullptr" @constant.builtin)
@@ -521,59 +506,59 @@
; Macros & directives ; Macros & directives
; ============================================================ ; ============================================================
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_def (preproc_def
name: (_) @constant.macro) name: (_) @constant.macro)
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_call (preproc_call
directive: (preproc_directive) @_u directive: (preproc_directive) @_u
argument: (_) @constant.macro argument: (_) @constant.macro
(#match? @_u "^#undef$")) (#match? @_u "^#undef$"))
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_ifdef (preproc_ifdef
name: (identifier) @constant.macro) name: (identifier) @constant.macro)
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_elifdef (preproc_elifdef
name: (identifier) @constant.macro) name: (identifier) @constant.macro)
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_defined (preproc_defined
(identifier) @constant.macro) (identifier) @constant.macro)
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_defined) @function.macro (preproc_defined) @function.macro
; ============================================================ ; ============================================================
; Builtins & special identifiers ; Builtins & special identifiers
; ============================================================ ; ============================================================
;; #F28FAD #000000 0 0 0 2 ;; #F28FAD #000000 0 0 0 0 2
(attribute_specifier (attribute_specifier
(argument_list (argument_list
(identifier) @variable.builtin)) (identifier) @variable.builtin))
;; #F28FAD #000000 0 0 0 2 ;; #F28FAD #000000 0 0 0 0 2
(attribute_specifier (attribute_specifier
(argument_list (argument_list
(call_expression (call_expression
function: (identifier) @variable.builtin))) function: (identifier) @variable.builtin)))
;; #F28FAD #000000 0 0 0 2 ;; #F28FAD #000000 0 0 0 0 2
(this) @variable.builtin (this) @variable.builtin
; ============================================================ ; ============================================================
; Exceptions & control helpers ; Exceptions & control helpers
; ============================================================ ; ============================================================
;; #FFB870 #000000 0 0 0 2 ;; #FFB870 #000000 0 0 0 0 2
"static_assert" @function.builtin "static_assert" @function.builtin
; ============================================================ ; ============================================================
; Comments ; Comments
; ============================================================ ; ============================================================
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment @spell (comment) @comment @spell

View File

@@ -2,45 +2,45 @@
; Identifiers ; Identifiers
; ============================================================ ; ============================================================
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
((identifier) @variable) ((identifier) @variable)
;; #FFB870 #000000 0 0 0 9 ;; #FFB870 #000000 0 0 0 0 9
(function_declarator (function_declarator
declarator: (identifier) @function) declarator: (identifier) @function)
;; #C4B5FF #000000 0 0 0 2 ;; #C4B5FF #000000 0 0 0 0 2
((identifier) @constant ((identifier) @constant
(#match? @constant "^[A-Z][A-Z0-9_]+$")) (#match? @constant "^[A-Z][A-Z0-9_]+$"))
;; #C4B5FF #000000 0 0 0 2 ;; #C4B5FF #000000 0 0 0 0 2
(preproc_def (preproc_def
(preproc_arg) @constant (preproc_arg) @constant
(#match? @constant "^[A-Z][A-Z0-9_]+$")) (#match? @constant "^[A-Z][A-Z0-9_]+$"))
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
((identifier) @constant.builtin ((identifier) @constant.builtin
(#match? @constant.builtin "^(stderr|stdin|stdout|__FILE__|__LINE__|__DATE__|__TIME__|__STDC__|__STDC_VERSION__|__STDC_HOSTED__|__cplusplus|__OBJC__|__ASSEMBLER__|__BASE_FILE__|__FILE_NAME__|__INCLUDE_LEVEL__|__TIMESTAMP__|__clang__|__clang_major__|__clang_minor__|__clang_patchlevel__|__clang_version__|__clang_literal_encoding__|__clang_wide_literal_encoding__|__FUNCTION__|__func__|__PRETTY_FUNCTION__|__VA_ARGS__|__VA_OPT__)$")) (#match? @constant.builtin "^(stderr|stdin|stdout|__FILE__|__LINE__|__DATE__|__TIME__|__STDC__|__STDC_VERSION__|__STDC_HOSTED__|__cplusplus|__OBJC__|__ASSEMBLER__|__BASE_FILE__|__FILE_NAME__|__INCLUDE_LEVEL__|__TIMESTAMP__|__clang__|__clang_major__|__clang_minor__|__clang_patchlevel__|__clang_version__|__clang_literal_encoding__|__clang_wide_literal_encoding__|__FUNCTION__|__func__|__PRETTY_FUNCTION__|__VA_ARGS__|__VA_OPT__)$"))
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_def (preproc_def
(preproc_arg) @constant.builtin (preproc_arg) @constant.builtin
(#match? @constant.builtin "^(stderr|stdin|stdout|__FILE__|__LINE__|__DATE__|__TIME__|__STDC__|__STDC_VERSION__|__STDC_HOSTED__|__cplusplus|__OBJC__|__ASSEMBLER__|__BASE_FILE__|__FILE_NAME__|__INCLUDE_LEVEL__|__TIMESTAMP__|__clang__|__clang_major__|__clang_minor__|__clang_patchlevel__|__clang_version__|__clang_literal_encoding__|__clang_wide_literal_encoding__|__FUNCTION__|__func__|__PRETTY_FUNCTION__|__VA_ARGS__|__VA_OPT__)$")) (#match? @constant.builtin "^(stderr|stdin|stdout|__FILE__|__LINE__|__DATE__|__TIME__|__STDC__|__STDC_VERSION__|__STDC_HOSTED__|__cplusplus|__OBJC__|__ASSEMBLER__|__BASE_FILE__|__FILE_NAME__|__INCLUDE_LEVEL__|__TIMESTAMP__|__clang__|__clang_major__|__clang_minor__|__clang_patchlevel__|__clang_version__|__clang_literal_encoding__|__clang_wide_literal_encoding__|__FUNCTION__|__func__|__PRETTY_FUNCTION__|__VA_ARGS__|__VA_OPT__)$"))
;; #8AD5FF #000000 0 0 0 2 ;; #8AD5FF #000000 0 0 0 0 2
(preproc_def (preproc_def
(preproc_arg) @variable) (preproc_arg) @variable)
;; #8AD5FF #000000 0 0 0 2 ;; #8AD5FF #000000 0 0 0 0 2
(statement_identifier) @label (statement_identifier) @label
;; #8AD5FF #000000 0 0 0 2 ;; #8AD5FF #000000 0 0 0 0 2
(declaration (declaration
type: (type_identifier) @_type type: (type_identifier) @_type
declarator: (identifier) @label declarator: (identifier) @label
(#match? @_type "^__label__$")) (#match? @_type "^__label__$"))
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
((identifier) @variable.member ((identifier) @variable.member
(#match? @variable.member "^m_.*$")) (#match? @variable.member "^m_.*$"))
@@ -48,7 +48,7 @@
; Keywords ; Keywords
; ============================================================ ; ============================================================
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"default" "default"
"goto" "goto"
@@ -56,7 +56,7 @@
"__asm__" "__asm__"
] @keyword ] @keyword
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"enum" "enum"
"struct" "struct"
@@ -64,21 +64,21 @@
"typedef" "typedef"
] @keyword.type ] @keyword.type
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
[ [
"sizeof" "sizeof"
"offsetof" "offsetof"
] @keyword.operator ] @keyword.operator
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(alignof_expression (alignof_expression
. .
_ @keyword.operator) _ @keyword.operator)
;; #FFB870 #000000 0 0 0 2 ;; #FFB870 #000000 0 0 0 0 2
"return" @keyword.return "return" @keyword.return
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"while" "while"
"for" "for"
@@ -87,7 +87,7 @@
"break" "break"
] @keyword.repeat ] @keyword.repeat
;; #FFB870 #000000 0 0 0 2 ;; #FFB870 #000000 0 0 0 0 2
[ [
"if" "if"
"else" "else"
@@ -95,14 +95,14 @@
"switch" "switch"
] @keyword.conditional ] @keyword.conditional
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
(conditional_expression (conditional_expression
[ [
"?" "?"
":" ":"
] @keyword.conditional.ternary) ] @keyword.conditional.ternary)
;; #8AD5FF #000000 0 0 0 2 ;; #8AD5FF #000000 0 0 0 0 2
[ [
"#if" "#if"
"#ifdef" "#ifdef"
@@ -115,13 +115,13 @@
(preproc_directive) (preproc_directive)
] @keyword.directive ] @keyword.directive
;; #8AD5FF #000000 0 0 0 2 ;; #8AD5FF #000000 0 0 0 0 2
"#define" @keyword.directive.define "#define" @keyword.directive.define
;; #8AD5FF #000000 0 0 0 2 ;; #8AD5FF #000000 0 0 0 0 2
"#include" @keyword.import "#include" @keyword.import
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"try" "try"
"catch" "catch"
@@ -129,7 +129,7 @@
"throw" "throw"
] @keyword.exception ] @keyword.exception
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"decltype" "decltype"
"explicit" "explicit"
@@ -140,7 +140,7 @@
"constexpr" "constexpr"
] @keyword ] @keyword
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"class" "class"
"namespace" "namespace"
@@ -149,14 +149,14 @@
"concept" "concept"
] @keyword.type ] @keyword.type
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"co_await" "co_await"
"co_yield" "co_yield"
"co_return" "co_return"
] @keyword.coroutine ] @keyword.coroutine
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
[ [
"public" "public"
"private" "private"
@@ -165,21 +165,21 @@
"virtual" "virtual"
] @keyword.modifier ] @keyword.modifier
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(storage_class_specifier) @keyword.modifier (storage_class_specifier) @keyword.modifier
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
[ [
(type_qualifier) (type_qualifier)
(gnu_asm_qualifier) (gnu_asm_qualifier)
"__extension__" "__extension__"
] @keyword.modifier ] @keyword.modifier
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(linkage_specification (linkage_specification
"extern" @keyword.modifier) "extern" @keyword.modifier)
;; #F29668 #000000 0 0 0 2 ;; #F29668 #000000 0 0 0 0 2
[ [
"new" "new"
"delete" "delete"
@@ -196,54 +196,39 @@
"or" "or"
] @keyword.operator ] @keyword.operator
;; #F29668 #000000 0 1 0 2 ;; #F29668 #000000 0 1 0 0 2
"<=>" @operator "<=>" @operator
; ============================================================ ; ============================================================
; Types & modules ; Types & modules
; ============================================================ ; ============================================================
;; #C4B5FF #000000 0 0 0 2 ;; #C4B5FF #000000 0 0 0 0 2
[ [
(type_identifier) (type_identifier)
(type_descriptor) (type_descriptor)
] @type ] @type
;; #C4B5FF #000000 0 0 0 2 ;; #C4B5FF #000000 0 0 0 0 2
(type_definition (type_definition
declarator: (type_identifier) @type.definition) declarator: (type_identifier) @type.definition)
;; #C4B5FF #000000 0 0 0 2 ;; #C4B5FF #000000 0 0 0 0 2
(primitive_type) @type.builtin (primitive_type) @type.builtin
;; #C4B5FF #000000 0 0 0 2 ;; #C4B5FF #000000 0 0 0 0 2
(sized_type_specifier (sized_type_specifier
_ @type.builtin _ @type.builtin
type: _?) type: _?)
;; #C4B5FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
(type_definition declarator: (type_identifier) @name) @definition.type
;; #C4B5FF #000000 0 0 0 2
(enum_specifier name: (type_identifier) @name) @definition.type
;; #C4B5FF #000000 0 0 0 2
(class_specifier name: (type_identifier) @name) @definition.class
;; #C4B5FF #000000 0 0 0 2
(struct_specifier name: (type_identifier) @name body:(_)) @definition.class
;; #C4B5FF #000000 0 0 0 2
(declaration type: (union_specifier name: (type_identifier) @name)) @definition.class
;; #9AD4FF #000000 0 0 0 2
(namespace_identifier) @module (namespace_identifier) @module
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
((namespace_identifier) @type ((namespace_identifier) @type
(#match? @type "^[A-Z]")) (#match? @type "^[A-Z]"))
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
(using_declaration (using_declaration
. .
"using" "using"
@@ -259,22 +244,22 @@
; Functions & calls ; Functions & calls
; ============================================================ ; ============================================================
;; #FFB870 #000000 0 0 0 1 ;; #FFB870 #000000 0 0 0 0 1
(operator_name) @function (operator_name) @function
;; #FFB870 #000000 0 0 0 3 ;; #FFB870 #000000 0 0 0 0 3
"operator" @function "operator" @function
;; #78C2FF #000000 0 0 0 2 ;; #78C2FF #000000 0 0 0 0 2
(call_expression (call_expression
function: (identifier) @function.call) function: (identifier) @function.call)
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
((call_expression ((call_expression
function: (identifier) @function.builtin) function: (identifier) @function.builtin)
(#match? @function.builtin "^__builtin_")) (#match? @function.builtin "^__builtin_"))
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
((call_expression ((call_expression
function: (identifier) @function.builtin)) function: (identifier) @function.builtin))
@@ -282,30 +267,30 @@
; Constructors & methods ; Constructors & methods
; ============================================================ ; ============================================================
;; #59C2FF #000000 0 0 0 2 ;; #59C2FF #000000 0 0 0 0 2
((call_expression ((call_expression
function: (identifier) @constructor) function: (identifier) @constructor)
(#match? @constructor "^[A-Z]")) (#match? @constructor "^[A-Z]"))
;; #59C2FF #000000 0 0 0 2 ;; #59C2FF #000000 0 0 0 0 2
((call_expression ((call_expression
function: (qualified_identifier function: (qualified_identifier
name: (identifier) @constructor)) name: (identifier) @constructor))
(#match? @constructor "^[A-Z]")) (#match? @constructor "^[A-Z]"))
;; #59C2FF #000000 0 0 0 2 ;; #59C2FF #000000 0 0 0 0 2
((call_expression ((call_expression
function: (field_expression function: (field_expression
field: (field_identifier) @constructor)) field: (field_identifier) @constructor))
(#match? @constructor "^[A-Z]")) (#match? @constructor "^[A-Z]"))
;; #59C2FF #000000 0 0 0 2 ;; #59C2FF #000000 0 0 0 0 2
((field_initializer ((field_initializer
(field_identifier) @constructor (field_identifier) @constructor
(argument_list)) (argument_list))
(#match? @constructor "^[A-Z]")) (#match? @constructor "^[A-Z]"))
;; #59C2FF #000000 0 0 0 4 ;; #59C2FF #000000 0 0 0 0 4
(destructor_name (destructor_name
(identifier) @function.method) (identifier) @function.method)
@@ -313,7 +298,7 @@
; Properties & members ; Properties & members
; ============================================================ ; ============================================================
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
((field_expression ((field_expression
(field_identifier) @property) @_parent) (field_identifier) @property) @_parent)
@@ -324,7 +309,7 @@
(field_initializer (field_initializer
(field_identifier) @property) (field_identifier) @property)
;; #F29CC3 #000000 0 0 1 2 ;; #F29CC3 #000000 0 0 1 0 2
(field_declaration (field_declaration
(field_identifier) @variable.member) (field_identifier) @variable.member)
@@ -332,32 +317,32 @@
; Parameters ; Parameters
; ============================================================ ; ============================================================
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(parameter_declaration (parameter_declaration
declarator: (identifier) @variable.parameter) declarator: (identifier) @variable.parameter)
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(parameter_declaration (parameter_declaration
declarator: (array_declarator) @variable.parameter) declarator: (array_declarator) @variable.parameter)
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(parameter_declaration (parameter_declaration
declarator: (pointer_declarator) @variable.parameter) declarator: (pointer_declarator) @variable.parameter)
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(preproc_params (preproc_params
(identifier) @variable.parameter) (identifier) @variable.parameter)
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(parameter_declaration (parameter_declaration
declarator: (reference_declarator) @variable.parameter) declarator: (reference_declarator) @variable.parameter)
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(variadic_parameter_declaration (variadic_parameter_declaration
declarator: (variadic_declarator declarator: (variadic_declarator
(_) @variable.parameter)) (_) @variable.parameter))
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(optional_parameter_declaration (optional_parameter_declaration
declarator: (_) @variable.parameter) declarator: (_) @variable.parameter)
@@ -365,7 +350,7 @@
; Attributes & specifiers ; Attributes & specifiers
; ============================================================ ; ============================================================
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
[ [
"__attribute__" "__attribute__"
"__declspec" "__declspec"
@@ -380,12 +365,12 @@
(attribute_declaration) (attribute_declaration)
] @attribute ] @attribute
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(attribute_specifier (attribute_specifier
(argument_list (argument_list
(identifier) @variable.builtin)) (identifier) @variable.builtin))
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(attribute_specifier (attribute_specifier
(argument_list (argument_list
(call_expression (call_expression
@@ -395,7 +380,7 @@
; Operators & punctuation ; Operators & punctuation
; ============================================================ ; ============================================================
;; #F29668 #000000 0 1 0 1 ;; #F29668 #000000 0 1 0 0 1
[ [
"=" "="
"-" "-"
@@ -433,11 +418,11 @@
"++" "++"
] @operator ] @operator
;; #F29668 #000000 0 1 0 1 ;; #F29668 #000000 0 1 0 0 1
(comma_expression (comma_expression
"," @operator) "," @operator)
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
[ [
";" ";"
":" ":"
@@ -446,13 +431,13 @@
"::" "::"
] @punctuation.delimiter ] @punctuation.delimiter
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
"::" @punctuation.delimiter "::" @punctuation.delimiter
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
"..." @punctuation.special "..." @punctuation.special
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
[ [
"(" "("
")" ")"
@@ -462,14 +447,14 @@
"}" "}"
] @punctuation.bracket ] @punctuation.bracket
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
(template_argument_list (template_argument_list
[ [
"<" "<"
">" ">"
] @punctuation.bracket) ] @punctuation.bracket)
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
(template_parameter_list (template_parameter_list
[ [
"<" "<"
@@ -480,40 +465,40 @@
; Literals ; Literals
; ============================================================ ; ============================================================
;; #C2E8FF #000000 0 0 0 2 ;; #C2E8FF #000000 0 0 0 0 2
[ [
(true) (true)
(false) (false)
] @boolean ] @boolean
;; #C2E8FF #000000 0 0 0 2 ;; #C2E8FF #000000 0 0 0 0 2
(true) @boolean_true (true) @boolean_true
;; #C2E8FF #000000 0 0 0 2 ;; #C2E8FF #000000 0 0 0 0 2
(false) @boolean_false (false) @boolean_false
;; #A6E3A1 #000000 0 0 0 2 ;; #A6E3A1 #000000 0 0 0 0 2
(string_literal) @string (string_literal) @string
;; #A6E3A1 #000000 0 0 0 2 ;; #A6E3A1 #000000 0 0 0 0 2
(system_lib_string) @string (system_lib_string) @string
;; #A6E3A1 #000000 0 0 0 2 ;; #A6E3A1 #000000 0 0 0 0 2
(raw_string_literal) @string (raw_string_literal) @string
;; #A6E3A1 #000000 0 0 0 2 ;; #A6E3A1 #000000 0 0 0 0 2
(escape_sequence) @string.escape (escape_sequence) @string.escape
;; #B8E986 #000000 0 0 0 2 ;; #B8E986 #000000 0 0 0 0 2
(number_literal) @number (number_literal) @number
;; #B8E986 #000000 0 0 0 2 ;; #B8E986 #000000 0 0 0 0 2
(char_literal) @character (char_literal) @character
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(null) @constant.builtin (null) @constant.builtin
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(null (null
"nullptr" @constant.builtin) "nullptr" @constant.builtin)
@@ -521,59 +506,59 @@
; Macros & directives ; Macros & directives
; ============================================================ ; ============================================================
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_def (preproc_def
name: (_) @constant.macro) name: (_) @constant.macro)
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_call (preproc_call
directive: (preproc_directive) @_u directive: (preproc_directive) @_u
argument: (_) @constant.macro argument: (_) @constant.macro
(#match? @_u "^#undef$")) (#match? @_u "^#undef$"))
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_ifdef (preproc_ifdef
name: (identifier) @constant.macro) name: (identifier) @constant.macro)
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_elifdef (preproc_elifdef
name: (identifier) @constant.macro) name: (identifier) @constant.macro)
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_defined (preproc_defined
(identifier) @constant.macro) (identifier) @constant.macro)
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_defined) @function.macro (preproc_defined) @function.macro
; ============================================================ ; ============================================================
; Builtins & special identifiers ; Builtins & special identifiers
; ============================================================ ; ============================================================
;; #F28FAD #000000 0 0 0 2 ;; #F28FAD #000000 0 0 0 0 2
(attribute_specifier (attribute_specifier
(argument_list (argument_list
(identifier) @variable.builtin)) (identifier) @variable.builtin))
;; #F28FAD #000000 0 0 0 2 ;; #F28FAD #000000 0 0 0 0 2
(attribute_specifier (attribute_specifier
(argument_list (argument_list
(call_expression (call_expression
function: (identifier) @variable.builtin))) function: (identifier) @variable.builtin)))
;; #F28FAD #000000 0 0 0 2 ;; #F28FAD #000000 0 0 0 0 2
(this) @variable.builtin (this) @variable.builtin
; ============================================================ ; ============================================================
; Exceptions & control helpers ; Exceptions & control helpers
; ============================================================ ; ============================================================
;; #FFB870 #000000 0 0 0 2 ;; #FFB870 #000000 0 0 0 0 2
"static_assert" @function.builtin "static_assert" @function.builtin
; ============================================================ ; ============================================================
; Comments ; Comments
; ============================================================ ; ============================================================
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment @spell (comment) @comment @spell

View File

@@ -1,9 +1,9 @@
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(tag_name) @tag (tag_name) @tag
(nesting_selector) @tag (nesting_selector) @tag
(universal_selector) @tag (universal_selector) @tag
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
"~" @operator "~" @operator
">" @operator ">" @operator
"+" @operator "+" @operator
@@ -21,45 +21,45 @@
"not" @operator "not" @operator
"only" @operator "only" @operator
;; #AAD94C #000000 0 0 0 2 ;; #AAD94C #000000 0 0 0 0 2
(attribute_selector (plain_value) @string) (attribute_selector (plain_value) @string)
(string_value) @string (string_value) @string
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
((property_name) @variable ((property_name) @variable
(#match? @variable "^--")) (#match? @variable "^--"))
((plain_value) @variable ((plain_value) @variable
(#match? @variable "^--")) (#match? @variable "^--"))
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(class_name) @property (class_name) @property
(id_name) @property (id_name) @property
(namespace_name) @property (namespace_name) @property
(property_name) @property (property_name) @property
(feature_name) @property (feature_name) @property
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
(pseudo_element_selector (tag_name) @attribute) (pseudo_element_selector (tag_name) @attribute)
(pseudo_class_selector (class_name) @attribute) (pseudo_class_selector (class_name) @attribute)
(attribute_name) @attribute (attribute_name) @attribute
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
(function_name) @function (function_name) @function
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment (comment) @comment
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(color_value) @string.special (color_value) @string.special
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
(integer_value) @number (integer_value) @number
(float_value) @number (float_value) @number
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
(unit) @type (unit) @type
;; #AAD94C #000000 0 0 0 3 ;; #AAD94C #000000 0 0 0 0 3
[ [
"#" "#"
"," ","
@@ -69,7 +69,7 @@
";" ";"
] @punctuation.delimiter ] @punctuation.delimiter
;; #AAD94C #000000 0 0 0 3 ;; #AAD94C #000000 0 0 0 0 3
[ [
"{" "{"
"}" "}"
@@ -79,7 +79,7 @@
"]" "]"
] @punctuation.bracket ] @punctuation.bracket
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(at_keyword) @keyword (at_keyword) @keyword
(to) @keyword (to) @keyword
(from) @keyword (from) @keyword

View File

@@ -1,33 +1,33 @@
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment @spell (comment) @comment @spell
;; #A6E3A1 #000000 0 0 0 2 ;; #A6E3A1 #000000 0 0 0 0 2
(addition) @diff.plus (addition) @diff.plus
;; #F07178 #000000 0 0 0 2 ;; #F07178 #000000 0 0 0 0 2
(deletion) @diff.minus (deletion) @diff.minus
;; #D2A6FF #000000 0 0 0 0 ;; #D2A6FF #000000 0 0 0 0 0
[ [
(new_file) (new_file)
(old_file) (old_file)
] @file ] @file
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(commit) @constant (commit) @constant
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(location) @attribute (location) @attribute
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(command (command
"diff" @function "diff" @function
(argument) @variable.parameter) (argument) @variable.parameter)
;; #7dcfff #000000 0 0 0 6 ;; #7dcfff #000000 0 0 0 0 6
(mode) @number (mode) @number
;; #888888 #000000 0 0 0 3 ;; #888888 #000000 0 0 0 0 3
[ [
".." ".."
"+" "+"
@@ -40,18 +40,18 @@
"----" "----"
] @punctuation.special ] @punctuation.special
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
[ [
(binary_change) (binary_change)
(similarity) (similarity)
(file_change) (file_change)
] @label ] @label
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(index (index
"index" @keyword) "index" @keyword)
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
(similarity (similarity
(score) @number (score) @number
"%" @number) "%" @number)

View File

@@ -1,7 +1,7 @@
;; #99ADBF #000000 0 1 0 4 ;; #99ADBF #000000 0 1 0 0 4
(comment_directive) @comment (comment_directive) @comment
;; #F29668 #000000 0 0 0 6 ;; #F29668 #000000 0 0 0 0 6
[ [
"<%#" "<%#"
"<%" "<%"

View File

@@ -1,4 +1,4 @@
;; #F29668 #000000 0 1 0 1 ;; #F29668 #000000 0 1 0 0 1
[ [
"&&" "&&"
"||" "||"
@@ -15,7 +15,7 @@
(command (command
name: (word) @function.builtin name: (word) @function.builtin
(#match? @function.builtin "^test$") (#match? @function.builtin "^test$")
;; #FFFFFF #000000 0 0 0 3 ;; #FFFFFF #000000 0 0 0 0 3
argument: (word) @word argument: (word) @word
(#match? @word "^(!?=|-[a-zA-Z]+)$")) (#match? @word "^(!?=|-[a-zA-Z]+)$"))
@@ -25,36 +25,36 @@
argument: (word) @word argument: (word) @word
(#match? @word "^(!?=|-[a-zA-Z]+)$")) (#match? @word "^(!?=|-[a-zA-Z]+)$"))
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
[ [
"not" "not"
"and" "and"
"or" "or"
] @keyword.operator ] @keyword.operator
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
(if_statement (if_statement
[ [
"if" "if"
"end" "end"
] @keyword.conditional) ] @keyword.conditional)
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
(switch_statement (switch_statement
[ [
"switch" "switch"
"end" "end"
] @keyword.conditional) ] @keyword.conditional)
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
(case_clause (case_clause
"case" @keyword.conditional) "case" @keyword.conditional)
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
(else_clause (else_clause
"else" @keyword.conditional) "else" @keyword.conditional)
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
(else_if_clause (else_if_clause
[ [
"else" "else"
@@ -62,21 +62,21 @@
] @keyword.conditional) ] @keyword.conditional)
; Loops/Blocks ; Loops/Blocks
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
(while_statement (while_statement
[ [
"while" "while"
"end" "end"
] @keyword.repeat) ] @keyword.repeat)
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
(for_statement (for_statement
[ [
"for" "for"
"end" "end"
] @keyword.repeat) ] @keyword.repeat)
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
(begin_statement (begin_statement
[ [
"begin" "begin"
@@ -84,17 +84,17 @@
] @keyword.repeat) ] @keyword.repeat)
; Keywords ; Keywords
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"in" "in"
(break) (break)
(continue) (continue)
] @keyword ] @keyword
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
"return" @keyword.return "return" @keyword.return
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
[ [
"[" "["
"]" "]"
@@ -104,38 +104,38 @@
")" ")"
] @punctuation.bracket ] @punctuation.bracket
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
"," @punctuation.delimiter "," @punctuation.delimiter
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(command_substitution (command_substitution
"$" @punctuation.special) "$" @punctuation.special)
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(command (command
name: (word) @function.call) name: (word) @function.call)
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(command (command
name: (word) @function.builtin name: (word) @function.builtin
(#match? @function.builtin (#match? @function.builtin
"^(\\.|:|_|abbr|alias|argparse|bg|bind|block|breakpoint|builtin|cd|command|commandline|complete|contains|count|disown|echo|emit|eval|exec|exit|fg|functions|history|isatty|jobs|math|path|printf|pwd|random|read|realpath|set|set_color|source|status|string|test|time|type|ulimit|wait)$")) "^(\\.|:|_|abbr|alias|argparse|bg|bind|block|breakpoint|builtin|cd|command|commandline|complete|contains|count|disown|echo|emit|eval|exec|exit|fg|functions|history|isatty|jobs|math|path|printf|pwd|random|read|realpath|set|set_color|source|status|string|test|time|type|ulimit|wait)$"))
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
(function_definition (function_definition
[ [
"function" "function"
"end" "end"
] @keyword.function) ] @keyword.function)
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(function_definition (function_definition
name: [ name: [
(word) (word)
(concatenation) (concatenation)
] @function) ] @function)
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(function_definition (function_definition
option: [ option: [
(word) (word)
@@ -144,47 +144,47 @@
] @variable.parameter ] @variable.parameter
(#match? @variable.parameter "^[-]")) (#match? @variable.parameter "^[-]"))
;; #AAD94C #000000 0 0 0 1 ;; #AAD94C #000000 0 0 0 0 1
[ [
(double_quote_string) (double_quote_string)
(single_quote_string) (single_quote_string)
] @string ] @string
;; #AAD94C #000000 0 0 0 1 ;; #AAD94C #000000 0 0 0 0 1
(escape_sequence) @string.escape (escape_sequence) @string.escape
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(variable_name) @variable (variable_name) @variable
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(variable_expansion) @constant (variable_expansion) @constant
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(variable_expansion (variable_expansion
"$" @punctuation.special) @none "$" @punctuation.special) @none
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
((variable_name) @variable.builtin ((variable_name) @variable.builtin
(#match? @variable.builtin (#match? @variable.builtin
"^(PATH|CDPATH|LANG|LC_ALL|LC_COLLATE|LC_CTYPE|LC_MESSAGES|LC_MONETARY|LC_NUMERIC|LC_TIME|fish_color_normal|fish_color_command|fish_color_keyword|fish_color_redirection|fish_color_end|fish_color_error|fish_color_param|fish_color_valid_path|fish_color_option|fish_color_comment|fish_color_selection|fish_color_operator|fish_color_escape|fish_color_autosuggestion|fish_color_cwd|fish_color_cwd_root|fish_color_user|fish_color_host|fish_color_host_remote|fish_color_status|fish_color_cancel|fish_color_search_match|fish_color_history_current|fish_pager_color_progress|fish_pager_color_background|fish_pager_color_prefix|fish_pager_color_completion|fish_pager_color_description|fish_pager_color_selected_background|fish_pager_color_selected_prefix|fish_pager_color_selected_completion|fish_pager_color_selected_description|fish_pager_color_secondary_background|fish_pager_color_secondary_prefix|fish_pager_color_secondary_completion|fish_pager_color_secondary_description|fish_term24bit|fish_term256|fish_ambiguous_width|fish_emoji_width|fish_autosuggestion_enabled|fish_handle_reflow|fish_key_bindings|fish_escape_delay_ms|fish_sequence_key_delay_ms|fish_complete_path|fish_cursor_selection_mode|fish_cursor_default|fish_cursor_insert|fish_cursor_replace|fish_cursor_replace_one|fish_cursor_visual|fish_cursor_external|fish_function_path|fish_greeting|fish_history|fish_trace|FISH_DEBUG|FISH_DEBUG_OUTPUT|fish_user_paths|umask|BROWSER|_|argv|CMD_DURATION|COLUMNS|LINES|fish_kill_signal|fish_killring|fish_read_limit|fish_pid|history|HOME|hostname|IFS|last_pid|PWD|pipestatus|SHLVL|status|status_generation|TERM|USER|EUID|version|FISH_VERSION)$")) "^(PATH|CDPATH|LANG|LC_ALL|LC_COLLATE|LC_CTYPE|LC_MESSAGES|LC_MONETARY|LC_NUMERIC|LC_TIME|fish_color_normal|fish_color_command|fish_color_keyword|fish_color_redirection|fish_color_end|fish_color_error|fish_color_param|fish_color_valid_path|fish_color_option|fish_color_comment|fish_color_selection|fish_color_operator|fish_color_escape|fish_color_autosuggestion|fish_color_cwd|fish_color_cwd_root|fish_color_user|fish_color_host|fish_color_host_remote|fish_color_status|fish_color_cancel|fish_color_search_match|fish_color_history_current|fish_pager_color_progress|fish_pager_color_background|fish_pager_color_prefix|fish_pager_color_completion|fish_pager_color_description|fish_pager_color_selected_background|fish_pager_color_selected_prefix|fish_pager_color_selected_completion|fish_pager_color_selected_description|fish_pager_color_secondary_background|fish_pager_color_secondary_prefix|fish_pager_color_secondary_completion|fish_pager_color_secondary_description|fish_term24bit|fish_term256|fish_ambiguous_width|fish_emoji_width|fish_autosuggestion_enabled|fish_handle_reflow|fish_key_bindings|fish_escape_delay_ms|fish_sequence_key_delay_ms|fish_complete_path|fish_cursor_selection_mode|fish_cursor_default|fish_cursor_insert|fish_cursor_replace|fish_cursor_replace_one|fish_cursor_visual|fish_cursor_external|fish_function_path|fish_greeting|fish_history|fish_trace|FISH_DEBUG|FISH_DEBUG_OUTPUT|fish_user_paths|umask|BROWSER|_|argv|CMD_DURATION|COLUMNS|LINES|fish_kill_signal|fish_killring|fish_read_limit|fish_pid|history|HOME|hostname|IFS|last_pid|PWD|pipestatus|SHLVL|status|status_generation|TERM|USER|EUID|version|FISH_VERSION)$"))
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
[ [
(integer) (integer)
(float) (float)
] @number ] @number
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment (comment) @comment
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @spell (comment) @spell
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
((word) @boolean ((word) @boolean
(#match? @boolean "^(true|false)$")) (#match? @boolean "^(true|false)$"))
;; #AAD94C #000000 0 0 0 3 ;; #AAD94C #000000 0 0 0 0 3
((program ((program
. .
(comment) @keyword.directive @nospell) (comment) @keyword.directive @nospell)

File diff suppressed because one or more lines are too long

View File

@@ -1,64 +1,64 @@
;; #AAD94C #000000 0 0 0 3 ;; #AAD94C #000000 0 0 0 0 3
(dir_sep) @punctuation.delimiter (dir_sep) @punctuation.delimiter
;; #AAD94C #000000 0 0 0 3 ;; #AAD94C #000000 0 0 0 0 3
(quoted_pattern (quoted_pattern
"\"" @punctuation.special) "\"" @punctuation.special)
;; #AAD94C #000000 0 0 0 3 ;; #AAD94C #000000 0 0 0 0 3
(range_notation) @string.special (range_notation) @string.special
;; #AAD94C #000000 0 0 0 3 ;; #AAD94C #000000 0 0 0 0 3
(range_notation (range_notation
[ "[" "]" ] @punctuation.bracket) [ "[" "]" ] @punctuation.bracket)
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
(wildcard) @string.regexp (wildcard) @string.regexp
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
(range_negation) @operator (range_negation) @operator
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(character_class) @constant (character_class) @constant
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
(class_range "-" @operator) (class_range "-" @operator)
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
(ansi_c_escape) (ansi_c_escape)
(escaped_char) (escaped_char)
] @escape ] @escape
;; #AAD94C #000000 0 0 0 3 ;; #AAD94C #000000 0 0 0 0 3
(attribute (attribute
(attr_name) @variable.parameter) (attr_name) @variable.parameter)
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
(attribute (attribute
(builtin_attr) @variable.builtin) (builtin_attr) @variable.builtin)
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
[ [
(attr_reset) (attr_reset)
(attr_unset) (attr_unset)
(attr_set) (attr_set)
] @operator ] @operator
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
(boolean_value) @boolean (boolean_value) @boolean
;; #AAD94C #000000 0 0 0 2 ;; #AAD94C #000000 0 0 0 0 2
(string_value) @string (string_value) @string
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(macro_tag) @keyword (macro_tag) @keyword
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(macro_def (macro_def
macro_name: (_) @property) macro_name: (_) @property)
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
[ [
(pattern_negation) (pattern_negation)
(redundant_escape) (redundant_escape)
@@ -66,5 +66,5 @@
(ignored_value) (ignored_value)
] @error ] @error
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment (comment) @comment

View File

@@ -1,46 +1,46 @@
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment @spell (comment) @comment @spell
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(pattern_char) @string.special.path (pattern_char) @string.special.path
;; #AAD94C #000000 0 0 0 3 ;; #AAD94C #000000 0 0 0 0 3
[ [
(directory_separator) (directory_separator)
(directory_separator_escaped) (directory_separator_escaped)
] @punctuation.delimiter ] @punctuation.delimiter
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
[ [
(wildcard_char_single) (wildcard_char_single)
(wildcard_chars) (wildcard_chars)
(wildcard_chars_allow_slash) (wildcard_chars_allow_slash)
] @character.special ] @character.special
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
(pattern_char_escaped) (pattern_char_escaped)
(bracket_char_escaped) (bracket_char_escaped)
] @string.escape ] @string.escape
;; #AAD94C #000000 0 0 0 3 ;; #AAD94C #000000 0 0 0 0 3
(negation) @punctuation.special (negation) @punctuation.special
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
(bracket_negation) @operator (bracket_negation) @operator
;; #AAD94C #000000 0 0 0 3 ;; #AAD94C #000000 0 0 0 0 3
[ [
"[" "["
"]" "]"
] @punctuation.bracket ] @punctuation.bracket
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(bracket_char) @constant (bracket_char) @constant
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
(bracket_range (bracket_range
"-" @operator) "-" @operator)
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
(bracket_char_class) @constant.builtin (bracket_char_class) @constant.builtin

View File

@@ -1,66 +1,66 @@
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(type_identifier) @type (type_identifier) @type
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(type_spec (type_spec
name: (type_identifier) @type.definition) name: (type_identifier) @type.definition)
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(field_identifier) @property (field_identifier) @property
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(identifier) @variable (identifier) @variable
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(package_identifier) @module (package_identifier) @module
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(parameter_declaration (parameter_declaration
(identifier) @variable.parameter) (identifier) @variable.parameter)
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(variadic_parameter_declaration (variadic_parameter_declaration
(identifier) @variable.parameter) (identifier) @variable.parameter)
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
(label_name) @label (label_name) @label
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(const_spec (const_spec
name: (identifier) @constant) name: (identifier) @constant)
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(call_expression (call_expression
function: (identifier) @function.call) function: (identifier) @function.call)
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(call_expression (call_expression
function: (selector_expression function: (selector_expression
field: (field_identifier) @function.method.call)) field: (field_identifier) @function.method.call))
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(function_declaration (function_declaration
name: (identifier) @function) name: (identifier) @function)
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(method_declaration (method_declaration
name: (field_identifier) @function.method) name: (field_identifier) @function.method)
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(method_elem (method_elem
name: (field_identifier) @function.method) name: (field_identifier) @function.method)
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
((call_expression ((call_expression
(identifier) @constructor) (identifier) @constructor)
(#match? @constructor "^[nN]ew.+$")) (#match? @constructor "^[nN]ew.+$"))
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
((call_expression ((call_expression
(identifier) @constructor) (identifier) @constructor)
(#match? @constructor "^[mM]ake.+$")) (#match? @constructor "^[mM]ake.+$"))
;; #F29668 #000000 0 1 0 1 ;; #F29668 #000000 0 1 0 0 1
[ [
"--" "--"
"-" "-"
@@ -102,7 +102,7 @@
"~" "~"
] @operator ] @operator
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"break" "break"
"const" "const"
@@ -116,32 +116,32 @@
"fallthrough" "fallthrough"
] @keyword ] @keyword
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"type" "type"
"struct" "struct"
"interface" "interface"
] @keyword.type ] @keyword.type
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
"func" @keyword.function "func" @keyword.function
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
"return" @keyword.return "return" @keyword.return
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
"go" @keyword.coroutine "go" @keyword.coroutine
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
"for" @keyword.repeat "for" @keyword.repeat
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"import" "import"
"package" "package"
] @keyword.import ] @keyword.import
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"else" "else"
"case" "case"
@@ -149,128 +149,128 @@
"if" "if"
] @keyword.conditional ] @keyword.conditional
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
[ [
"chan" "chan"
"map" "map"
] @type.builtin ] @type.builtin
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
((type_identifier) @type.builtin ((type_identifier) @type.builtin
(#match? @type.builtin (#match? @type.builtin
"^(any|bool|byte|comparable|complex128|complex64|error|float32|float64|int|int16|int32|int64|int8|rune|string|uint|uint16|uint32|uint64|uint8|uintptr)$")) "^(any|bool|byte|comparable|complex128|complex64|error|float32|float64|int|int16|int32|int64|int8|rune|string|uint|uint16|uint32|uint64|uint8|uintptr)$"))
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
((identifier) @function.builtin ((identifier) @function.builtin
(#match? @function.builtin (#match? @function.builtin
"^(append|cap|clear|close|complex|copy|delete|imag|len|make|max|min|new|panic|print|println|real|recover)$")) "^(append|cap|clear|close|complex|copy|delete|imag|len|make|max|min|new|panic|print|println|real|recover)$"))
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
"." @punctuation.delimiter "." @punctuation.delimiter
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
"," @punctuation.delimiter "," @punctuation.delimiter
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
":" @punctuation.delimiter ":" @punctuation.delimiter
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
";" @punctuation.delimiter ";" @punctuation.delimiter
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
"(" @punctuation.bracket "(" @punctuation.bracket
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
")" @punctuation.bracket ")" @punctuation.bracket
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
"{" @punctuation.bracket "{" @punctuation.bracket
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
"}" @punctuation.bracket "}" @punctuation.bracket
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
"[" @punctuation.bracket "[" @punctuation.bracket
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
"]" @punctuation.bracket "]" @punctuation.bracket
;; #AAD94C #000000 0 0 0 1 ;; #AAD94C #000000 0 0 0 0 1
(interpreted_string_literal) @string (interpreted_string_literal) @string
;; #AAD94C #000000 0 0 0 1 ;; #AAD94C #000000 0 0 0 0 1
(raw_string_literal) @string (raw_string_literal) @string
;; #AAD94C #000000 0 0 0 1 ;; #AAD94C #000000 0 0 0 0 1
(rune_literal) @string (rune_literal) @string
;; #AAD94C #000000 0 0 0 1 ;; #AAD94C #000000 0 0 0 0 1
(escape_sequence) @string.escape (escape_sequence) @string.escape
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
(int_literal) @number (int_literal) @number
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
(float_literal) @number.float (float_literal) @number.float
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
(imaginary_literal) @number (imaginary_literal) @number
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
[ [
(true) (true)
(false) (false)
] @boolean ] @boolean
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
[ [
(nil) (nil)
(iota) (iota)
] @constant.builtin ] @constant.builtin
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(keyed_element (keyed_element
. .
(literal_element (literal_element
(identifier) @variable.member)) (identifier) @variable.member))
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(field_declaration (field_declaration
name: (field_identifier) @variable.member) name: (field_identifier) @variable.member)
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment @spell (comment) @comment @spell
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(source_file (source_file
. .
(comment)+ @comment.documentation) (comment)+ @comment.documentation)
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(source_file (source_file
(comment)+ @comment.documentation (comment)+ @comment.documentation
. .
(const_declaration)) (const_declaration))
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(source_file (source_file
(comment)+ @comment.documentation (comment)+ @comment.documentation
. .
(function_declaration)) (function_declaration))
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(source_file (source_file
(comment)+ @comment.documentation (comment)+ @comment.documentation
. .
(type_declaration)) (type_declaration))
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(source_file (source_file
(comment)+ @comment.documentation (comment)+ @comment.documentation
. .
(var_declaration)) (var_declaration))
;; #AAD94C #000000 0 0 0 1 ;; #AAD94C #000000 0 0 0 0 1
(call_expression (call_expression
(selector_expression) @_function (selector_expression) @_function
(#match? @_function (#match? @_function

View File

@@ -1,4 +1,4 @@
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
[ [
"require" "require"
"replace" "replace"
@@ -7,34 +7,34 @@
"retract" "retract"
] @keyword ] @keyword
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
[ [
"go" "go"
"module" "module"
] @keyword.directive ] @keyword.directive
;; #F29668 #000000 0 1 0 1 ;; #F29668 #000000 0 1 0 0 1
"=>" @operator "=>" @operator
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment @spell (comment) @comment @spell
;; #7dcfff #000000 0 0 0 1 ;; #7dcfff #000000 0 0 0 0 1
(module_path) @string.special.url (module_path) @string.special.url
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(tool_directive) @keyword.directive (tool_directive) @keyword.directive
(tool) @string.special.url (tool) @string.special.url
;; #F29668 #000000 0 0 0 2 ;; #F29668 #000000 0 0 0 0 2
[ [
(version) (version)
(go_version) (go_version)
(toolchain_name) (toolchain_name)
] @string.special ] @string.special
;; #888888 #000000 0 0 0 3 ;; #888888 #000000 0 0 0 0 3
[ [
"(" "("
")" ")"
@@ -42,5 +42,5 @@
"]" "]"
] @punctuation.bracket ] @punctuation.bracket
;; #888888 #000000 0 1 0 3 ;; #888888 #000000 0 1 0 0 3
"," @punctuation.delimiter "," @punctuation.delimiter

View File

@@ -2,45 +2,45 @@
; Identifiers ; Identifiers
; ============================================================ ; ============================================================
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
((identifier) @variable) ((identifier) @variable)
;; #FFB870 #000000 0 0 0 9 ;; #FFB870 #000000 0 0 0 0 9
(function_declarator (function_declarator
declarator: (identifier) @function) declarator: (identifier) @function)
;; #C4B5FF #000000 0 0 0 2 ;; #C4B5FF #000000 0 0 0 0 2
((identifier) @constant ((identifier) @constant
(#match? @constant "^[A-Z][A-Z0-9_]+$")) (#match? @constant "^[A-Z][A-Z0-9_]+$"))
;; #C4B5FF #000000 0 0 0 2 ;; #C4B5FF #000000 0 0 0 0 2
(preproc_def (preproc_def
(preproc_arg) @constant (preproc_arg) @constant
(#match? @constant "^[A-Z][A-Z0-9_]+$")) (#match? @constant "^[A-Z][A-Z0-9_]+$"))
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
((identifier) @constant.builtin ((identifier) @constant.builtin
(#match? @constant.builtin "^(stderr|stdin|stdout|__FILE__|__LINE__|__DATE__|__TIME__|__STDC__|__STDC_VERSION__|__STDC_HOSTED__|__cplusplus|__OBJC__|__ASSEMBLER__|__BASE_FILE__|__FILE_NAME__|__INCLUDE_LEVEL__|__TIMESTAMP__|__clang__|__clang_major__|__clang_minor__|__clang_patchlevel__|__clang_version__|__clang_literal_encoding__|__clang_wide_literal_encoding__|__FUNCTION__|__func__|__PRETTY_FUNCTION__|__VA_ARGS__|__VA_OPT__)$")) (#match? @constant.builtin "^(stderr|stdin|stdout|__FILE__|__LINE__|__DATE__|__TIME__|__STDC__|__STDC_VERSION__|__STDC_HOSTED__|__cplusplus|__OBJC__|__ASSEMBLER__|__BASE_FILE__|__FILE_NAME__|__INCLUDE_LEVEL__|__TIMESTAMP__|__clang__|__clang_major__|__clang_minor__|__clang_patchlevel__|__clang_version__|__clang_literal_encoding__|__clang_wide_literal_encoding__|__FUNCTION__|__func__|__PRETTY_FUNCTION__|__VA_ARGS__|__VA_OPT__)$"))
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_def (preproc_def
(preproc_arg) @constant.builtin (preproc_arg) @constant.builtin
(#match? @constant.builtin "^(stderr|stdin|stdout|__FILE__|__LINE__|__DATE__|__TIME__|__STDC__|__STDC_VERSION__|__STDC_HOSTED__|__cplusplus|__OBJC__|__ASSEMBLER__|__BASE_FILE__|__FILE_NAME__|__INCLUDE_LEVEL__|__TIMESTAMP__|__clang__|__clang_major__|__clang_minor__|__clang_patchlevel__|__clang_version__|__clang_literal_encoding__|__clang_wide_literal_encoding__|__FUNCTION__|__func__|__PRETTY_FUNCTION__|__VA_ARGS__|__VA_OPT__)$")) (#match? @constant.builtin "^(stderr|stdin|stdout|__FILE__|__LINE__|__DATE__|__TIME__|__STDC__|__STDC_VERSION__|__STDC_HOSTED__|__cplusplus|__OBJC__|__ASSEMBLER__|__BASE_FILE__|__FILE_NAME__|__INCLUDE_LEVEL__|__TIMESTAMP__|__clang__|__clang_major__|__clang_minor__|__clang_patchlevel__|__clang_version__|__clang_literal_encoding__|__clang_wide_literal_encoding__|__FUNCTION__|__func__|__PRETTY_FUNCTION__|__VA_ARGS__|__VA_OPT__)$"))
;; #8AD5FF #000000 0 0 0 2 ;; #8AD5FF #000000 0 0 0 0 2
(preproc_def (preproc_def
(preproc_arg) @variable) (preproc_arg) @variable)
;; #8AD5FF #000000 0 0 0 2 ;; #8AD5FF #000000 0 0 0 0 2
(statement_identifier) @label (statement_identifier) @label
;; #8AD5FF #000000 0 0 0 2 ;; #8AD5FF #000000 0 0 0 0 2
(declaration (declaration
type: (type_identifier) @_type type: (type_identifier) @_type
declarator: (identifier) @label declarator: (identifier) @label
(#match? @_type "^__label__$")) (#match? @_type "^__label__$"))
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
((identifier) @variable.member ((identifier) @variable.member
(#match? @variable.member "^m_.*$")) (#match? @variable.member "^m_.*$"))
@@ -48,7 +48,7 @@
; Keywords ; Keywords
; ============================================================ ; ============================================================
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"default" "default"
"goto" "goto"
@@ -56,7 +56,7 @@
"__asm__" "__asm__"
] @keyword ] @keyword
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"enum" "enum"
"struct" "struct"
@@ -64,21 +64,21 @@
"typedef" "typedef"
] @keyword.type ] @keyword.type
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
[ [
"sizeof" "sizeof"
"offsetof" "offsetof"
] @keyword.operator ] @keyword.operator
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(alignof_expression (alignof_expression
. .
_ @keyword.operator) _ @keyword.operator)
;; #FFB870 #000000 0 0 0 2 ;; #FFB870 #000000 0 0 0 0 2
"return" @keyword.return "return" @keyword.return
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"while" "while"
"for" "for"
@@ -87,7 +87,7 @@
"break" "break"
] @keyword.repeat ] @keyword.repeat
;; #FFB870 #000000 0 0 0 2 ;; #FFB870 #000000 0 0 0 0 2
[ [
"if" "if"
"else" "else"
@@ -95,14 +95,14 @@
"switch" "switch"
] @keyword.conditional ] @keyword.conditional
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
(conditional_expression (conditional_expression
[ [
"?" "?"
":" ":"
] @keyword.conditional.ternary) ] @keyword.conditional.ternary)
;; #8AD5FF #000000 0 0 0 2 ;; #8AD5FF #000000 0 0 0 0 2
[ [
"#if" "#if"
"#ifdef" "#ifdef"
@@ -115,13 +115,13 @@
(preproc_directive) (preproc_directive)
] @keyword.directive ] @keyword.directive
;; #8AD5FF #000000 0 0 0 2 ;; #8AD5FF #000000 0 0 0 0 2
"#define" @keyword.directive.define "#define" @keyword.directive.define
;; #8AD5FF #000000 0 0 0 2 ;; #8AD5FF #000000 0 0 0 0 2
"#include" @keyword.import "#include" @keyword.import
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"try" "try"
"catch" "catch"
@@ -129,7 +129,7 @@
"throw" "throw"
] @keyword.exception ] @keyword.exception
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"decltype" "decltype"
"explicit" "explicit"
@@ -140,7 +140,7 @@
"constexpr" "constexpr"
] @keyword ] @keyword
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"class" "class"
"namespace" "namespace"
@@ -149,14 +149,14 @@
"concept" "concept"
] @keyword.type ] @keyword.type
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
[ [
"co_await" "co_await"
"co_yield" "co_yield"
"co_return" "co_return"
] @keyword.coroutine ] @keyword.coroutine
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
[ [
"public" "public"
"private" "private"
@@ -165,21 +165,21 @@
"virtual" "virtual"
] @keyword.modifier ] @keyword.modifier
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(storage_class_specifier) @keyword.modifier (storage_class_specifier) @keyword.modifier
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
[ [
(type_qualifier) (type_qualifier)
(gnu_asm_qualifier) (gnu_asm_qualifier)
"__extension__" "__extension__"
] @keyword.modifier ] @keyword.modifier
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(linkage_specification (linkage_specification
"extern" @keyword.modifier) "extern" @keyword.modifier)
;; #F29668 #000000 0 0 0 2 ;; #F29668 #000000 0 0 0 0 2
[ [
"new" "new"
"delete" "delete"
@@ -196,54 +196,39 @@
"or" "or"
] @keyword.operator ] @keyword.operator
;; #F29668 #000000 0 1 0 2 ;; #F29668 #000000 0 1 0 0 2
"<=>" @operator "<=>" @operator
; ============================================================ ; ============================================================
; Types & modules ; Types & modules
; ============================================================ ; ============================================================
;; #C4B5FF #000000 0 0 0 2 ;; #C4B5FF #000000 0 0 0 0 2
[ [
(type_identifier) (type_identifier)
(type_descriptor) (type_descriptor)
] @type ] @type
;; #C4B5FF #000000 0 0 0 2 ;; #C4B5FF #000000 0 0 0 0 2
(type_definition (type_definition
declarator: (type_identifier) @type.definition) declarator: (type_identifier) @type.definition)
;; #C4B5FF #000000 0 0 0 2 ;; #C4B5FF #000000 0 0 0 0 2
(primitive_type) @type.builtin (primitive_type) @type.builtin
;; #C4B5FF #000000 0 0 0 2 ;; #C4B5FF #000000 0 0 0 0 2
(sized_type_specifier (sized_type_specifier
_ @type.builtin _ @type.builtin
type: _?) type: _?)
;; #C4B5FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
(type_definition declarator: (type_identifier) @name) @definition.type
;; #C4B5FF #000000 0 0 0 2
(enum_specifier name: (type_identifier) @name) @definition.type
;; #C4B5FF #000000 0 0 0 2
(class_specifier name: (type_identifier) @name) @definition.class
;; #C4B5FF #000000 0 0 0 2
(struct_specifier name: (type_identifier) @name body:(_)) @definition.class
;; #C4B5FF #000000 0 0 0 2
(declaration type: (union_specifier name: (type_identifier) @name)) @definition.class
;; #9AD4FF #000000 0 0 0 2
(namespace_identifier) @module (namespace_identifier) @module
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
((namespace_identifier) @type ((namespace_identifier) @type
(#match? @type "^[A-Z]")) (#match? @type "^[A-Z]"))
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
(using_declaration (using_declaration
. .
"using" "using"
@@ -259,22 +244,22 @@
; Functions & calls ; Functions & calls
; ============================================================ ; ============================================================
;; #FFB870 #000000 0 0 0 1 ;; #FFB870 #000000 0 0 0 0 1
(operator_name) @function (operator_name) @function
;; #FFB870 #000000 0 0 0 3 ;; #FFB870 #000000 0 0 0 0 3
"operator" @function "operator" @function
;; #78C2FF #000000 0 0 0 2 ;; #78C2FF #000000 0 0 0 0 2
(call_expression (call_expression
function: (identifier) @function.call) function: (identifier) @function.call)
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
((call_expression ((call_expression
function: (identifier) @function.builtin) function: (identifier) @function.builtin)
(#match? @function.builtin "^__builtin_")) (#match? @function.builtin "^__builtin_"))
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
((call_expression ((call_expression
function: (identifier) @function.builtin)) function: (identifier) @function.builtin))
@@ -282,30 +267,30 @@
; Constructors & methods ; Constructors & methods
; ============================================================ ; ============================================================
;; #59C2FF #000000 0 0 0 2 ;; #59C2FF #000000 0 0 0 0 2
((call_expression ((call_expression
function: (identifier) @constructor) function: (identifier) @constructor)
(#match? @constructor "^[A-Z]")) (#match? @constructor "^[A-Z]"))
;; #59C2FF #000000 0 0 0 2 ;; #59C2FF #000000 0 0 0 0 2
((call_expression ((call_expression
function: (qualified_identifier function: (qualified_identifier
name: (identifier) @constructor)) name: (identifier) @constructor))
(#match? @constructor "^[A-Z]")) (#match? @constructor "^[A-Z]"))
;; #59C2FF #000000 0 0 0 2 ;; #59C2FF #000000 0 0 0 0 2
((call_expression ((call_expression
function: (field_expression function: (field_expression
field: (field_identifier) @constructor)) field: (field_identifier) @constructor))
(#match? @constructor "^[A-Z]")) (#match? @constructor "^[A-Z]"))
;; #59C2FF #000000 0 0 0 2 ;; #59C2FF #000000 0 0 0 0 2
((field_initializer ((field_initializer
(field_identifier) @constructor (field_identifier) @constructor
(argument_list)) (argument_list))
(#match? @constructor "^[A-Z]")) (#match? @constructor "^[A-Z]"))
;; #59C2FF #000000 0 0 0 4 ;; #59C2FF #000000 0 0 0 0 4
(destructor_name (destructor_name
(identifier) @function.method) (identifier) @function.method)
@@ -313,7 +298,7 @@
; Properties & members ; Properties & members
; ============================================================ ; ============================================================
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
((field_expression ((field_expression
(field_identifier) @property) @_parent) (field_identifier) @property) @_parent)
@@ -324,7 +309,7 @@
(field_initializer (field_initializer
(field_identifier) @property) (field_identifier) @property)
;; #F29CC3 #000000 0 0 1 2 ;; #F29CC3 #000000 0 0 1 0 2
(field_declaration (field_declaration
(field_identifier) @variable.member) (field_identifier) @variable.member)
@@ -332,32 +317,32 @@
; Parameters ; Parameters
; ============================================================ ; ============================================================
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(parameter_declaration (parameter_declaration
declarator: (identifier) @variable.parameter) declarator: (identifier) @variable.parameter)
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(parameter_declaration (parameter_declaration
declarator: (array_declarator) @variable.parameter) declarator: (array_declarator) @variable.parameter)
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(parameter_declaration (parameter_declaration
declarator: (pointer_declarator) @variable.parameter) declarator: (pointer_declarator) @variable.parameter)
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(preproc_params (preproc_params
(identifier) @variable.parameter) (identifier) @variable.parameter)
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(parameter_declaration (parameter_declaration
declarator: (reference_declarator) @variable.parameter) declarator: (reference_declarator) @variable.parameter)
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(variadic_parameter_declaration (variadic_parameter_declaration
declarator: (variadic_declarator declarator: (variadic_declarator
(_) @variable.parameter)) (_) @variable.parameter))
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(optional_parameter_declaration (optional_parameter_declaration
declarator: (_) @variable.parameter) declarator: (_) @variable.parameter)
@@ -365,7 +350,7 @@
; Attributes & specifiers ; Attributes & specifiers
; ============================================================ ; ============================================================
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
[ [
"__attribute__" "__attribute__"
"__declspec" "__declspec"
@@ -380,12 +365,12 @@
(attribute_declaration) (attribute_declaration)
] @attribute ] @attribute
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(attribute_specifier (attribute_specifier
(argument_list (argument_list
(identifier) @variable.builtin)) (identifier) @variable.builtin))
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(attribute_specifier (attribute_specifier
(argument_list (argument_list
(call_expression (call_expression
@@ -395,7 +380,7 @@
; Operators & punctuation ; Operators & punctuation
; ============================================================ ; ============================================================
;; #F29668 #000000 0 1 0 1 ;; #F29668 #000000 0 1 0 0 1
[ [
"=" "="
"-" "-"
@@ -433,11 +418,11 @@
"++" "++"
] @operator ] @operator
;; #F29668 #000000 0 1 0 1 ;; #F29668 #000000 0 1 0 0 1
(comma_expression (comma_expression
"," @operator) "," @operator)
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
[ [
";" ";"
":" ":"
@@ -446,13 +431,13 @@
"::" "::"
] @punctuation.delimiter ] @punctuation.delimiter
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
"::" @punctuation.delimiter "::" @punctuation.delimiter
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
"..." @punctuation.special "..." @punctuation.special
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
[ [
"(" "("
")" ")"
@@ -462,14 +447,14 @@
"}" "}"
] @punctuation.bracket ] @punctuation.bracket
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
(template_argument_list (template_argument_list
[ [
"<" "<"
">" ">"
] @punctuation.bracket) ] @punctuation.bracket)
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
(template_parameter_list (template_parameter_list
[ [
"<" "<"
@@ -480,40 +465,40 @@
; Literals ; Literals
; ============================================================ ; ============================================================
;; #C2E8FF #000000 0 0 0 2 ;; #C2E8FF #000000 0 0 0 0 2
[ [
(true) (true)
(false) (false)
] @boolean ] @boolean
;; #C2E8FF #000000 0 0 0 2 ;; #C2E8FF #000000 0 0 0 0 2
(true) @boolean_true (true) @boolean_true
;; #C2E8FF #000000 0 0 0 2 ;; #C2E8FF #000000 0 0 0 0 2
(false) @boolean_false (false) @boolean_false
;; #A6E3A1 #000000 0 0 0 2 ;; #A6E3A1 #000000 0 0 0 0 2
(string_literal) @string (string_literal) @string
;; #A6E3A1 #000000 0 0 0 2 ;; #A6E3A1 #000000 0 0 0 0 2
(system_lib_string) @string (system_lib_string) @string
;; #A6E3A1 #000000 0 0 0 2 ;; #A6E3A1 #000000 0 0 0 0 2
(raw_string_literal) @string (raw_string_literal) @string
;; #A6E3A1 #000000 0 0 0 2 ;; #A6E3A1 #000000 0 0 0 0 2
(escape_sequence) @string.escape (escape_sequence) @string.escape
;; #B8E986 #000000 0 0 0 2 ;; #B8E986 #000000 0 0 0 0 2
(number_literal) @number (number_literal) @number
;; #B8E986 #000000 0 0 0 2 ;; #B8E986 #000000 0 0 0 0 2
(char_literal) @character (char_literal) @character
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(null) @constant.builtin (null) @constant.builtin
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(null (null
"nullptr" @constant.builtin) "nullptr" @constant.builtin)
@@ -521,59 +506,59 @@
; Macros & directives ; Macros & directives
; ============================================================ ; ============================================================
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_def (preproc_def
name: (_) @constant.macro) name: (_) @constant.macro)
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_call (preproc_call
directive: (preproc_directive) @_u directive: (preproc_directive) @_u
argument: (_) @constant.macro argument: (_) @constant.macro
(#match? @_u "^#undef$")) (#match? @_u "^#undef$"))
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_ifdef (preproc_ifdef
name: (identifier) @constant.macro) name: (identifier) @constant.macro)
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_elifdef (preproc_elifdef
name: (identifier) @constant.macro) name: (identifier) @constant.macro)
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_defined (preproc_defined
(identifier) @constant.macro) (identifier) @constant.macro)
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(preproc_defined) @function.macro (preproc_defined) @function.macro
; ============================================================ ; ============================================================
; Builtins & special identifiers ; Builtins & special identifiers
; ============================================================ ; ============================================================
;; #F28FAD #000000 0 0 0 2 ;; #F28FAD #000000 0 0 0 0 2
(attribute_specifier (attribute_specifier
(argument_list (argument_list
(identifier) @variable.builtin)) (identifier) @variable.builtin))
;; #F28FAD #000000 0 0 0 2 ;; #F28FAD #000000 0 0 0 0 2
(attribute_specifier (attribute_specifier
(argument_list (argument_list
(call_expression (call_expression
function: (identifier) @variable.builtin))) function: (identifier) @variable.builtin)))
;; #F28FAD #000000 0 0 0 2 ;; #F28FAD #000000 0 0 0 0 2
(this) @variable.builtin (this) @variable.builtin
; ============================================================ ; ============================================================
; Exceptions & control helpers ; Exceptions & control helpers
; ============================================================ ; ============================================================
;; #FFB870 #000000 0 0 0 2 ;; #FFB870 #000000 0 0 0 0 2
"static_assert" @function.builtin "static_assert" @function.builtin
; ============================================================ ; ============================================================
; Comments ; Comments
; ============================================================ ; ============================================================
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment @spell (comment) @comment @spell

View File

@@ -1,82 +1,82 @@
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(variable) @variable (variable) @variable
;; Lambdas / patterns keep params white ;; Lambdas / patterns keep params white
;; #FFFFFF #000000 0 1 0 5 ;; #FFFFFF #000000 0 1 0 0 5
(expression/lambda (expression/lambda
(_)+ @variable.parameter (_)+ @variable.parameter
"->") "->")
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(decl/function (decl/function
patterns: (patterns patterns: (patterns
(_) @variable.parameter)) (_) @variable.parameter))
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(decl/function (decl/function
(infix (infix
(pattern) @variable.parameter)) (pattern) @variable.parameter))
;; Types / builtins ;; Types / builtins
;; #F07178 #000000 0 0 0 6 ;; #F07178 #000000 0 0 0 0 6
((name) @type.builtin ((name) @type.builtin
(#match? @type.builtin "^(Int|Integer|Bool|Char|String|Float|Double|Word)$")) (#match? @type.builtin "^(Int|Integer|Bool|Char|String|Float|Double|Word)$"))
;; Strings / chars ;; Strings / chars
;; #9ADE7A #000000 0 0 0 1 ;; #9ADE7A #000000 0 0 0 0 1
(char) @literal.char (char) @literal.char
;; #9ADE7A #000000 0 0 0 1 ;; #9ADE7A #000000 0 0 0 0 1
(string) @literal.string (string) @literal.string
;; Comments ;; Comments
;; #99ADBF #000000 0 1 0 5 ;; #99ADBF #000000 0 1 0 0 5
(comment) @comment.general (comment) @comment.general
;; #99ADBF #000000 0 1 0 5 ;; #99ADBF #000000 0 1 0 0 5
(haddock) @comment.documentation (haddock) @comment.documentation
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @spell (comment) @spell
;; Punctuation ;; Punctuation
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
[ [
"(" ")" "{" "}" "[" "]" "(" ")" "{" "}" "[" "]"
] @punctuation.bracket ] @punctuation.bracket
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
[ "," ";" ] @punctuation.delimiter [ "," ";" ] @punctuation.delimiter
;; Keywords (orange) ;; Keywords (orange)
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ "forall" ] @keyword.quantifier [ "forall" ] @keyword.quantifier
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
(pragma) @keyword.directive (pragma) @keyword.directive
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"if" "then" "else" "case" "of" "if" "then" "else" "case" "of"
] @keyword.conditional ] @keyword.conditional
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ "import" "qualified" "module" ] @keyword.import [ "import" "qualified" "module" ] @keyword.import
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"where" "let" "in" "class" "instance" "pattern" "data" "where" "let" "in" "class" "instance" "pattern" "data"
"newtype" "family" "type" "as" "hiding" "deriving" "via" "newtype" "family" "type" "as" "hiding" "deriving" "via"
"stock" "anyclass" "do" "mdo" "rec" "infix" "infixl" "infixr" "stock" "anyclass" "do" "mdo" "rec" "infix" "infixl" "infixr"
] @keyword.definition ] @keyword.definition
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ "forall" ] @keyword.repeat [ "forall" ] @keyword.repeat
;; Operators (italic white, high priority) ;; Operators (italic white, high priority)
;; #FFFFFF #000000 0 1 0 6 ;; #FFFFFF #000000 0 1 0 0 6
[ [
(operator) (operator)
(constructor_operator) (constructor_operator)
(all_names) (all_names)
"." ".." "=" "|" "::" "=>" "->" "<-" "\\" "`" "@" "." ".." "=" "|" "::" "=>" "->" "<-" "\\" "`" "@"
] @operator.general ] @operator.general
;; #FFFFFF #000000 0 1 0 6 ;; #FFFFFF #000000 0 1 0 0 6
(infix_id (infix_id
[ [
(variable) @operator.infix (variable) @operator.infix
(qualified (variable) @operator.infix) (qualified (variable) @operator.infix)
]) ])
;; #FFFFFF #000000 0 1 0 6 ;; #FFFFFF #000000 0 1 0 0 6
[ [
(operator) (operator)
(constructor_operator) (constructor_operator)
@@ -86,39 +86,39 @@
] @operator ] @operator
;; Modules ;; Modules
;; #7dcfff #000000 0 0 0 1 ;; #7dcfff #000000 0 0 0 0 1
(module (module
(module_id) @module.name) (module_id) @module.name)
;; #7dcfff #000000 0 0 0 1 ;; #7dcfff #000000 0 0 0 0 1
(module (module
(module_id) @module) (module_id) @module)
;; Functions / calls (leave blue for function identifiers, but vars stay white due to higher priority var rules) ;; Functions / calls (leave blue for function identifiers, but vars stay white due to higher priority var rules)
;; #82AAFF #000000 0 0 0 3 ;; #82AAFF #000000 0 0 0 0 3
(decl/signature (decl/signature
[ [
name: (variable) @function.name name: (variable) @function.name
names: (binding_list (variable) @function.name) names: (binding_list (variable) @function.name)
]) ])
;; #82AAFF #000000 0 0 0 3 ;; #82AAFF #000000 0 0 0 0 3
(decl/function (decl/function
[ [
name: (variable) @function.name name: (variable) @function.name
names: (binding_list (variable) @function.name) names: (binding_list (variable) @function.name)
]) ])
;; #82AAFF #000000 0 0 0 3 ;; #82AAFF #000000 0 0 0 0 3
(decl/bind (decl/bind
[ [
name: (variable) @function.name name: (variable) @function.name
names: (binding_list (variable) @function.name) names: (binding_list (variable) @function.name)
]) ])
;; #82AAFF #000000 0 0 0 2 ;; #82AAFF #000000 0 0 0 0 2
(decl (decl
[ [
name: (variable) @function name: (variable) @function
names: (binding_list (variable) @function) names: (binding_list (variable) @function)
]) ])
;; #82AAFF #000000 0 0 0 3 ;; #82AAFF #000000 0 0 0 0 3
(decl/signature (decl/signature
name: (variable) @function.io name: (variable) @function.io
type: (type/apply type: (type/apply
@@ -126,7 +126,7 @@
(#match? @_io "^IO$")) (#match? @_io "^IO$"))
;; Function calls kept white via var priority; ensure explicit call rule stays neutral/white ;; Function calls kept white via var priority; ensure explicit call rule stays neutral/white
;; #FFFFFF #000000 0 0 0 3 ;; #FFFFFF #000000 0 0 0 0 3
(apply (apply
[ [
(expression/variable) @function.call (expression/variable) @function.call
@@ -134,23 +134,23 @@
]) ])
;; Types / constructors ;; Types / constructors
;; #82AAFF #000000 0 0 0 3 ;; #82AAFF #000000 0 0 0 0 3
(name) @type (name) @type
;; #82AAFF #000000 0 0 0 3 ;; #82AAFF #000000 0 0 0 0 3
(type/star) @type (type/star) @type
;; #C6B5FF #000000 0 0 0 1 ;; #C6B5FF #000000 0 0 0 0 1
(constructor) @constructor.general (constructor) @constructor.general
;; #9ADE7A #000000 0 0 0 2 ;; #9ADE7A #000000 0 0 0 0 2
((constructor) @boolean ((constructor) @boolean
(#match? @boolean "^(True|False)$")) (#match? @boolean "^(True|False)$"))
;; #9ADE7A #000000 0 0 0 1 ;; #9ADE7A #000000 0 0 0 0 1
((variable) @boolean ((variable) @boolean
(#match? @boolean "^otherwise$")) (#match? @boolean "^otherwise$"))
;; Quoters / quasiquotes ;; Quoters / quasiquotes
;; #82AAFF #000000 0 0 0 3 ;; #82AAFF #000000 0 0 0 0 3
(quoter) @function.call (quoter) @function.call
;; #9ADE7A #000000 0 0 0 1 ;; #9ADE7A #000000 0 0 0 0 1
(quasiquote (quasiquote
[ [
(quoter) @_name (quoter) @_name
@@ -159,13 +159,13 @@
] ]
(#match? @_name "^qq$") (#match? @_name "^qq$")
(quasiquote_body) @string) (quasiquote_body) @string)
;; #9ADE7A #000000 0 0 0 1 ;; #9ADE7A #000000 0 0 0 0 1
(quasiquote (quasiquote
(_ (_
(variable) @_name) (variable) @_name)
(#match? @_name "^qq$") (#match? @_name "^qq$")
(quasiquote_body) @string) (quasiquote_body) @string)
;; #82AAFF #000000 0 0 0 3 ;; #82AAFF #000000 0 0 0 0 3
(quasiquote (quasiquote
(_ (_
(module) @module (module) @module
@@ -173,35 +173,35 @@
(variable) @function.call)) (variable) @function.call))
;; Exceptions / Debug ;; Exceptions / Debug
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
((variable) @keyword.exception ((variable) @keyword.exception
(#match? @keyword.exception "^(error|undefined|try|tryJust|tryAny|catch|catches|catchJust|handle|handleJust|throw|throwIO|throwTo|throwError|ioError|mask|mask_|uninterruptibleMask|uninterruptibleMask_|bracket|bracket_|bracketOnErrorSource|finally|fail|onException|expectationFailure)$")) (#match? @keyword.exception "^(error|undefined|try|tryJust|tryAny|catch|catches|catchJust|handle|handleJust|throw|throwIO|throwTo|throwError|ioError|mask|mask_|uninterruptibleMask|uninterruptibleMask_|bracket|bracket_|bracketOnErrorSource|finally|fail|onException|expectationFailure)$"))
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
((variable) @keyword.debug ((variable) @keyword.debug
(#match? @keyword.debug "^(trace|traceId|traceShow|traceShowId|traceWith|traceShowWith|traceStack|traceIO|traceM|traceShowM|traceEvent|traceEventWith|traceEventIO|flushEventLog|traceMarker|traceMarkerIO)$")) (#match? @keyword.debug "^(trace|traceId|traceShow|traceShowId|traceWith|traceShowWith|traceStack|traceIO|traceM|traceShowM|traceEvent|traceEventWith|traceEventIO|flushEventLog|traceMarker|traceMarkerIO)$"))
;; Misc remaining structural ;; Misc remaining structural
;; #C6B5FF #000000 0 0 0 1 ;; #C6B5FF #000000 0 0 0 0 1
(wildcard) @literal.special (wildcard) @literal.special
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
[ "," ";" ] @punctuation.delimiter [ "," ";" ] @punctuation.delimiter
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
[ [
"(" ")" "{" "}" "[" "]" "(" ")" "{" "}" "[" "]"
] @punctuation.bracket ] @punctuation.bracket
;; #7dcfff #000000 0 0 0 1 ;; #7dcfff #000000 0 0 0 0 1
(type/unit) @type.unit (type/unit) @type.unit
(type/list) @type.list (type/list) @type.list
(type/star) @type.star (type/star) @type.star
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(field_name (variable) @variable.member) (field_name (variable) @variable.member)
(import_name (name) . (children (variable) @variable.member)) (import_name (name) . (children (variable) @variable.member))
;; Numbers (bright yellow-green) ;; Numbers (bright yellow-green)
;; #DFFFA0 #000000 0 0 0 2 ;; #DFFFA0 #000000 0 0 0 0 2
(integer) @number.integer (integer) @number.integer
;; #DFFFA0 #000000 0 0 0 2 ;; #DFFFA0 #000000 0 0 0 0 2
(negation) @number.integer (negation) @number.integer
;; #DFFFA0 #000000 0 0 0 2 ;; #DFFFA0 #000000 0 0 0 0 2
(expression/literal (expression/literal
(float) @number.float) (float) @number.float)

334
grammar/hover.scm Normal file
View File

@@ -0,0 +1,334 @@
;; #82AAFF #000000 1 0 1 0 4
(setext_heading
(paragraph) @markup.heading.1
(setext_h1_underline) @markup.heading.1)
;; #82AAFF #000000 1 0 1 0 4
(setext_heading
(paragraph) @markup.heading.2
(setext_h2_underline) @markup.heading.2)
(atx_heading
(atx_h1_marker)) @markup.heading.1
(atx_heading
(atx_h2_marker)) @markup.heading.2
;; #82AAFF #000000 1 0 0 0 4
(atx_heading
(atx_h3_marker)) @markup.heading.3
;; #82AAFF #000000 1 0 0 0 4
(atx_heading
(atx_h4_marker)) @markup.heading.4
;; #82AAFF #000000 1 0 0 0 4
(atx_heading
(atx_h5_marker)) @markup.heading.5
;; #82AAFF #000000 1 0 0 0 4
(atx_heading
(atx_h6_marker)) @markup.heading.6
;; #82AAFF #000000 0 0 0 0 4
(info_string) @label
;; #FF6347 #000000 0 0 0 0 4
(pipe_table_header
(pipe_table_cell) @markup.heading)
;; #FF8F40 #000000 0 0 0 0 4
(pipe_table_header
"|" @punctuation.special)
(pipe_table_row
"|" @punctuation.special)
(pipe_table_delimiter_row
"|" @punctuation.special)
(pipe_table_delimiter_cell) @punctuation.special
;; #AAD94C #000000 0 0 0 0 2
(indented_code_block) @markup.raw.block
(fenced_code_block) @markup.raw.block
(fenced_code_block
(fenced_code_block_delimiter) @markup.raw.block)
(fenced_code_block
(info_string
(language) @label))
;; #7dcfff #000000 0 0 1 0 6
(link_destination) @markup.link.url
;; #7dcfff #000000 0 0 1 0 6
[
(link_title)
(link_label)
] @markup.link.label
;; #FF8F40 #000000 0 0 0 0 4
((link_label)
.
":" @punctuation.delimiter)
;; #9ADE7A #000000 0 0 0 0 4
[
(list_marker_plus)
(list_marker_minus)
(list_marker_star)
(list_marker_dot)
(list_marker_parenthesis)
] @markup.list
(thematic_break) @punctuation.special
;; #FF8F40 #000000 0 0 0 0 4
(task_list_marker_unchecked) @markup.list.unchecked
;; #AAD94C #000000 0 0 0 0 4
(task_list_marker_checked) @markup.list.checked
[
(plus_metadata)
(minus_metadata)
] @keyword.directive
[
(block_continuation)
(block_quote_marker)
] @punctuation.special
;; #AAD94C #000000 0 0 0 0 6
(backslash_escape) @string.escape
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^ruby$"))
;; !ruby
(code_fence_content) @injection.ruby)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^bash$"))
;; !bash
(code_fence_content) @injection.bash)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^cpp$"))
;; !cpp
(code_fence_content) @injection.cpp)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^objective-cpp$"))
;; !cpp
(code_fence_content) @injection.cpp)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^h$"))
;; !h
(code_fence_content) @injection.h)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^c$"))
;; !c
(code_fence_content) @injection.h)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^css$"))
;; !css
(code_fence_content) @injection.css)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^fish$"))
;; !fish
(code_fence_content) @injection.fish)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^go$"))
;; !go
(code_fence_content) @injection.go)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^haskell$"))
;; !haskell
(code_fence_content) @injection.haskell)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^html$"))
;; !html
(code_fence_content) @injection.html)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^javascript$"))
;; !javascript
(code_fence_content) @injection.javascript)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^json$"))
;; !json
(code_fence_content) @injection.json)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^lua$"))
; - lua format in hover boxes is typed making it unparsable as normal lua
; - TODO: add a lua grammar with typing or remove this injection
(code_fence_content) @injection.lua)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^regex$"))
;; !regex
(code_fence_content) @injection.regex)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^query$"))
;; !query
(code_fence_content) @injection.query)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^markdown$"))
;; !markdown
(code_fence_content) @injection.markdown)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^markdown_inline$"))
;; !markdown_inline
(code_fence_content) @injection.markdown_inline)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^erb$"))
;; !embedded_template
(code_fence_content) @injection.embedded_template)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^python$"))
;; !python
(code_fence_content) @injection.python)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^php$"))
;; !php
(code_fence_content) @injection.php)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^rust$"))
;; !rust
(code_fence_content) @injection.rust)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^sql$"))
;; !sql
(code_fence_content) @injection.sql)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^gitattributes$"))
;; !gitattributes
(code_fence_content) @injection.gitattributes)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^gitignore$"))
;; !gitignore
(code_fence_content) @injection.gitignore)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^gdscript$"))
;; !gdscript
(code_fence_content) @injection.gdscript)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^make$"))
;; !make
(code_fence_content) @injection.make)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^diff$"))
;; !diff
(code_fence_content) @injection.diff)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^ini$"))
;; !ini
(code_fence_content) @injection.ini)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^nginx$"))
;; !nginx
(code_fence_content) @injection.nginx)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^toml$"))
;; !toml
(code_fence_content) @injection.toml)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^yaml$"))
;; !yaml
(code_fence_content) @injection.yaml)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^gomod$"))
;; !gomod
(code_fence_content) @injection.gomod)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^man$"))
;; !man
(code_fence_content) @injection.man)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^cabal$"))
;; !cabal
(code_fence_content) @injection.cabal)
;; !html
(html_block) @injection.html
;; !yaml
(minus_metadata) @injection.yaml
;; !toml
(plus_metadata) @injection.toml
;; !markdown_inline
(paragraph) @inline
(pipe_table_row
(pipe_table_cell) @inline)
(block_quote ((paragraph) @inline))

View File

@@ -1,10 +1,10 @@
;; #99ADBF #000000 0 1 0 5 ;; #99ADBF #000000 0 1 0 0 5
(comment) @comment @spell (comment) @comment @spell
;; #9ADE7A #000000 0 0 0 1 ;; #9ADE7A #000000 0 0 0 0 1
(attribute_name) @tag.attribute (attribute_name) @tag.attribute
;; #FF8F40 #000000 0 0 0 0 ;; #FF8F40 #000000 0 0 0 0 0
((attribute ((attribute
(quoted_attribute_value) @string)) (quoted_attribute_value) @string))
@@ -15,56 +15,56 @@
"\"" "\""
] @string ] @string
;; #82AAFF #000000 1 0 0 3 ;; #82AAFF #000000 1 0 0 0 3
((element ((element
(start_tag (start_tag
(tag_name) @_tag) (tag_name) @_tag)
(text) @markup.heading) (text) @markup.heading)
(#match? @_tag "^title$")) (#match? @_tag "^title$"))
;; #82AAFF #000000 1 0 1 3 ;; #82AAFF #000000 1 0 1 0 3
((element ((element
(start_tag (start_tag
(tag_name) @_tag) (tag_name) @_tag)
(text) @markup.heading.1) (text) @markup.heading.1)
(#match? @_tag "^h[1-6]$")) (#match? @_tag "^h[1-6]$"))
;; #FFD700 #000000 1 0 0 2 ;; #FFD700 #000000 1 0 0 0 2
((element ((element
(start_tag (start_tag
(tag_name) @_tag) (tag_name) @_tag)
(text) @markup.strong) (text) @markup.strong)
(#match? @_tag "^(strong|b)$")) (#match? @_tag "^(strong|b)$"))
;; #FF8F40 #000000 0 1 0 2 ;; #FF8F40 #000000 0 1 0 0 2
((element ((element
(start_tag (start_tag
(tag_name) @_tag) (tag_name) @_tag)
(text) @markup.italic) (text) @markup.italic)
(#match? @_tag "^(em|i)$")) (#match? @_tag "^(em|i)$"))
;; #FF6347 #000000 0 0 1 2 ;; #FF6347 #000000 0 0 0 1 2
((element ((element
(start_tag (start_tag
(tag_name) @_tag) (tag_name) @_tag)
(text) @markup.strikethrough) (text) @markup.strikethrough)
(#match? @_tag "^(s|del)$")) (#match? @_tag "^(s|del)$"))
;; #82AAFF #000000 0 0 1 2 ;; #82AAFF #000000 0 0 1 0 2
((element ((element
(start_tag (start_tag
(tag_name) @_tag) (tag_name) @_tag)
(text) @markup.underline) (text) @markup.underline)
(#match? @_tag "^u$")) (#match? @_tag "^u$"))
;; #9ADE7A #000000 0 0 0 2 ;; #9ADE7A #000000 0 0 0 0 2
((element ((element
(start_tag (start_tag
(tag_name) @_tag) (tag_name) @_tag)
(text) @markup.raw) (text) @markup.raw)
(#match? @_tag "^(code|kbd)$")) (#match? @_tag "^(code|kbd)$"))
;; #7dcfff #000000 0 0 1 2 ;; #7dcfff #000000 0 0 1 0 2
((element ((element
(start_tag (start_tag
(tag_name) @_tag) (tag_name) @_tag)
@@ -74,12 +74,12 @@
((attribute ((attribute
(attribute_name) @_attr (attribute_name) @_attr
(quoted_attribute_value (quoted_attribute_value
;; #7dcfff #000000 0 0 1 5 ;; #7dcfff #000000 0 0 1 0 5
(attribute_value) @string.special.url)) (attribute_value) @string.special.url))
(#match? @_attr "^(href|src)$")) (#match? @_attr "^(href|src)$"))
;; Punctuation ;; Punctuation
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
[ [
"<" "<"
">" ">"
@@ -87,19 +87,19 @@
"/>" "/>"
] @tag.delimiter ] @tag.delimiter
;; #FFFFFF #000000 0 1 0 1 ;; #FFFFFF #000000 0 1 0 0 1
"=" @operator "=" @operator
;; #7dcfff #000000 0 0 0 1 ;; #7dcfff #000000 0 0 0 0 1
(tag_name) @tag (tag_name) @tag
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
(erroneous_end_tag_name) @tag.error (erroneous_end_tag_name) @tag.error
;; #FFD700 #000000 0 0 0 1 ;; #FFD700 #000000 0 0 0 0 1
(doctype) @constant (doctype) @constant
;; #9ADE7A #000000 0 0 0 1 ;; #9ADE7A #000000 0 0 0 0 1
(attribute_name) @attribute (attribute_name) @attribute
; Injections ; Injections

View File

@@ -1,34 +1,34 @@
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(section_name (section_name
(text) @type) (text) @type)
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment @spell (comment) @comment @spell
;; #888888 #000000 0 0 0 3 ;; #888888 #000000 0 0 0 0 3
[ [
"[" "["
"]" "]"
] @punctuation.bracket ] @punctuation.bracket
;; #F29668 #000000 0 1 0 1 ;; #F29668 #000000 0 1 0 0 1
"=" @operator "=" @operator
;; #F0F8FF #000000 0 0 0 2 ;; #F0F8FF #000000 0 0 0 0 2
(setting (setting
(setting_name) @property) (setting_name) @property)
;; #F29668 #000000 0 0 0 2 ;; #F29668 #000000 0 0 0 0 2
((setting_value) @boolean ((setting_value) @boolean
(#match? @boolean "^\\s*(true|false|True|False|yes|no|Yes|No|on|off|On|Off|)\\s*$")) (#match? @boolean "^\\s*(true|false|True|False|yes|no|Yes|No|on|off|On|Off|)\\s*$"))
;; #FF8F40 #000000 0 0 0 2 ;; #FF8F40 #000000 0 0 0 0 2
((setting_value) @number ((setting_value) @number
(#match? @number "^\\s*[-+0-9]+\\s*$")) (#match? @number "^\\s*[-+0-9]+\\s*$"))
;; #A6E3A1 #000000 0 0 0 2 ;; #A6E3A1 #000000 0 0 0 0 2
((setting_value) @float ((setting_value) @float
(#match? @float "^\\s*[-+0-9\\.]+\\s*$")) (#match? @float "^\\s*[-+0-9\\.]+\\s*$"))
;; #AAD94C #000000 0 0 0 1 ;; #AAD94C #000000 0 0 0 0 1
(setting_value) @string (setting_value) @string

View File

@@ -2,19 +2,19 @@
; Identifiers ; Identifiers
; ============================================================ ; ============================================================
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(identifier) @variable (identifier) @variable
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
((identifier) @constant ((identifier) @constant
(#match? @constant "^[A-Z_][A-Z0-9_]*$")) (#match? @constant "^[A-Z_][A-Z0-9_]*$"))
;; #F07178 #000000 0 0 0 3 ;; #F07178 #000000 0 0 0 0 3
((identifier) @variable.builtin ((identifier) @variable.builtin
(#match? @variable.builtin (#match? @variable.builtin
"^(arguments|console|window|document|globalThis|process|module|exports)$")) "^(arguments|console|window|document|globalThis|process|module|exports)$"))
;; #59C2FF #000000 0 0 0 3 ;; #59C2FF #000000 0 0 0 0 1
((identifier) @constructor ((identifier) @constructor
(#match? @constructor "^[A-Z][a-zA-Z0-9]*$")) (#match? @constructor "^[A-Z][a-zA-Z0-9]*$"))
@@ -22,21 +22,21 @@
; Properties ; Properties
; ============================================================ ; ============================================================
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
(property_identifier) @property (property_identifier) @property
; ============================================================ ; ============================================================
; Functions ; Functions
; ============================================================ ; ============================================================
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(function_declaration (function_declaration
name: (identifier) @function) name: (identifier) @function)
(function_expression (function_expression
name: (identifier) @function) name: (identifier) @function)
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(method_definition (method_definition
name: (property_identifier) @function.method) name: (property_identifier) @function.method)
@@ -56,11 +56,11 @@
; Function calls ; Function calls
; ------------------------------------------------------------ ; ------------------------------------------------------------
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(call_expression (call_expression
function: (identifier) @function.call) function: (identifier) @function.call)
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(call_expression (call_expression
function: (member_expression function: (member_expression
property: (property_identifier) @function.method)) property: (property_identifier) @function.method))
@@ -69,7 +69,7 @@
; Highlighted definitions & references ; Highlighted definitions & references
; ============================================================ ; ============================================================
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(assignment_expression (assignment_expression
left: [ left: [
(identifier) @name (identifier) @name
@@ -79,23 +79,21 @@
right: [(arrow_function) (function_expression)] right: [(arrow_function) (function_expression)]
) @definition.function ) @definition.function
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(pair (pair
key: (property_identifier) @name key: (property_identifier) @name
value: [(arrow_function) (function_expression)]) @definition.function value: [(arrow_function) (function_expression)]) @definition.function
;; #59C2FF #000000 0 0 0 2 ;; #59C2FF #000000 0 0 0 0 0
( ((call_expression
(call_expression
function: (identifier) @name) @reference.call function: (identifier) @name) @reference.call
(#not-match? @name "^(require)$") (#not-match? @name "^(require)$"))
)
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(new_expression (new_expression
constructor: (_) @name) @reference.class constructor: (_) @name) @reference.class
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
(export_statement value: (assignment_expression left: (identifier) @name right: ([ (export_statement value: (assignment_expression left: (identifier) @name right: ([
(number) (number)
(string) (string)
@@ -111,7 +109,7 @@
; Parameters ; Parameters
; ============================================================ ; ============================================================
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(formal_parameters (formal_parameters
[ [
(identifier) @variable.parameter (identifier) @variable.parameter
@@ -128,7 +126,7 @@
; Keywords (split into semantic groups) ; Keywords (split into semantic groups)
; ============================================================ ; ============================================================
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
; Declarations ; Declarations
[ [
"var" "var"
@@ -138,7 +136,7 @@
"class" "class"
] @keyword.declaration ] @keyword.declaration
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
; Control flow ; Control flow
[ [
"if" "if"
@@ -159,7 +157,7 @@
"extends" "extends"
] @keyword.control ] @keyword.control
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
; Imports / exports ; Imports / exports
[ [
"import" "import"
@@ -168,7 +166,7 @@
"as" "as"
] @keyword.import ] @keyword.import
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
; Operators-as-keywords ; Operators-as-keywords
[ [
"in" "in"
@@ -181,7 +179,7 @@
"yield" "yield"
] @keyword.operator ] @keyword.operator
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
; Modifiers ; Modifiers
[ [
"async" "async"
@@ -194,11 +192,11 @@
; Literals ; Literals
; ============================================================ ; ============================================================
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
(this) @variable.builtin (this) @variable.builtin
(super) @variable.builtin (super) @variable.builtin
;; #D2A6FF #000000 0 0 0 4 ;; #D2A6FF #000000 0 0 0 0 4
[ [
(true) (true)
(false) (false)
@@ -206,27 +204,27 @@
(undefined) (undefined)
] @constant.builtin ] @constant.builtin
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
(number) @number (number) @number
;; #D2A6FF #000000 0 1 0 2 ;; #D2A6FF #000000 0 1 0 0 2
((string) @use_strict ((string) @use_strict
(#match? @use_strict "^['\"]use strict['\"]$")) (#match? @use_strict "^['\"]use strict['\"]$"))
;; #AAD94C #000000 0 0 0 0 ;; #AAD94C #000000 0 0 0 0 0
(string) @string (string) @string
;; #AAD94C #000000 0 0 0 0 ;; #AAD94C #000000 0 0 0 0 0
(template_string) @string.special (template_string) @string.special
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment (comment) @comment
; ============================================================ ; ============================================================
; Operators & punctuation ; Operators & punctuation
; ============================================================ ; ============================================================
;; #F29668 #000000 0 1 0 1 ;; #F29668 #000000 0 1 0 0 1
[ [
"+" "+"
"-" "-"
@@ -273,14 +271,14 @@
"=>" "=>"
] @operator ] @operator
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
[ [
"." "."
"," ","
";" ";"
] @punctuation.delimiter ] @punctuation.delimiter
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
[ [
"(" "("
")" ")"
@@ -290,7 +288,7 @@
"}" "}"
] @punctuation.bracket ] @punctuation.bracket
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(template_substitution (template_substitution
"${" @punctuation.special "${" @punctuation.special
"}" @punctuation.special) "}" @punctuation.special)
@@ -299,18 +297,18 @@
; JSX ; JSX
; ============================================================ ; ============================================================
;; #59C2FF #000000 0 0 0 2 ;; #59C2FF #000000 0 0 0 0 4
(jsx_opening_element (identifier) @tag (#match? @tag "^[a-z][^.]*$")) (jsx_opening_element (identifier) @tag2)
(jsx_closing_element (identifier) @tag (#match? @tag "^[a-z][^.]*$")) (jsx_closing_element (identifier) @tag2)
(jsx_self_closing_element (identifier) @tag (#match? @tag "^[a-z][^.]*$")) (jsx_self_closing_element (identifier) @tag2)
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 3
(jsx_attribute (property_identifier) @attribute) (jsx_attribute (property_identifier) @attribute2)
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 3
(jsx_opening_element (["<" ">"]) @punctuation.bracket) (jsx_opening_element (["<" ">"]) @punctuation.bracket2)
(jsx_closing_element (["</" ">"]) @punctuation.bracket) (jsx_closing_element (["</" ">"]) @punctuation.bracket2)
(jsx_self_closing_element (["<" "/>"]) @punctuation.bracket) (jsx_self_closing_element (["<" "/>"]) @punctuation.bracket2)
; Injections ; Injections

View File

@@ -1,22 +1,22 @@
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
(pair (pair
key: (_) @string.special.key) key: (_) @string.special.key)
;; #AAD94C #000000 0 0 0 1 ;; #AAD94C #000000 0 0 0 0 1
(string) @string (string) @string
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(number) @number (number) @number
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
[ [
(null) (null)
(true) (true)
(false) (false)
] @constant.builtin ] @constant.builtin
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(escape_sequence) @escape (escape_sequence) @escape
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment (comment) @comment

22
grammar/jsonc.scm Normal file
View File

@@ -0,0 +1,22 @@
;; #D2A6FF #000000 0 0 0 0 2
(pair
key: (_) @string.special.key)
;; #AAD94C #000000 0 0 0 0 1
(string) @string
;; #7dcfff #000000 0 0 0 0 2
(number) @number
;; #F07178 #000000 0 0 0 0 1
[
(null)
(true)
(false)
] @constant.builtin
;; #7dcfff #000000 0 0 0 0 2
(escape_sequence) @escape
;; #99ADBF #000000 0 1 0 0 1
(comment) @comment

View File

@@ -2,19 +2,19 @@
; Identifiers ; Identifiers
; ============================================================ ; ============================================================
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(identifier) @variable (identifier) @variable
;; #C9B4FF #000000 0 0 0 2 ;; #C9B4FF #000000 0 0 0 0 2
((identifier) @constant ((identifier) @constant
(#match? @constant "^[A-Z][A-Z_0-9]*$")) (#match? @constant "^[A-Z][A-Z_0-9]*$"))
;; #F28FAD #000000 0 0 0 3 ;; #F28FAD #000000 0 0 0 0 3
((identifier) @variable.builtin ((identifier) @variable.builtin
(#match? @variable.builtin "^self$")) (#match? @variable.builtin "^self$"))
; Attributes (generic parameters) ; Attributes (generic parameters)
;; #7CD5CF #000000 0 0 0 2 ;; #7CD5CF #000000 0 0 0 0 2
(variable_list (variable_list
(attribute (attribute
"<" @punctuation.bracket "<" @punctuation.bracket
@@ -25,30 +25,30 @@
; Control flow & keywords ; Control flow & keywords
; ============================================================ ; ============================================================
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
"return" @keyword.return "return" @keyword.return
;; #FF9E64 #000000 0 0 0 2 ;; #FF9E64 #000000 0 0 0 0 2
[ [
"goto" "goto"
"in" "in"
"local" "local"
] @keyword ] @keyword
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
(label_statement) @label (label_statement) @label
;; #FF9E64 #000000 0 0 0 2 ;; #FF9E64 #000000 0 0 0 0 2
(break_statement) @keyword (break_statement) @keyword
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
(do_statement (do_statement
[ [
"do" "do"
"end" "end"
] @keyword) ] @keyword)
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
(while_statement (while_statement
[ [
"while" "while"
@@ -56,14 +56,14 @@
"end" "end"
] @repeat) ] @repeat)
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
(repeat_statement (repeat_statement
[ [
"repeat" "repeat"
"until" "until"
] @repeat) ] @repeat)
;; #FFB870 #000000 0 0 0 2 ;; #FFB870 #000000 0 0 0 0 2
(if_statement (if_statement
[ [
"if" "if"
@@ -73,7 +73,7 @@
"end" "end"
] @conditional) ] @conditional)
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
(elseif_statement (elseif_statement
[ [
"elseif" "elseif"
@@ -81,14 +81,14 @@
"end" "end"
] @conditional) ] @conditional)
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
(else_statement (else_statement
[ [
"else" "else"
"end" "end"
] @conditional) ] @conditional)
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
(for_statement (for_statement
[ [
"for" "for"
@@ -96,14 +96,14 @@
"end" "end"
] @repeat) ] @repeat)
;; #FFB870 #000000 0 0 0 2 ;; #FFB870 #000000 0 0 0 0 2
(function_declaration (function_declaration
[ [
"function" "function"
"end" "end"
] @keyword.function) ] @keyword.function)
;; #FFB870 #000000 0 0 0 2 ;; #FFB870 #000000 0 0 0 0 2
(function_definition (function_definition
[ [
"function" "function"
@@ -114,13 +114,13 @@
; Operators ; Operators
; ============================================================ ; ============================================================
;; #6BD9DF #000000 0 1 0 1 ;; #6BD9DF #000000 0 1 0 0 1
(binary_expression operator: _ @operator) (binary_expression operator: _ @operator)
;; #6BD9DF #000000 0 1 0 1 ;; #6BD9DF #000000 0 1 0 0 1
(unary_expression operator: _ @operator) (unary_expression operator: _ @operator)
;; #F29CC3 #000000 0 0 0 1 ;; #F29CC3 #000000 0 0 0 0 1
[ [
"and" "and"
"not" "not"
@@ -131,7 +131,7 @@
; Punctuation ; Punctuation
; ============================================================ ; ============================================================
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
[ [
";" ";"
":" ":"
@@ -140,7 +140,7 @@
] @punctuation.delimiter ] @punctuation.delimiter
; Brackets ; Brackets
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
[ [
"(" "("
")" ")"
@@ -154,13 +154,13 @@
; Tables & fields ; Tables & fields
; ============================================================ ; ============================================================
;; #9AD4FF #000000 0 0 0 1 ;; #9AD4FF #000000 0 0 0 0 1
(field name: (identifier) @field) (field name: (identifier) @field)
;; #9AD4FF #000000 0 0 0 1 ;; #9AD4FF #000000 0 0 0 0 1
(dot_index_expression field: (identifier) @field) (dot_index_expression field: (identifier) @field)
;; #7CD5CF #000000 0 0 0 1 ;; #7CD5CF #000000 0 0 0 0 1
(table_constructor (table_constructor
[ [
"{" "{"
@@ -171,10 +171,10 @@
; Functions ; Functions
; ============================================================ ; ============================================================
;; #FFC877 #000000 0 0 0 3 ;; #FFC877 #000000 0 0 0 0 3
(parameters (identifier) @parameter) (parameters (identifier) @parameter)
;; #FFC877 #000000 0 0 0 3 ;; #FFC877 #000000 0 0 0 0 3
(function_declaration (function_declaration
name: [ name: [
(identifier) @function (identifier) @function
@@ -182,12 +182,12 @@
field: (identifier) @function) field: (identifier) @function)
]) ])
;; #FFC877 #000000 0 0 0 3 ;; #FFC877 #000000 0 0 0 0 3
(function_declaration (function_declaration
name: (method_index_expression name: (method_index_expression
method: (identifier) @method)) method: (identifier) @method))
;; #FFC877 #000000 0 0 0 3 ;; #FFC877 #000000 0 0 0 0 3
(assignment_statement (assignment_statement
(variable_list . (variable_list .
name: [ name: [
@@ -198,14 +198,14 @@
(expression_list . (expression_list .
value: (function_definition))) value: (function_definition)))
;; #FFC877 #000000 0 0 0 3 ;; #FFC877 #000000 0 0 0 0 3
(table_constructor (table_constructor
(field (field
name: (identifier) @function name: (identifier) @function
value: (function_definition))) value: (function_definition)))
; Function calls ; Function calls
;; #78C2FF #000000 0 0 0 2 ;; #78C2FF #000000 0 0 0 0 2
(function_call (function_call
name: [ name: [
(identifier) @function.call (identifier) @function.call
@@ -216,7 +216,7 @@
]) ])
; Highlighted definitions & references ; Highlighted definitions & references
;; #FFC877 #000000 0 0 0 3 ;; #FFC877 #000000 0 0 0 0 3
(function_declaration (function_declaration
name: [ name: [
(identifier) @name (identifier) @name
@@ -224,12 +224,12 @@
field: (identifier) @name) field: (identifier) @name)
]) @definition.function ]) @definition.function
;; #FFC877 #000000 0 0 0 3 ;; #FFC877 #000000 0 0 0 0 3
(function_declaration (function_declaration
name: (method_index_expression name: (method_index_expression
method: (identifier) @name)) @definition.method method: (identifier) @name)) @definition.method
;; #FFC877 #000000 0 0 0 3 ;; #FFC877 #000000 0 0 0 0 3
(assignment_statement (assignment_statement
(variable_list . (variable_list .
name: [ name: [
@@ -240,13 +240,13 @@
(expression_list . (expression_list .
value: (function_definition))) @definition.function value: (function_definition))) @definition.function
;; #FFC877 #000000 0 0 0 3 ;; #FFC877 #000000 0 0 0 0 3
(table_constructor (table_constructor
(field (field
name: (identifier) @name name: (identifier) @name
value: (function_definition))) @definition.function value: (function_definition))) @definition.function
;; #78C2FF #000000 0 0 0 2 ;; #78C2FF #000000 0 0 0 0 2
(function_call (function_call
name: [ name: [
(identifier) @name (identifier) @name
@@ -257,7 +257,7 @@
]) @reference.call ]) @reference.call
; Builtins ; Builtins
;; #F28FAD #000000 0 0 0 2 ;; #F28FAD #000000 0 0 0 0 2
(function_call (function_call
(identifier) @function.builtin (identifier) @function.builtin
(#match? @function.builtin "^(assert|collectgarbage|dofile|error|getfenv|getmetatable|ipairs|load|loadfile|loadstring|module|next|pairs|pcall|print|rawequal|rawget|rawset|required|select|setfenv|setmetatable|tonumber|tostring|type|unpack|xpcall)$")) (#match? @function.builtin "^(assert|collectgarbage|dofile|error|getfenv|getmetatable|ipairs|load|loadfile|loadstring|module|next|pairs|pcall|print|rawequal|rawget|rawset|required|select|setfenv|setmetatable|tonumber|tostring|type|unpack|xpcall)$"))
@@ -266,22 +266,22 @@
; Literals & constants ; Literals & constants
; ============================================================ ; ============================================================
;; #B8E986 #000000 0 0 0 5 ;; #B8E986 #000000 0 0 0 0 5
(number) @number (number) @number
;; #A6E3A1 #000000 0 0 0 5 ;; #A6E3A1 #000000 0 0 0 0 5
(string) @string (string) @string
;; #A6E3A1 #000000 0 0 0 6 ;; #A6E3A1 #000000 0 0 0 0 6
(escape_sequence) @string.escape (escape_sequence) @string.escape
;; #C9B4FF #000000 0 0 0 2 ;; #C9B4FF #000000 0 0 0 0 2
(vararg_expression) @constant (vararg_expression) @constant
;; #C9B4FF #000000 0 0 0 2 ;; #C9B4FF #000000 0 0 0 0 2
(nil) @constant.builtin (nil) @constant.builtin
;; #C2E8FF #000000 0 0 0 2 ;; #C2E8FF #000000 0 0 0 0 2
[ [
(false) (false)
(true) (true)
@@ -291,17 +291,17 @@
; Comments & directives ; Comments & directives
; ============================================================ ; ============================================================
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment (comment) @comment
;; #7CD5CF #000000 0 0 0 1 ;; #7CD5CF #000000 0 0 0 0 1
(hash_bang_line) @preproc (hash_bang_line) @preproc
; ============================================================ ; ============================================================
; Injections ; Injections
; ============================================================ ; ============================================================
;; #7CD5CF #000000 0 1 0 2 ;; #7CD5CF #000000 0 1 0 0 2
((function_call ((function_call
name: [ name: [
(identifier) @_cdef_identifier (identifier) @_cdef_identifier

View File

@@ -1,4 +1,4 @@
;; #9CDCFE #000000 0 0 0 3 ;; #9CDCFE #000000 0 0 0 0 3
[ [
"(" "("
")" ")"
@@ -6,7 +6,7 @@
"}" "}"
] @punctuation.bracket ] @punctuation.bracket
;; #C2E8FF #000000 0 1 0 2 ;; #C2E8FF #000000 0 1 0 0 2
[ [
":" ":"
"&:" "&:"
@@ -18,21 +18,21 @@
"," ","
] @punctuation.delimiter ] @punctuation.delimiter
;; #FFD700 #000000 0 0 0 2 ;; #FFD700 #000000 0 0 0 0 2
[ [
"$" "$"
"$$" "$$"
] @punctuation.special ] @punctuation.special
;; #FF8F40 #000000 0 0 0 2 ;; #FF8F40 #000000 0 0 0 0 2
(automatic_variable (automatic_variable
[ "@" "%" "<" "?" "^" "+" "/" "*" "D" "F"] @punctuation.special) [ "@" "%" "<" "?" "^" "+" "/" "*" "D" "F"] @punctuation.special)
;; #FF6347 #000000 0 0 0 2 ;; #FF6347 #000000 0 0 0 0 2
(automatic_variable (automatic_variable
"/" @error . ["D" "F"]) "/" @error . ["D" "F"])
;; #F29668 #000000 0 1 0 2 ;; #F29668 #000000 0 1 0 0 2
[ [
"=" "="
":=" ":="
@@ -45,17 +45,17 @@
"+" "+"
] @operator ] @operator
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
[ [
(text) (text)
(string) (string)
(raw_text) (raw_text)
] @string ] @string
;; #9AD4FF #000000 0 0 0 2 ;; #9AD4FF #000000 0 0 0 0 2
(variable_assignment (word) @string) (variable_assignment (word) @string)
;; #7AA2F7 #000000 0 0 0 1 ;; #7AA2F7 #000000 0 0 0 0 1
[ [
"ifeq" "ifeq"
"ifneq" "ifneq"
@@ -68,10 +68,10 @@
"and" "and"
] @conditional ] @conditional
;; #9ADE7A #000000 0 0 0 2 ;; #9ADE7A #000000 0 0 0 0 2
"foreach" @repeat "foreach" @repeat
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
[ [
"define" "define"
"endef" "endef"
@@ -84,14 +84,14 @@
; "load" ; "load"
] @keyword ] @keyword
;; #C6B5FF #000000 0 0 0 2 ;; #C6B5FF #000000 0 0 0 0 2
[ [
"include" "include"
"sinclude" "sinclude"
"-include" "-include"
] @include ] @include
;; #82AAFF #000000 0 0 0 2 ;; #82AAFF #000000 0 0 0 0 2
[ [
"subst" "subst"
"patsubst" "patsubst"
@@ -122,70 +122,70 @@
"shell" "shell"
] @keyword.function ] @keyword.function
;; #FF9D5C #000000 0 0 0 2 ;; #FF9D5C #000000 0 0 0 0 2
[ [
"error" "error"
"warning" "warning"
"info" "info"
] @exception ] @exception
;; #B8E986 #000000 0 0 0 2 ;; #B8E986 #000000 0 0 0 0 2
(variable_assignment (variable_assignment
name: (word) @constant) name: (word) @constant)
;; #B8E986 #000000 0 0 0 2 ;; #B8E986 #000000 0 0 0 0 2
(variable_reference (variable_reference
(word) @constant) (word) @constant)
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment (comment) @comment
;; #F28FAD #000000 0 0 0 2 ;; #F28FAD #000000 0 0 0 0 2
((word) @clean @string.regex ((word) @clean @string.regex
(#match? @clean "[%\*\?]")) (#match? @clean "[%\*\?]"))
;; #F07178 #000000 0 0 0 2 ;; #F07178 #000000 0 0 0 0 2
(function_call (function_call
function: "error" function: "error"
(arguments (text) @text.danger)) (arguments (text) @text.danger))
;; #FFC877 #000000 0 0 0 2 ;; #FFC877 #000000 0 0 0 0 2
(function_call (function_call
function: "warning" function: "warning"
(arguments (text) @text.warning)) (arguments (text) @text.warning))
;; #61AFEF #000000 0 0 0 2 ;; #61AFEF #000000 0 0 0 0 2
(function_call (function_call
function: "info" function: "info"
(arguments (text) @text.note)) (arguments (text) @text.note))
;; #95E6CB #000000 0 0 0 2 ;; #95E6CB #000000 0 0 0 0 2
[ [
"VPATH" "VPATH"
".RECIPEPREFIX" ".RECIPEPREFIX"
] @constant.builtin ] @constant.builtin
;; #95E6CB #000000 0 0 0 2 ;; #95E6CB #000000 0 0 0 0 2
(variable_assignment (variable_assignment
name: (word) @clean @constant.builtin name: (word) @clean @constant.builtin
(#match? @clean "^(AR|AS|CC|CXX|CPP|FC|M2C|PC|CO|GET|LEX|YACC|LINT|MAKEINFO|TEX|TEXI2DVI|WEAVE|CWEAVE|TANGLE|CTANGLE|RM|ARFLAGS|ASFLAGS|CFLAGS|CXXFLAGS|COFLAGS|CPPFLAGS|FFLAGS|GFLAGS|LDFLAGS|LDLIBS|LFLAGS|YFLAGS|PFLAGS|RFLAGS|LINTFLAGS|PRE_INSTALL|POST_INSTALL|NORMAL_INSTALL|PRE_UNINSTALL|POST_UNINSTALL|NORMAL_UNINSTALL|MAKEFILE_LIST|MAKE_RESTARTS|MAKE_TERMOUT|MAKE_TERMERR|\\.DEFAULT_GOAL|\\.RECIPEPREFIX|\\.EXTRA_PREREQS)$")) (#match? @clean "^(AR|AS|CC|CXX|CPP|FC|M2C|PC|CO|GET|LEX|YACC|LINT|MAKEINFO|TEX|TEXI2DVI|WEAVE|CWEAVE|TANGLE|CTANGLE|RM|ARFLAGS|ASFLAGS|CFLAGS|CXXFLAGS|COFLAGS|CPPFLAGS|FFLAGS|GFLAGS|LDFLAGS|LDLIBS|LFLAGS|YFLAGS|PFLAGS|RFLAGS|LINTFLAGS|PRE_INSTALL|POST_INSTALL|NORMAL_INSTALL|PRE_UNINSTALL|POST_UNINSTALL|NORMAL_UNINSTALL|MAKEFILE_LIST|MAKE_RESTARTS|MAKE_TERMOUT|MAKE_TERMERR|\\.DEFAULT_GOAL|\\.RECIPEPREFIX|\\.EXTRA_PREREQS)$"))
;; #95E6CB #000000 0 0 0 2 ;; #95E6CB #000000 0 0 0 0 2
(variable_reference (variable_reference
(word) @clean @constant.builtin (word) @clean @constant.builtin
(#match? @clean "^(AR|AS|CC|CXX|CPP|FC|M2C|PC|CO|GET|LEX|YACC|LINT|MAKEINFO|TEX|TEXI2DVI|WEAVE|CWEAVE|TANGLE|CTANGLE|RM|ARFLAGS|ASFLAGS|CFLAGS|CXXFLAGS|COFLAGS|CPPFLAGS|FFLAGS|GFLAGS|LDFLAGS|LDLIBS|LFLAGS|YFLAGS|PFLAGS|RFLAGS|LINTFLAGS|PRE_INSTALL|POST_INSTALL|NORMAL_INSTALL|PRE_UNINSTALL|POST_UNINSTALL|NORMAL_UNINSTALL|MAKEFILE_LIST|MAKE_RESTARTS|MAKE_TERMOUT|MAKE_TERMERR|\\.DEFAULT_GOAL|\\.RECIPEPREFIX|\\.EXTRA_PREREQS\\.VARIABLES|\\.FEATURES|\\.INCLUDE_DIRS|\\.LOADED)$")) (#match? @clean "^(AR|AS|CC|CXX|CPP|FC|M2C|PC|CO|GET|LEX|YACC|LINT|MAKEINFO|TEX|TEXI2DVI|WEAVE|CWEAVE|TANGLE|CTANGLE|RM|ARFLAGS|ASFLAGS|CFLAGS|CXXFLAGS|COFLAGS|CPPFLAGS|FFLAGS|GFLAGS|LDFLAGS|LDLIBS|LFLAGS|YFLAGS|PFLAGS|RFLAGS|LINTFLAGS|PRE_INSTALL|POST_INSTALL|NORMAL_INSTALL|PRE_UNINSTALL|POST_UNINSTALL|NORMAL_UNINSTALL|MAKEFILE_LIST|MAKE_RESTARTS|MAKE_TERMOUT|MAKE_TERMERR|\\.DEFAULT_GOAL|\\.RECIPEPREFIX|\\.EXTRA_PREREQS\\.VARIABLES|\\.FEATURES|\\.INCLUDE_DIRS|\\.LOADED)$"))
;; #C792EA #000000 0 0 0 2 ;; #C792EA #000000 0 0 0 0 2
(targets (targets
(word) @constant.macro (word) @constant.macro
(#match? @constant.macro "^(all|install|install-html|install-dvi|install-pdf|install-ps|uninstall|install-strip|clean|distclean|mostlyclean|maintainer-clean|TAGS|info|dvi|html|pdf|ps|dist|check|installcheck|installdirs)$")) (#match? @constant.macro "^(all|install|install-html|install-dvi|install-pdf|install-ps|uninstall|install-strip|clean|distclean|mostlyclean|maintainer-clean|TAGS|info|dvi|html|pdf|ps|dist|check|installcheck|installdirs)$"))
;; #C792EA #000000 0 0 0 2 ;; #C792EA #000000 0 0 0 0 2
(targets (targets
(word) @constant.macro (word) @constant.macro
(#match? @constant.macro "^(all|install|install-html|install-dvi|install-pdf|install-ps|uninstall|install-strip|clean|distclean|mostlyclean|maintainer-clean|TAGS|info|dvi|html|pdf|ps|dist|check|installcheck|installdirs)$")) (#match? @constant.macro "^(all|install|install-html|install-dvi|install-pdf|install-ps|uninstall|install-strip|clean|distclean|mostlyclean|maintainer-clean|TAGS|info|dvi|html|pdf|ps|dist|check|installcheck|installdirs)$"))
;; #C792EA #000000 0 0 0 2 ;; #C792EA #000000 0 0 0 0 2
(targets (targets
(word) @constant.macro (word) @constant.macro
(#match? @constant.macro "^\\.(PHONY|SUFFIXES|DEFAULT|PRECIOUS|INTERMEDIATE|SECONDARY|SECONDEXPANSION|DELETE_ON_ERROR|IGNORE|LOW_RESOLUTION_TIME|SILENT|EXPORT_ALL_VARIABLES|NOTPARALLEL|ONESHELL|POSIX)$")) (#match? @constant.macro "^\\.(PHONY|SUFFIXES|DEFAULT|PRECIOUS|INTERMEDIATE|SECONDARY|SECONDEXPANSION|DELETE_ON_ERROR|IGNORE|LOW_RESOLUTION_TIME|SILENT|EXPORT_ALL_VARIABLES|NOTPARALLEL|ONESHELL|POSIX)$"))

23
grammar/man.scm Normal file
View File

@@ -0,0 +1,23 @@
;; #82AAFF #000000 1 0 1 0 2
(title) @markup.heading.1
;; #ccefc9 #000000 0 0 0 0 0
(section_title) @markup.heading.2
;; #FF8F40 #000000 1 0 0 0 2
(subsection_title) @markup.heading.3
;; #AAD94C #000000 0 0 0 0 3
(option) @variable.parameter
;; #FFD700 #000000 1 0 0 0 3
(reference) @markup.link.label
;; #C792EA #000000 0 0 0 0 3
(footer) @markup.heading
(section_heading
(section_title) @_title
;; #FFD700 #000000 1 0 0 0 1
(block) @injection.content
(#match? @_title "SYNOPSIS"))

View File

@@ -1,9 +1,9 @@
;; #82AAFF #000000 1 0 1 4 ;; #82AAFF #000000 1 0 1 0 4
(setext_heading (setext_heading
(paragraph) @markup.heading.1 (paragraph) @markup.heading.1
(setext_h1_underline) @markup.heading.1) (setext_h1_underline) @markup.heading.1)
;; #82AAFF #000000 1 0 1 4 ;; #82AAFF #000000 1 0 1 0 4
(setext_heading (setext_heading
(paragraph) @markup.heading.2 (paragraph) @markup.heading.2
(setext_h2_underline) @markup.heading.2) (setext_h2_underline) @markup.heading.2)
@@ -14,30 +14,30 @@
(atx_heading (atx_heading
(atx_h2_marker)) @markup.heading.2 (atx_h2_marker)) @markup.heading.2
;; #82AAFF #000000 1 0 0 4 ;; #82AAFF #000000 1 0 0 0 4
(atx_heading (atx_heading
(atx_h3_marker)) @markup.heading.3 (atx_h3_marker)) @markup.heading.3
;; #82AAFF #000000 1 0 0 4 ;; #82AAFF #000000 1 0 0 0 4
(atx_heading (atx_heading
(atx_h4_marker)) @markup.heading.4 (atx_h4_marker)) @markup.heading.4
;; #82AAFF #000000 1 0 0 4 ;; #82AAFF #000000 1 0 0 0 4
(atx_heading (atx_heading
(atx_h5_marker)) @markup.heading.5 (atx_h5_marker)) @markup.heading.5
;; #82AAFF #000000 1 0 0 4 ;; #82AAFF #000000 1 0 0 0 4
(atx_heading (atx_heading
(atx_h6_marker)) @markup.heading.6 (atx_h6_marker)) @markup.heading.6
;; #82AAFF #000000 0 0 0 4 ;; #82AAFF #000000 0 0 0 0 4
(info_string) @label (info_string) @label
;; #FF6347 #000000 0 0 0 4 ;; #FF6347 #000000 0 0 0 0 4
(pipe_table_header (pipe_table_header
(pipe_table_cell) @markup.heading) (pipe_table_cell) @markup.heading)
;; #FF8F40 #000000 0 0 0 4 ;; #FF8F40 #000000 0 0 0 0 4
(pipe_table_header (pipe_table_header
"|" @punctuation.special) "|" @punctuation.special)
@@ -49,7 +49,7 @@
(pipe_table_delimiter_cell) @punctuation.special (pipe_table_delimiter_cell) @punctuation.special
;; #AAD94C #000000 0 0 0 2 ;; #AAD94C #000000 0 0 0 0 2
(indented_code_block) @markup.raw.block (indented_code_block) @markup.raw.block
(fenced_code_block) @markup.raw.block (fenced_code_block) @markup.raw.block
@@ -61,21 +61,21 @@
(info_string (info_string
(language) @label)) (language) @label))
;; #7dcfff #000000 0 0 1 6 ;; #7dcfff #000000 0 0 1 0 6
(link_destination) @markup.link.url (link_destination) @markup.link.url
;; #7dcfff #000000 0 0 1 6 ;; #7dcfff #000000 0 0 1 0 6
[ [
(link_title) (link_title)
(link_label) (link_label)
] @markup.link.label ] @markup.link.label
;; #FF8F40 #000000 0 0 0 4 ;; #FF8F40 #000000 0 0 0 0 4
((link_label) ((link_label)
. .
":" @punctuation.delimiter) ":" @punctuation.delimiter)
;; #9ADE7A #000000 0 0 0 4 ;; #9ADE7A #000000 0 0 0 0 4
[ [
(list_marker_plus) (list_marker_plus)
(list_marker_minus) (list_marker_minus)
@@ -86,10 +86,10 @@
(thematic_break) @punctuation.special (thematic_break) @punctuation.special
;; #FF8F40 #000000 0 0 0 4 ;; #FF8F40 #000000 0 0 0 0 4
(task_list_marker_unchecked) @markup.list.unchecked (task_list_marker_unchecked) @markup.list.unchecked
;; #AAD94C #000000 0 0 0 4 ;; #AAD94C #000000 0 0 0 0 4
(task_list_marker_checked) @markup.list.checked (task_list_marker_checked) @markup.list.checked
[ [
@@ -102,7 +102,7 @@
(block_quote_marker) (block_quote_marker)
] @punctuation.special ] @punctuation.special
;; #AAD94C #000000 0 0 0 6 ;; #AAD94C #000000 0 0 0 0 6
(backslash_escape) @string.escape (backslash_escape) @string.escape
(fenced_code_block (fenced_code_block
@@ -297,6 +297,12 @@
;; !gomod ;; !gomod
(code_fence_content) @injection.gomod) (code_fence_content) @injection.gomod)
(fenced_code_block
(info_string
(language) @injection.language (#match? @injection.language "^man$"))
;; !man
(code_fence_content) @injection.man)
(fenced_code_block (fenced_code_block
(info_string (info_string
(language) @injection.language (#match? @injection.language "^cabal$")) (language) @injection.language (#match? @injection.language "^cabal$"))

View File

@@ -1,22 +1,22 @@
;; #AAD94C #000000 0 0 0 0 ;; #AAD94C #000000 0 0 0 0 0
(code_span) @markup.raw (code_span) @markup.raw
;; #FF8F40 #000000 0 1 0 1 ;; #FF8F40 #000000 0 1 0 0 1
(emphasis) @markup.italic (emphasis) @markup.italic
;; #FFD700 #000000 1 0 0 1 ;; #FFD700 #000000 1 0 0 0 1
(strong_emphasis) @markup.strong (strong_emphasis) @markup.strong
;; #FF6347 #000000 0 0 1 1 ;; #FF6347 #000000 0 0 0 1 1
(strikethrough) @markup.strikethrough (strikethrough) @markup.strikethrough
;; #7dcfff #000000 0 0 0 1 ;; #7dcfff #000000 0 0 0 0 1
[ [
(backslash_escape) (backslash_escape)
(hard_line_break) (hard_line_break)
] @string.escape ] @string.escape
;; #7dcfff #000000 0 0 1 1 ;; #7dcfff #000000 0 0 1 0 1
(inline_link (inline_link
[ [
"[" "["
@@ -26,7 +26,7 @@
")" ")"
] @markup.link) ] @markup.link)
;; #7dcfff #000000 0 0 1 1 ;; #7dcfff #000000 0 0 1 0 1
[ [
(link_label) (link_label)
(link_text) (link_text)
@@ -34,15 +34,15 @@
(image_description) (image_description)
] @markup.link.label ] @markup.link.label
;; #7dcfff #000000 0 0 1 1 ;; #7dcfff #000000 0 0 1 0 1
((inline_link ((inline_link
(link_destination) @_url) @_label) (link_destination) @_url) @_label)
;; #7dcfff #000000 0 0 1 1 ;; #7dcfff #000000 0 0 1 0 1
((image ((image
(link_destination) @_url) @_label) (link_destination) @_url) @_label)
;; #7dcfff #000000 0 0 1 1 ;; #7dcfff #000000 0 0 1 0 1
(image (image
[ [
"!" "!"
@@ -53,7 +53,7 @@
")" ")"
] @markup.link) ] @markup.link)
;; #7dcfff #000000 0 0 1 1 ;; #7dcfff #000000 0 0 1 0 1
(full_reference_link (full_reference_link
[ [
"[" "["
@@ -61,30 +61,30 @@
(link_label) (link_label)
] @markup.link) ] @markup.link)
;; #7dcfff #000000 0 0 1 1 ;; #7dcfff #000000 0 0 1 0 1
(collapsed_reference_link (collapsed_reference_link
[ [
"[" "["
"]" "]"
] @markup.link) ] @markup.link)
;; #7dcfff #000000 0 0 1 1 ;; #7dcfff #000000 0 0 1 0 1
(shortcut_link (shortcut_link
[ [
"[" "["
"]" "]"
] @markup.link) ] @markup.link)
;; #7dcfff #000000 0 0 1 1 ;; #7dcfff #000000 0 0 1 0 1
[ [
(link_destination) (link_destination)
(uri_autolink) (uri_autolink)
(email_autolink) (email_autolink)
] @markup.link.url @nospell ] @markup.link.url @nospell
;; #7dcfff #000000 0 0 1 1 ;; #7dcfff #000000 0 0 1 0 1
(uri_autolink) @_url (uri_autolink) @_url
;; #FF8F40 #000000 0 0 0 0 ;; #FF8F40 #000000 0 0 0 0 0
;; !html ;; !html
(html_tag) @injection.html (html_tag) @injection.html

View File

@@ -1,49 +1,49 @@
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment (comment) @comment
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(number) @number (number) @number
(metric) @number (metric) @number
;; !regex ;; !regex
(regex) @regex (regex) @regex
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(variable) @variable (variable) @variable
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
(modifier) @operator (modifier) @operator
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(simple_directive (simple_directive
name: (directive) @function) name: (directive) @function)
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(block_directive (block_directive
name: (directive) @function) name: (directive) @function)
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(lua_block_directive (lua_block_directive
"access_by_lua_block" @function) "access_by_lua_block" @function)
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
((generic) @constant.builtin ((generic) @constant.builtin
(#match? @constant.builtin "^(off|on)$")) (#match? @constant.builtin "^(off|on)$"))
;; #AAD94C #000000 0 0 0 2 ;; #AAD94C #000000 0 0 0 0 2
(generic) @string (generic) @string
(string) @string (string) @string
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(scheme) @string (scheme) @string
(ipv4) @number (ipv4) @number
;; #888888 #000000 0 1 0 3 ;; #888888 #000000 0 1 0 0 3
[ [
";" ";"
] @delimiter ] @delimiter
;; #888888 #000000 0 0 0 3 ;; #888888 #000000 0 0 0 0 3
[ [
"{" "{"
"}" "}"

View File

@@ -3,7 +3,7 @@
;; Coolwarm balanced palette (blue / teal / purple / orange) ;; Coolwarm balanced palette (blue / teal / purple / orange)
;; ========================================================= ;; =========================================================
;; #FF9D5C #000000 0 0 0 1 ;; #FF9D5C #000000 0 0 0 0 1
;; Keywords (logic / flow) ;; Keywords (logic / flow)
[ [
"and" "and"
@@ -13,13 +13,13 @@
"xor" "xor"
] @keyword.operator ] @keyword.operator
;; #FF9D5C #000000 0 0 0 1 ;; #FF9D5C #000000 0 0 0 0 1
[ [
"fn" "fn"
"function" "function"
] @keyword.function ] @keyword.function
;; #FF9D5C #000000 0 0 0 1 ;; #FF9D5C #000000 0 0 0 0 1
[ [
"clone" "clone"
"declare" "declare"
@@ -36,7 +36,7 @@
"unset" "unset"
] @keyword ] @keyword
;; #6FB3FF #000000 0 0 0 1 ;; #6FB3FF #000000 0 0 0 0 1
[ [
"enum" "enum"
"class" "class"
@@ -45,7 +45,7 @@
"trait" "trait"
] @keyword.type ] @keyword.type
;; #FF9D5C #000000 0 0 0 1 ;; #FF9D5C #000000 0 0 0 0 1
[ [
"abstract" "abstract"
"const" "const"
@@ -57,7 +57,7 @@
"static" "static"
] @keyword.modifier ] @keyword.modifier
;; #FF9D5C #000000 0 0 0 1 ;; #FF9D5C #000000 0 0 0 0 1
[ [
"return" "return"
"exit" "exit"
@@ -65,7 +65,7 @@
"yield from" "yield from"
] @keyword.return ] @keyword.return
;; #FF9D5C #000000 0 0 0 1 ;; #FF9D5C #000000 0 0 0 0 1
[ [
"case" "case"
"else" "else"
@@ -78,7 +78,7 @@
"??" "??"
] @keyword.conditional ] @keyword.conditional
;; #FF9D5C #000000 0 0 0 1 ;; #FF9D5C #000000 0 0 0 0 1
[ [
"break" "break"
"continue" "continue"
@@ -91,7 +91,7 @@
"while" "while"
] @keyword.repeat ] @keyword.repeat
;; #FF9D5C #000000 0 0 0 1 ;; #FF9D5C #000000 0 0 0 0 1
[ [
"catch" "catch"
"finally" "finally"
@@ -99,7 +99,7 @@
"try" "try"
] @keyword.exception ] @keyword.exception
;; #8BD5CA #000000 0 0 0 1 ;; #8BD5CA #000000 0 0 0 0 1
[ [
"include_once" "include_once"
"include" "include"
@@ -108,7 +108,7 @@
"use" "use"
] @keyword.import ] @keyword.import
;; #B0BEC5 #000000 0 0 0 1 ;; #B0BEC5 #000000 0 0 0 0 1
[ [
"," ","
";" ";"
@@ -116,7 +116,7 @@
"\\" "\\"
] @punctuation.delimiter ] @punctuation.delimiter
;; #B0BEC5 #000000 0 0 0 1 ;; #B0BEC5 #000000 0 0 0 0 1
[ [
(php_tag) (php_tag)
(php_end_tag) (php_end_tag)
@@ -129,7 +129,7 @@
"#[" "#["
] @punctuation.bracket ] @punctuation.bracket
;; #F29668 #000000 0 1 0 1 ;; #F29668 #000000 0 1 0 0 1
[ [
"=" "="
"." "."
@@ -181,30 +181,30 @@
"::" "::"
] @operator ] @operator
;; #7DCFFF #000000 0 0 0 1 ;; #7DCFFF #000000 0 0 0 0 1
(variable_name) @variable (variable_name) @variable
;; #C792EA #000000 0 0 0 1 ;; #C792EA #000000 0 0 0 0 1
((name) @constant ((name) @constant
(#lua-match? @constant "^_?[A-Z][A-Z%d_]*$")) (#lua-match? @constant "^_?[A-Z][A-Z%d_]*$"))
;; #C792EA #000000 0 0 0 1 ;; #C792EA #000000 0 0 0 0 1
((name) @constant.builtin ((name) @constant.builtin
(#lua-match? @constant.builtin "^__[A-Z][A-Z%d_]+__$")) (#lua-match? @constant.builtin "^__[A-Z][A-Z%d_]+__$"))
;; #6FB3FF #000000 0 0 0 1 ;; #6FB3FF #000000 0 0 0 0 1
(const_declaration (const_declaration
(const_element (const_element
(name) @constant)) (name) @constant))
;; #82AAFF #000000 0 0 0 1 ;; #82AAFF #000000 0 0 0 0 1
[ [
(primitive_type) (primitive_type)
(cast_type) (cast_type)
(bottom_type) (bottom_type)
] @type.builtin ] @type.builtin
;; #82AAFF #000000 0 0 0 1 ;; #82AAFF #000000 0 0 0 0 1
(named_type (named_type
[ [
(name) @type (name) @type
@@ -212,24 +212,24 @@
(relative_name (name) @type) (relative_name (name) @type)
]) ])
;; #82AAFF #000000 0 0 0 1 ;; #82AAFF #000000 0 0 0 0 1
(named_type (named_type
(name) @type.builtin (name) @type.builtin
(#any-of? @type.builtin "static" "self")) (#any-of? @type.builtin "static" "self"))
;; #82AAFF #000000 0 0 0 1 ;; #82AAFF #000000 0 0 0 0 1
(class_declaration (class_declaration
name: (name) @type) name: (name) @type)
;; #82AAFF #000000 0 0 0 1 ;; #82AAFF #000000 0 0 0 0 1
(enum_declaration (enum_declaration
name: (name) @type) name: (name) @type)
;; #82AAFF #000000 0 0 0 1 ;; #82AAFF #000000 0 0 0 0 1
(interface_declaration (interface_declaration
name: (name) @type) name: (name) @type)
;; #7DCFFF #000000 0 0 0 1 ;; #7DCFFF #000000 0 0 0 0 1
(namespace_use_clause (namespace_use_clause
[ [
(name) @type (name) @type
@@ -237,7 +237,7 @@
alias: (name) @type.definition alias: (name) @type.definition
]) ])
;; #7DCFFF #000000 0 0 0 1 ;; #7DCFFF #000000 0 0 0 0 1
(namespace_use_clause (namespace_use_clause
type: "function" type: "function"
[ [
@@ -246,7 +246,7 @@
alias: (name) @function alias: (name) @function
]) ])
;; #7DCFFF #000000 0 0 0 1 ;; #7DCFFF #000000 0 0 0 0 1
(namespace_use_clause (namespace_use_clause
type: "const" type: "const"
[ [
@@ -255,7 +255,7 @@
alias: (name) @constant alias: (name) @constant
]) ])
;; #7DCFFF #000000 0 0 0 1 ;; #7DCFFF #000000 0 0 0 0 1
(scoped_call_expression (scoped_call_expression
scope: [ scope: [
(name) @type (name) @type
@@ -263,7 +263,7 @@
(relative_name (name) @type) (relative_name (name) @type)
]) ])
;; #7DCFFF #000000 0 0 0 1 ;; #7DCFFF #000000 0 0 0 0 1
(class_constant_access_expression (class_constant_access_expression
. .
[ [
@@ -273,19 +273,19 @@
] ]
(name) @constant) (name) @constant)
;; #A6E3A1 #000000 0 0 0 1 ;; #A6E3A1 #000000 0 0 0 0 1
(scoped_property_access_expression (scoped_property_access_expression
name: (variable_name) @variable.member) name: (variable_name) @variable.member)
;; #A6E3A1 #000000 0 0 0 1 ;; #A6E3A1 #000000 0 0 0 0 1
(trait_declaration (trait_declaration
name: (name) @type) name: (name) @type)
;; #A6E3A1 #000000 0 0 0 1 ;; #A6E3A1 #000000 0 0 0 0 1
(use_declaration (use_declaration
(name) @type) (name) @type)
;; #FF9D5C #000000 0 0 0 1 ;; #FF9D5C #000000 0 0 0 0 1
(binary_expression (binary_expression
operator: "instanceof" operator: "instanceof"
right: [ right: [
@@ -294,24 +294,24 @@
(relative_name (name) @type) (relative_name (name) @type)
]) ])
;; #FFD580 #000000 0 0 0 1 ;; #FFD580 #000000 0 0 0 0 1
(array_creation_expression (array_creation_expression
"array" @function.builtin) "array" @function.builtin)
;; #FFD580 #000000 0 0 0 1 ;; #FFD580 #000000 0 0 0 0 1
(list_literal (list_literal
"list" @function.builtin) "list" @function.builtin)
;; #FFD580 #000000 0 0 0 1 ;; #FFD580 #000000 0 0 0 0 1
(exit_statement (exit_statement
"exit" @function.builtin "exit" @function.builtin
"(") "(")
;; #89DDFF #000000 0 0 0 1 ;; #89DDFF #000000 0 0 0 0 1
(method_declaration (method_declaration
name: (name) @function.method) name: (name) @function.method)
;; #89DDFF #000000 0 0 0 1 ;; #89DDFF #000000 0 0 0 0 1
(function_call_expression (function_call_expression
function: [ function: [
(name) @function.call (name) @function.call
@@ -319,24 +319,24 @@
(relative_name (name) @function.call) (relative_name (name) @function.call)
]) ])
;; #89DDFF #000000 0 0 0 1 ;; #89DDFF #000000 0 0 0 0 1
(scoped_call_expression (scoped_call_expression
name: (name) @function.call) name: (name) @function.call)
;; #89DDFF #000000 0 0 0 1 ;; #89DDFF #000000 0 0 0 0 1
(member_call_expression (member_call_expression
name: (name) @function.method) name: (name) @function.method)
;; #89DDFF #000000 0 0 0 1 ;; #89DDFF #000000 0 0 0 0 1
(nullsafe_member_call_expression (nullsafe_member_call_expression
name: (name) @function.method) name: (name) @function.method)
;; #FFD580 #000000 0 0 0 1 ;; #FFD580 #000000 0 0 0 0 1
(method_declaration (method_declaration
name: (name) @constructor name: (name) @constructor
(#eq? @constructor "__construct")) (#eq? @constructor "__construct"))
;; #FFD580 #000000 0 0 0 1 ;; #FFD580 #000000 0 0 0 0 1
(object_creation_expression (object_creation_expression
[ [
(name) @constructor (name) @constructor
@@ -344,55 +344,55 @@
(relative_name (name) @constructor) (relative_name (name) @constructor)
]) ])
;; #9CDCFE #000000 0 0 0 1 ;; #9CDCFE #000000 0 0 0 0 1
(variadic_parameter (variadic_parameter
"..." @operator "..." @operator
name: (variable_name) @variable.parameter) name: (variable_name) @variable.parameter)
;; #9CDCFE #000000 0 0 0 1 ;; #9CDCFE #000000 0 0 0 0 1
(simple_parameter (simple_parameter
name: (variable_name) @variable.parameter) name: (variable_name) @variable.parameter)
;; #9CDCFE #000000 0 0 0 1 ;; #9CDCFE #000000 0 0 0 0 1
(argument (argument
(name) @variable.parameter) (name) @variable.parameter)
;; #9CDCFE #000000 0 0 0 1 ;; #9CDCFE #000000 0 0 0 0 1
(property_element (property_element
(variable_name) @property) (variable_name) @property)
;; #9CDCFE #000000 0 0 0 1 ;; #9CDCFE #000000 0 0 0 0 1
(member_access_expression (member_access_expression
name: (variable_name (name)) @variable.member) name: (variable_name (name)) @variable.member)
;; #9CDCFE #000000 0 0 0 1 ;; #9CDCFE #000000 0 0 0 0 1
(relative_scope) @variable.builtin (relative_scope) @variable.builtin
;; #7AA2F7 #000000 0 0 0 1 ;; #7AA2F7 #000000 0 0 0 0 1
((variable_name) @variable.builtin ((variable_name) @variable.builtin
(#eq? @variable.builtin "$this")) (#eq? @variable.builtin "$this"))
;; #C792EA #000000 0 0 0 1 ;; #C792EA #000000 0 0 0 0 1
(namespace_definition (namespace_definition
name: (namespace_name (name) @module)) name: (namespace_name (name) @module))
;; #C792EA #000000 0 0 0 1 ;; #C792EA #000000 0 0 0 0 1
(namespace_name (namespace_name
(name) @module) (name) @module)
;; #7AA2F7 #000000 0 0 0 1 ;; #7AA2F7 #000000 0 0 0 0 1
(relative_name (relative_name
"namespace" @module.builtin) "namespace" @module.builtin)
;; #89DDFF #000000 0 0 0 1 ;; #89DDFF #000000 0 0 0 0 1
(attribute_list) @attribute (attribute_list) @attribute
;; #FF9D5C #000000 0 0 0 1 ;; #FF9D5C #000000 0 0 0 0 1
(conditional_expression (conditional_expression
"?" @keyword.conditional.ternary "?" @keyword.conditional.ternary
":" @keyword.conditional.ternary) ":" @keyword.conditional.ternary)
;; #9CDCFE #000000 0 0 0 1 ;; #9CDCFE #000000 0 0 0 0 1
(declare_directive (declare_directive
[ [
"strict_types" "strict_types"
@@ -400,7 +400,7 @@
"encoding" "encoding"
] @variable.parameter) ] @variable.parameter)
;; #A6E3A1 #000000 0 0 0 1 ;; #A6E3A1 #000000 0 0 0 0 1
[ [
(string) (string)
(encapsed_string) (encapsed_string)
@@ -409,45 +409,45 @@
(shell_command_expression) (shell_command_expression)
] @string ] @string
;; #A6E3A1 #000000 0 0 0 1 ;; #A6E3A1 #000000 0 0 0 0 1
(escape_sequence) @string.escape (escape_sequence) @string.escape
;; #A6E3A1 #000000 0 0 0 1 ;; #A6E3A1 #000000 0 0 0 0 1
[ [
(heredoc_start) (heredoc_start)
(heredoc_end) (heredoc_end)
] @label ] @label
;; #DDB6F2 #000000 0 0 0 1 ;; #DDB6F2 #000000 0 0 0 0 1
(nowdoc (nowdoc
"'" @label) "'" @label)
;; #F38BA8 #000000 0 0 0 1 ;; #F38BA8 #000000 0 0 0 0 1
(boolean) @boolean (boolean) @boolean
;; #F38BA8 #000000 0 0 0 1 ;; #F38BA8 #000000 0 0 0 0 1
(null) @constant.builtin (null) @constant.builtin
;; #F38BA8 #000000 0 0 0 1 ;; #F38BA8 #000000 0 0 0 0 1
(integer) @number (integer) @number
;; #F38BA8 #000000 0 0 0 1 ;; #F38BA8 #000000 0 0 0 0 1
(float) @number.float (float) @number.float
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment @spell (comment) @comment @spell
;; #A6E3A1 #000000 0 0 0 1 ;; #A6E3A1 #000000 0 0 0 0 1
(named_label_statement) @label (named_label_statement) @label
;; #7AA2F7 #000000 0 0 0 1 ;; #7AA2F7 #000000 0 0 0 0 1
(property_hook (property_hook
(name) @label) (name) @label)
;; #7AA2F7 #000000 0 0 0 1 ;; #7AA2F7 #000000 0 0 0 0 1
(visibility_modifier (visibility_modifier
(operation) @label) (operation) @label)
;; #89DDFF #000000 0 0 0 1 ;; #89DDFF #000000 0 0 0 0 1
;; !html ;; !html
(text) @injection.html (text) @injection.html

View File

@@ -2,33 +2,33 @@
; Identifiers ; Identifiers
; ============================================================ ; ============================================================
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(identifier) @variable (identifier) @variable
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
((identifier) @type ((identifier) @type
(#match? @type "^[A-Z].*[a-z]")) (#match? @type "^[A-Z].*[a-z]"))
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
((identifier) @constant ((identifier) @constant
(#match? @constant "^[A-Z][A-Z_0-9]*$")) (#match? @constant "^[A-Z][A-Z_0-9]*$"))
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
((identifier) @constant.builtin ((identifier) @constant.builtin
(#match? @constant.builtin "^__[a-zA-Z0-9_]*__$")) (#match? @constant.builtin "^__[a-zA-Z0-9_]*__$"))
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
((identifier) @constant.builtin ((identifier) @constant.builtin
(#match? @constant.builtin "^(NotImplemented|Ellipsis|quit|exit|copyright|credits|license)$")) (#match? @constant.builtin "^(NotImplemented|Ellipsis|quit|exit|copyright|credits|license)$"))
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
((assignment ((assignment
left: (identifier) @type.definition left: (identifier) @type.definition
(type (type
(identifier) @_annotation)) (identifier) @_annotation))
(#match? @_annotation "^TypeAlias$")) (#match? @_annotation "^TypeAlias$"))
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
((assignment ((assignment
left: (identifier) @type.definition left: (identifier) @type.definition
right: (call right: (call
@@ -39,20 +39,20 @@
; Function definitions ; Function definitions
; ============================================================ ; ============================================================
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(function_definition (function_definition
name: (identifier) @function) name: (identifier) @function)
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(type (type
(identifier) @type) (identifier) @type)
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(type (type
(subscript (subscript
(identifier) @type)) (identifier) @type))
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
((call ((call
function: (identifier) @_isinstance function: (identifier) @_isinstance
arguments: (argument_list arguments: (argument_list
@@ -64,40 +64,40 @@
; Literals ; Literals
; ============================================================ ; ============================================================
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
(none) @constant.builtin (none) @constant.builtin
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
[ [
(true) (true)
(false) (false)
] @boolean ] @boolean
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
(integer) @number (integer) @number
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
(float) @number.float (float) @number.float
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment @spell (comment) @comment @spell
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
((module ((module
. .
(comment) @keyword.directive @nospell) (comment) @keyword.directive @nospell)
(#match? @keyword.directive "^#!/")) (#match? @keyword.directive "^#!/"))
;; #AAD94C #000000 0 0 0 0 ;; #AAD94C #000000 0 0 0 0 0
(string) @string (string) @string
;; #AAD94C #000000 0 0 0 0 ;; #AAD94C #000000 0 0 0 0 0
[ [
(escape_sequence) (escape_sequence)
(escape_interpolation) (escape_interpolation)
] @string.escape ] @string.escape
;; #AAD94C #000000 0 0 0 0 ;; #AAD94C #000000 0 0 0 0 0
(expression_statement (expression_statement
(string (string
(string_content) @spell) @string.documentation) (string_content) @spell) @string.documentation)
@@ -106,37 +106,37 @@
; Operators ; Operators
; ============================================================ ; ============================================================
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ "if" "elif" "else" "for" "while" "break" "continue" ] @keyword.control_flow_loops [ "if" "elif" "else" "for" "while" "break" "continue" ] @keyword.control_flow_loops
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ "def" "return" "lambda" "yield" "async" "await" ] @keyword.functions_coroutines [ "def" "return" "lambda" "yield" "async" "await" ] @keyword.functions_coroutines
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
[ "class" ] @keyword.class [ "class" ] @keyword.class
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
[ "try" "except" "finally" "raise" ] @keyword.exceptions [ "try" "except" "finally" "raise" ] @keyword.exceptions
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
[ "with" ] @keyword.context_management [ "with" ] @keyword.context_management
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
[ "import" "from" "exec" ] @keyword.imports_execution [ "import" "from" "exec" ] @keyword.imports_execution
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
[ "match" "case" ] @keyword.pattern_matching [ "match" "case" ] @keyword.pattern_matching
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
[ "global" "nonlocal" ] @keyword.scope_bindings [ "global" "nonlocal" ] @keyword.scope_bindings
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ "del" ] @keyword.deletion [ "del" ] @keyword.deletion
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ "pass" "assert" "as" "print" ] @keyword.utility [ "pass" "assert" "as" "print" ] @keyword.utility
;; #F29668 #000000 0 1 0 1 ;; #F29668 #000000 0 1 0 0 1
[ [
"-" "-"
"-=" "-="
@@ -183,7 +183,7 @@
"not in" "not in"
] @operatoroperator ] @operatoroperator
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
[ [
"," ","
"." "."
@@ -192,7 +192,7 @@
(ellipsis) (ellipsis)
] @punctuation.delimiter ] @punctuation.delimiter
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
[ [
"(" "("
")" ")"
@@ -202,27 +202,27 @@
"}" "}"
] @punctuation.bracket ] @punctuation.bracket
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(interpolation (interpolation
"{" @punctuation.special "{" @punctuation.special
"}" @punctuation.special) "}" @punctuation.special)
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(format_expression (format_expression
"{" @punctuation.special "{" @punctuation.special
"}" @punctuation.special) "}" @punctuation.special)
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(line_continuation) @punctuation.special (line_continuation) @punctuation.special
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(type_conversion) @function.macro (type_conversion) @function.macro
; ============================================================ ; ============================================================
; Builtins / Exception types ; Builtins / Exception types
; ============================================================ ; ============================================================
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
((identifier) @type.builtin ((identifier) @type.builtin
(#match? @type.builtin (#match? @type.builtin
"^(BaseException|Exception|ArithmeticError|BufferError|LookupError|AssertionError|AttributeError|EOFError|FloatingPointError|GeneratorExit|ImportError|ModuleNotFoundError|IndexError|KeyError|KeyboardInterrupt|MemoryError|NameError|NotImplementedError|OSError|OverflowError|RecursionError|ReferenceError|RuntimeError|StopIteration|StopAsyncIteration|SyntaxError|IndentationError|TabError|SystemError|SystemExit|TypeError|UnboundLocalError|UnicodeError|UnicodeEncodeError|UnicodeDecodeError|UnicodeTranslateError|ValueError|ZeroDivisionError|EnvironmentError|IOError|WindowsError|BlockingIOError|ChildProcessError|ConnectionError|BrokenPipeError|ConnectionAbortedError|ConnectionRefusedError|ConnectionResetError|FileExistsError|FileNotFoundError|InterruptedError|IsADirectoryError|NotADirectoryError|PermissionError|ProcessLookupError|TimeoutError|Warning|UserWarning|DeprecationWarning|PendingDeprecationWarning|SyntaxWarning|RuntimeWarning|FutureWarning|ImportWarning|UnicodeWarning|BytesWarning|ResourceWarning)$")) "^(BaseException|Exception|ArithmeticError|BufferError|LookupError|AssertionError|AttributeError|EOFError|FloatingPointError|GeneratorExit|ImportError|ModuleNotFoundError|IndexError|KeyError|KeyboardInterrupt|MemoryError|NameError|NotImplementedError|OSError|OverflowError|RecursionError|ReferenceError|RuntimeError|StopIteration|StopAsyncIteration|SyntaxError|IndentationError|TabError|SystemError|SystemExit|TypeError|UnboundLocalError|UnicodeError|UnicodeEncodeError|UnicodeDecodeError|UnicodeTranslateError|ValueError|ZeroDivisionError|EnvironmentError|IOError|WindowsError|BlockingIOError|ChildProcessError|ConnectionError|BrokenPipeError|ConnectionAbortedError|ConnectionRefusedError|ConnectionResetError|FileExistsError|FileNotFoundError|InterruptedError|IsADirectoryError|NotADirectoryError|PermissionError|ProcessLookupError|TimeoutError|Warning|UserWarning|DeprecationWarning|PendingDeprecationWarning|SyntaxWarning|RuntimeWarning|FutureWarning|ImportWarning|UnicodeWarning|BytesWarning|ResourceWarning)$"))
@@ -231,56 +231,56 @@
; Function / Lambda parameters ; Function / Lambda parameters
; ============================================================ ; ============================================================
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(parameters (parameters
(identifier) @variable.parameter) (identifier) @variable.parameter)
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(lambda_parameters (lambda_parameters
(identifier) @variable.parameter) (identifier) @variable.parameter)
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(lambda_parameters (lambda_parameters
(tuple_pattern (tuple_pattern
(identifier) @variable.parameter)) (identifier) @variable.parameter))
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(keyword_argument (keyword_argument
name: (identifier) @variable.parameter) name: (identifier) @variable.parameter)
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(default_parameter (default_parameter
name: (identifier) @variable.parameter) name: (identifier) @variable.parameter)
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(typed_parameter (typed_parameter
(identifier) @variable.parameter) (identifier) @variable.parameter)
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(typed_default_parameter (typed_default_parameter
name: (identifier) @variable.parameter) name: (identifier) @variable.parameter)
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(parameters (parameters
(list_splat_pattern (list_splat_pattern
(identifier) @variable.parameter)) (identifier) @variable.parameter))
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(parameters (parameters
(dictionary_splat_pattern (dictionary_splat_pattern
(identifier) @variable.parameter)) (identifier) @variable.parameter))
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(lambda_parameters (lambda_parameters
(list_splat_pattern (list_splat_pattern
(identifier) @variable.parameter)) (identifier) @variable.parameter))
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(lambda_parameters (lambda_parameters
(dictionary_splat_pattern (dictionary_splat_pattern
(identifier) @variable.parameter)) (identifier) @variable.parameter))
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
((identifier) @variable.builtin ((identifier) @variable.builtin
(#match? @variable.builtin "^(self|cls)$")) (#match? @variable.builtin "^(self|cls)$"))
@@ -288,7 +288,7 @@
; Attributes / Class members ; Attributes / Class members
; ============================================================ ; ============================================================
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
((attribute ((attribute
attribute: (identifier) @variable.member) attribute: (identifier) @variable.member)
(#match? @variable.member "^[%l_].*$")) (#match? @variable.member "^[%l_].*$"))
@@ -297,22 +297,22 @@
; Class definitions ; Class definitions
; ============================================================ ; ============================================================
;; #59C2FF #000000 0 0 0 2 ;; #59C2FF #000000 0 0 0 0 2
(class_definition (class_definition
name: (identifier) @type) name: (identifier) @type)
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(class_definition (class_definition
body: (block body: (block
(function_definition (function_definition
name: (identifier) @function.method))) name: (identifier) @function.method)))
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
(class_definition (class_definition
superclasses: (argument_list superclasses: (argument_list
(identifier) @type)) (identifier) @type))
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
((class_definition ((class_definition
body: (block body: (block
(expression_statement (expression_statement
@@ -320,7 +320,7 @@
left: (identifier) @variable.member)))) left: (identifier) @variable.member))))
(#match? @variable.member "^[%l_].*$")) (#match? @variable.member "^[%l_].*$"))
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
((class_definition ((class_definition
body: (block body: (block
(expression_statement (expression_statement
@@ -329,7 +329,7 @@
(identifier) @variable.member))))) (identifier) @variable.member)))))
(#match? @variable.member "^[%l_].*$")) (#match? @variable.member "^[%l_].*$"))
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
((class_definition ((class_definition
(block (block
(function_definition (function_definition
@@ -340,27 +340,27 @@
; Function calls ; Function calls
; ============================================================ ; ============================================================
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(call (call
function: (identifier) @function.call) function: (identifier) @function.call)
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(call (call
function: (attribute function: (attribute
attribute: (identifier) @function.method.call)) attribute: (identifier) @function.method.call))
;; #59C2FF #000000 0 0 0 3 ;; #59C2FF #000000 0 0 0 0 3
((call ((call
function: (identifier) @constructor) function: (identifier) @constructor)
(#match? @constructor "^[A-Z]")) (#match? @constructor "^[A-Z]"))
;; #59C2FF #000000 0 0 0 3 ;; #59C2FF #000000 0 0 0 0 3
((call ((call
function: (attribute function: (attribute
attribute: (identifier) @constructor)) attribute: (identifier) @constructor))
(#match? @constructor "^[A-Z]")) (#match? @constructor "^[A-Z]"))
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
((call ((call
function: (identifier) @function.builtin) function: (identifier) @function.builtin)
(#match? @function.builtin (#match? @function.builtin
@@ -382,31 +382,31 @@
; Decorators ; Decorators
; ============================================================ ; ============================================================
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(decorator (decorator
"@" @attribute) "@" @attribute)
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(decorator (decorator
(identifier) @attribute) (identifier) @attribute)
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(decorator (decorator
(attribute (attribute
attribute: (identifier) @attribute)) attribute: (identifier) @attribute))
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(decorator (decorator
(call (call
(identifier) @attribute)) (identifier) @attribute))
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(decorator (decorator
(call (call
(attribute (attribute
attribute: (identifier) @attribute))) attribute: (identifier) @attribute)))
;; #59C2FF #000000 0 0 0 3 ;; #59C2FF #000000 0 0 0 0 3
((decorator ((decorator
(identifier) @attribute.builtin) (identifier) @attribute.builtin)
(#match? @attribute.builtin "^(classmethod|property|staticmethod)$")) (#match? @attribute.builtin "^(classmethod|property|staticmethod)$"))

View File

@@ -2,37 +2,37 @@
;; Strings & escapes ;; Strings & escapes
;; ============================================================ ;; ============================================================
;; #AAD94C #000000 0 0 0 2 ;; #AAD94C #000000 0 0 0 0 2
(string) @string (string) @string
;; #95E6CB #000000 0 0 0 2 ;; #95E6CB #000000 0 0 0 0 2
(escape_sequence) @string.escape (escape_sequence) @string.escape
;; ============================================================ ;; ============================================================
;; Identifiers ;; Identifiers
;; ============================================================ ;; ============================================================
;; #C4B5FF #000000 0 0 0 2 ;; #C4B5FF #000000 0 0 0 0 2
(capture (capture
(identifier) @type) (identifier) @type)
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(predicate (predicate
name: (identifier) @function.call) name: (identifier) @function.call)
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(named_node (named_node
name: (identifier) @variable) name: (identifier) @variable)
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(missing_node (missing_node
name: (identifier) @variable) name: (identifier) @variable)
;; #F07178 #000000 0 0 0 2 ;; #F07178 #000000 0 0 0 0 2
(field_definition (field_definition
name: (identifier) @variable.member) name: (identifier) @variable.member)
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(negated_field (negated_field
"!" @operator "!" @operator
(identifier) @property) (identifier) @property)
@@ -41,23 +41,23 @@
;; Comments ;; Comments
;; ============================================================ ;; ============================================================
;; #99ADBF #000000 0 1 0 2 ;; #99ADBF #000000 0 1 0 0 2
(comment) @comment @spell (comment) @comment @spell
;; ============================================================ ;; ============================================================
;; Operators & punctuation ;; Operators & punctuation
;; ============================================================ ;; ============================================================
;; #F29668 #000000 0 0 0 2 ;; #F29668 #000000 0 0 0 0 2
(quantifier) @operator (quantifier) @operator
;; #BFBDB6 #000000 0 0 0 2 ;; #BFBDB6 #000000 0 0 0 0 2
(predicate_type) @punctuation.special (predicate_type) @punctuation.special
;; #F29668 #000000 0 0 0 2 ;; #F29668 #000000 0 0 0 0 2
"." @operator "." @operator
;; #BFBDB6 #000000 0 0 0 2 ;; #BFBDB6 #000000 0 0 0 0 2
[ [
"[" "["
"]" "]"
@@ -65,33 +65,33 @@
")" ")"
] @punctuation.bracket ] @punctuation.bracket
;; #BFBDB6 #000000 0 0 0 2 ;; #BFBDB6 #000000 0 0 0 0 2
[ [
":" ":"
"/" "/"
] @punctuation.delimiter ] @punctuation.delimiter
;; #BFBDB6 #000000 0 0 0 2 ;; #BFBDB6 #000000 0 0 0 0 2
[ [
"@" "@"
"#" "#"
] @punctuation.special ] @punctuation.special
;; #BFBDB6 #000000 0 0 0 2 ;; #BFBDB6 #000000 0 0 0 0 2
(predicate (predicate
"." @punctuation.special) "." @punctuation.special)
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
"_" @character.special "_" @character.special
;; #FF8F40 #000000 0 0 0 2 ;; #FF8F40 #000000 0 0 0 0 2
"MISSING" @keyword "MISSING" @keyword
;; ============================================================ ;; ============================================================
;; Numbers ;; Numbers
;; ============================================================ ;; ============================================================
;; #B8E986 #000000 0 0 0 2 ;; #B8E986 #000000 0 0 0 0 2
((parameters ((parameters
(identifier) @number) (identifier) @number)
(#match? @number "^[-+]?[0-9]+(.[0-9]+)?$")) (#match? @number "^[-+]?[0-9]+(.[0-9]+)?$"))
@@ -100,7 +100,7 @@
;; Predicate parameters ;; Predicate parameters
;; ============================================================ ;; ============================================================
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
((predicate ((predicate
name: (identifier) @_name name: (identifier) @_name
parameters: (parameters parameters: (parameters
@@ -110,7 +110,7 @@
(identifier) @property)) (identifier) @property))
(#match? @_name "^set$")) (#match? @_name "^set$"))
;; #AAD94C #000000 0 0 0 2 ;; #AAD94C #000000 0 0 0 0 2
((predicate ((predicate
name: (identifier) @_name name: (identifier) @_name
parameters: (parameters parameters: (parameters

View File

@@ -2,7 +2,7 @@
;; Punctuation / brackets ;; Punctuation / brackets
;; ============================================================ ;; ============================================================
;; #B6BEC8 #000000 0 0 0 1 ;; #B6BEC8 #000000 0 0 0 0 1
[ [
"(" "("
")" ")"
@@ -20,10 +20,10 @@
":]" ":]"
] @punctuation.bracket ] @punctuation.bracket
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(group_name) @property (group_name) @property
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
[ [
"*" "*"
"+" "+"
@@ -33,38 +33,38 @@
"!" "!"
] @operator ] @operator
;; #B8E986 #000000 0 0 0 2 ;; #B8E986 #000000 0 0 0 0 2
(count_quantifier (count_quantifier
[ [
(decimal_digits) @number (decimal_digits) @number
"," @punctuation.delimiter "," @punctuation.delimiter
]) ])
;; #F29668 #000000 0 0 0 2 ;; #F29668 #000000 0 0 0 0 2
(inline_flags_group (inline_flags_group
"-"? @operator "-"? @operator
":"? @punctuation.delimiter) ":"? @punctuation.delimiter)
;; #F29CC3 #000000 0 0 0 2 ;; #F29CC3 #000000 0 0 0 0 2
(flags) @character.special (flags) @character.special
;; #C2E8FF #000000 0 0 0 2 ;; #C2E8FF #000000 0 0 0 0 2
(character_class (character_class
[ [
"^" @operator "^" @operator
(class_range "-" @operator) (class_range "-" @operator)
]) ])
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
[ [
(class_character) (class_character)
(posix_class_name) (posix_class_name)
] @constant.character ] @constant.character
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
(pattern_character) @string (pattern_character) @string
;; #95E6CB #000000 0 0 0 2 ;; #95E6CB #000000 0 0 0 0 2
[ [
(identity_escape) (identity_escape)
(control_letter_escape) (control_letter_escape)

View File

@@ -1,10 +1,10 @@
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
[ [
(identifier) (identifier)
(global_variable) (global_variable)
] @variable ] @variable
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"alias" "alias"
"begin" "begin"
@@ -16,17 +16,17 @@
"then" "then"
] @keyword ] @keyword
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
"class" @keyword.type "class" @keyword.type
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"return" "return"
"yield" "yield"
] @keyword.return ] @keyword.return
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
[ [
"and" "and"
"or" "or"
@@ -34,7 +34,7 @@
"not" "not"
] @keyword.operator ] @keyword.operator
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"def" "def"
"undef" "undef"
@@ -44,7 +44,7 @@
"end" @keyword.function) "end" @keyword.function)
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"case" "case"
"else" "else"
@@ -58,7 +58,7 @@
(if (if
"end" @keyword.conditional) "end" @keyword.conditional)
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"for" "for"
"until" "until"
@@ -69,28 +69,28 @@
"next" "next"
] @keyword.repeat ] @keyword.repeat
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(constant) @constant (constant) @constant
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"rescue" "rescue"
"ensure" "ensure"
] @keyword.exception ] @keyword.exception
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
"defined?" @function "defined?" @function
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(call (call
receiver: (constant)? @type receiver: (constant)? @type
method: [ method: [
(identifier) (identifier)
(constant) (constant)
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
] @function.call) ] @function.call)
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(alias (alias
(identifier) @function) (identifier) @function)
@@ -109,7 +109,7 @@
(constant) @type (constant) @type
]) ])
;; #59C2FF #000000 0 0 0 2 ;; #59C2FF #000000 0 0 0 0 2
(class (class
name: (constant) @type) name: (constant) @type)
@@ -119,27 +119,27 @@
(superclass (superclass
(constant) @type) (constant) @type)
;; #F07178 #000000 0 0 0 2 ;; #F07178 #000000 0 0 0 0 2
[ [
(class_variable) (class_variable)
(instance_variable) (instance_variable)
] @variable.member ] @variable.member
;; #FF8F40 #000000 0 0 0 2 ;; #FF8F40 #000000 0 0 0 0 2
((identifier) @keyword.modifier ((identifier) @keyword.modifier
(#match? @keyword.modifier "^(private|protected|public)$" )) (#match? @keyword.modifier "^(private|protected|public)$" ))
;; #FF8F40 #000000 0 0 0 3 ;; #FF8F40 #000000 0 0 0 0 3
(program (program
(call (call
(identifier) @keyword.import) (identifier) @keyword.import)
(#match? @keyword.import "^(require|require_relative|load)$")) (#match? @keyword.import "^(require|require_relative|load)$"))
;; #D2A6FF #000000 0 0 0 4 ;; #D2A6FF #000000 0 0 0 0 4
((identifier) @constant.builtin ((identifier) @constant.builtin
(#match? @constant.builtin "^(__callee__|__dir__|__id__|__method__|__send__|__ENCODING__|__FILE__|__LINE__)$" )) (#match? @constant.builtin "^(__callee__|__dir__|__id__|__method__|__send__|__ENCODING__|__FILE__|__LINE__)$" ))
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
((identifier) @function.builtin ((identifier) @function.builtin
(#match? @function.builtin "^(attr_reader|attr_writer|attr_accessor|module_function)$" )) (#match? @function.builtin "^(attr_reader|attr_writer|attr_accessor|module_function)$" ))
@@ -148,17 +148,17 @@
method: (identifier) @function.builtin) method: (identifier) @function.builtin)
(#match? @function.builtin "^(include|extend|prepend|refine|using)$")) (#match? @function.builtin "^(include|extend|prepend|refine|using)$"))
;; #FF8F40 #000000 0 0 0 3 ;; #FF8F40 #000000 0 0 0 0 3
((identifier) @keyword.exception ((identifier) @keyword.exception
(#match? @keyword.exception "^(raise|fail|catch|throw)$" )) (#match? @keyword.exception "^(raise|fail|catch|throw)$" ))
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
[ [
(self) (self)
(super) (super)
] @variable.builtin ] @variable.builtin
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(method_parameters (method_parameters
(identifier) @variable.parameter) (identifier) @variable.parameter)
@@ -186,7 +186,7 @@
(keyword_parameter (keyword_parameter
(identifier) @variable.parameter) (identifier) @variable.parameter)
;; #AAD94C #000000 0 0 0 1 ;; #AAD94C #000000 0 0 0 0 1
[ [
(string_content) (string_content)
(heredoc_content) (heredoc_content)
@@ -194,13 +194,13 @@
"`" "`"
] @string ] @string
;; #E6C08A #000000 0 0 0 1 ;; #E6C08A #000000 0 0 0 0 1
[ [
(heredoc_beginning) (heredoc_beginning)
(heredoc_end) (heredoc_end)
] @label ] @label
;; #39BAE6 #000000 0 0 0 2 ;; #39BAE6 #000000 0 0 0 0 2
[ [
(bare_symbol) (bare_symbol)
(simple_symbol) (simple_symbol)
@@ -208,34 +208,34 @@
(hash_key_symbol) (hash_key_symbol)
] @string.special.symbol ] @string.special.symbol
;; #95E6CB #000000 0 0 0 2 ;; #95E6CB #000000 0 0 0 0 2
(escape_sequence) @string.escape (escape_sequence) @string.escape
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
(integer) @number (integer) @number
;; #D2A6FF #000000 0 0 0 2 ;; #D2A6FF #000000 0 0 0 0 2
(float) @number.float (float) @number.float
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(true) @boolean.true (true) @boolean.true
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(false) @boolean.false (false) @boolean.false
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(nil) @constant.nil (nil) @constant.nil
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment (comment) @comment
;; #AAD94C #000000 0 0 0 3 ;; #AAD94C #000000 0 0 0 0 3
((program ((program
. .
(comment) @shebang @nospell) (comment) @shebang @nospell)
(#match? @shebang "^#!/")) (#match? @shebang "^#!/"))
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
[ [
"!" "!"
"=" "="
@@ -263,7 +263,7 @@
":" ":"
] @operator ] @operator
;; #F29668 #000000 0 1 0 1 ;; #F29668 #000000 0 1 0 0 1
[ [
"==" "=="
"===" "==="
@@ -281,7 +281,7 @@
"..." "..."
] @operator.ligature ] @operator.ligature
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
[ [
"," ","
";" ";"
@@ -293,7 +293,7 @@
(pair (pair
":" @punctuation.delimiter) ":" @punctuation.delimiter)
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 3
[ [
"(" "("
")" ")"
@@ -311,7 +311,7 @@
(block_parameters (block_parameters
"|" @punctuation.bracket) "|" @punctuation.bracket)
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(interpolation (interpolation
"#{" @punctuation.special "#{" @punctuation.special
"}" @punctuation.special) "}" @punctuation.special)
@@ -507,3 +507,9 @@
(heredoc_content) @cabal_injection (heredoc_content) @cabal_injection
((heredoc_end) @lang ((heredoc_end) @lang
(#match? @lang "CABAL"))) (#match? @lang "CABAL")))
(heredoc_body
;; !man
(heredoc_content) @man_injection
((heredoc_end) @lang
(#match? @lang "MAN")))

View File

@@ -2,51 +2,51 @@
; Identifiers & Modules ; Identifiers & Modules
; ============================================================ ; ============================================================
;; #82AAFF #000000 0 0 0 1 ;; #82AAFF #000000 0 0 0 0 1
(shebang) @keyword.directive1 (shebang) @keyword.directive1
;; #E5C07B #000000 0 0 0 1 ;; #E5C07B #000000 0 0 0 0 1
(identifier) @variable1 (identifier) @variable1
;; #A6E22E #000000 0 0 0 2 ;; #A6E22E #000000 0 0 0 0 2
((identifier) @type1 ((identifier) @type1
(#match? @type1 "^[A-Z]")) (#match? @type1 "^[A-Z]"))
;; #FFD700 #000000 0 0 0 2 ;; #FFD700 #000000 0 0 0 0 2
(const_item (const_item
name: (identifier) @constant1) name: (identifier) @constant1)
;; #FF9E64 #000000 0 0 0 3 ;; #FF9E64 #000000 0 0 0 0 3
((identifier) @constant2 ((identifier) @constant2
(#match? @constant2 "^[A-Z][A-Z%d_]*$")) (#match? @constant2 "^[A-Z][A-Z%d_]*$"))
;; #7DCFFF #000000 0 0 0 4 ;; #7DCFFF #000000 0 0 0 0 4
(type_identifier) @type2 (type_identifier) @type2
;; #7DCFFF #000000 0 0 0 2 ;; #7DCFFF #000000 0 0 0 0 2
(primitive_type) @type.builtin1 (primitive_type) @type.builtin1
;; #C678DD #000000 0 0 0 2 ;; #C678DD #000000 0 0 0 0 2
(field_identifier) @variable.member1 (field_identifier) @variable.member1
;; #C678DD #000000 0 0 0 2 ;; #C678DD #000000 0 0 0 0 2
(shorthand_field_identifier) @variable.member2 (shorthand_field_identifier) @variable.member2
;; #C678DD #000000 0 0 0 2 ;; #C678DD #000000 0 0 0 0 2
(shorthand_field_initializer (shorthand_field_initializer
(identifier) @variable.member3) (identifier) @variable.member3)
;; #61AFEF #000000 0 0 0 2 ;; #61AFEF #000000 0 0 0 0 2
(mod_item (mod_item
name: (identifier) @module1) name: (identifier) @module1)
;; #D19A66 #000000 0 0 0 2 ;; #D19A66 #000000 0 0 0 0 2
(self) @variable.builtin1 (self) @variable.builtin1
;; #5C6370 #000000 0 0 0 1 ;; #5C6370 #000000 0 0 0 0 1
"_" @character.special1 "_" @character.special1
;; #61AFEF #000000 0 0 1 2 ;; #61AFEF #000000 0 0 1 0 2
(label (label
[ [
"'" "'"
@@ -57,22 +57,22 @@
; Functions & Parameters ; Functions & Parameters
; ============================================================ ; ============================================================
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(function_item (function_item
(identifier) @function1) (identifier) @function1)
;; #FFB454 #000000 0 0 0 3 ;; #FFB454 #000000 0 0 0 0 3
(function_signature_item (function_signature_item
(identifier) @function2) (identifier) @function2)
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(parameter (parameter
[ [
(identifier) (identifier)
"_" "_"
] @variable.parameter1) ] @variable.parameter1)
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(parameter (parameter
(ref_pattern (ref_pattern
[ [
@@ -81,7 +81,7 @@
(identifier) @variable.parameter3 (identifier) @variable.parameter3
])) ]))
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(closure_parameters (closure_parameters
(_) @variable.parameter4) (_) @variable.parameter4)
@@ -89,39 +89,39 @@
; Function Calls & Constructors ; Function Calls & Constructors
; ============================================================ ; ============================================================
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(call_expression (call_expression
function: (identifier) @function.call1) function: (identifier) @function.call1)
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(call_expression (call_expression
function: (scoped_identifier function: (scoped_identifier
(identifier) @function.call2 .)) (identifier) @function.call2 .))
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(call_expression (call_expression
function: (field_expression function: (field_expression
field: (field_identifier) @function.call3)) field: (field_identifier) @function.call3))
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(generic_function (generic_function
function: (identifier) @function.call4) function: (identifier) @function.call4)
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(generic_function (generic_function
function: (scoped_identifier function: (scoped_identifier
name: (identifier) @function.call5)) name: (identifier) @function.call5))
;; #FFB454 #000000 0 0 0 2 ;; #FFB454 #000000 0 0 0 0 2
(generic_function (generic_function
function: (field_expression function: (field_expression
field: (field_identifier) @function.call6)) field: (field_identifier) @function.call6))
;; #9ADE7A #000000 0 0 0 32 ;; #9ADE7A #000000 0 0 0 0 32
((field_identifier) @constant3 ((field_identifier) @constant3
(#match? @constant3 "^[A-Z]")) (#match? @constant3 "^[A-Z]"))
;; #9ADE7A #000000 0 0 0 32 ;; #9ADE7A #000000 0 0 0 0 32
(enum_variant (enum_variant
name: (identifier) @constant4) name: (identifier) @constant4)
@@ -129,86 +129,86 @@
; Scoped Identifiers & Paths ; Scoped Identifiers & Paths
; ============================================================ ; ============================================================
;; #82AAFF #000000 0 0 0 9 ;; #82AAFF #000000 0 0 0 0 9
(scoped_identifier (scoped_identifier
path: (identifier) @module2) path: (identifier) @module2)
;; #82AAFF #000000 0 0 0 9 ;; #82AAFF #000000 0 0 0 0 9
(scoped_identifier (scoped_identifier
(scoped_identifier (scoped_identifier
name: (identifier) @module3)) name: (identifier) @module3))
;; #7DCFFF #000000 0 0 0 9 ;; #7DCFFF #000000 0 0 0 0 9
(scoped_type_identifier (scoped_type_identifier
path: (identifier) @module4) path: (identifier) @module4)
;; #7DCFFF #000000 0 0 0 9 ;; #7DCFFF #000000 0 0 0 0 9
(scoped_type_identifier (scoped_type_identifier
path: (identifier) @type3 path: (identifier) @type3
(#match? @type3 "^[A-Z]")) (#match? @type3 "^[A-Z]"))
;; #7DCFFF #000000 0 0 0 9 ;; #7DCFFF #000000 0 0 0 0 9
(scoped_type_identifier (scoped_type_identifier
(scoped_identifier (scoped_identifier
name: (identifier) @module5)) name: (identifier) @module5))
;; #7DCFFF #000000 0 0 0 9 ;; #7DCFFF #000000 0 0 0 0 9
((scoped_identifier ((scoped_identifier
path: (identifier) @type4) path: (identifier) @type4)
(#match? @type4 "^[A-Z]")) (#match? @type4 "^[A-Z]"))
;; #7DCFFF #000000 0 0 0 9 ;; #7DCFFF #000000 0 0 0 0 9
((scoped_identifier ((scoped_identifier
name: (identifier) @type5) name: (identifier) @type5)
(#match? @type5 "^[A-Z]")) (#match? @type5 "^[A-Z]"))
;; #FFD700 #000000 0 0 0 7 ;; #FFD700 #000000 0 0 0 0 7
((scoped_identifier ((scoped_identifier
name: (identifier) @constant5) name: (identifier) @constant5)
(#match? @constant5 "^[A-Z][A-Z%d_]*$")) (#match? @constant5 "^[A-Z][A-Z%d_]*$"))
;; #FFD700 #000000 0 0 0 7 ;; #FFD700 #000000 0 0 0 0 7
((scoped_identifier ((scoped_identifier
path: (identifier) @type6 path: (identifier) @type6
name: (identifier) @constant6) name: (identifier) @constant6)
(#match? @type6 "^[A-Z]") (#match? @type6 "^[A-Z]")
(#match? @constant6 "^[A-Z]")) (#match? @constant6 "^[A-Z]"))
;; #FFD700 #000000 0 0 0 7 ;; #FFD700 #000000 0 0 0 0 7
((scoped_type_identifier ((scoped_type_identifier
path: (identifier) @type7 path: (identifier) @type7
name: (type_identifier) @constant7) name: (type_identifier) @constant7)
(#match? @type7 "^[A-Z]") (#match? @type7 "^[A-Z]")
(#match? @constant7 "^[A-Z]")) (#match? @constant7 "^[A-Z]"))
;; #61AFEF #000000 0 0 0 0 ;; #61AFEF #000000 0 0 0 0 0
[ [
(crate) (crate)
(super) (super)
] @module6 ] @module6
;; #61AFEF #000000 0 0 0 0 ;; #61AFEF #000000 0 0 0 0 0
(scoped_use_list (scoped_use_list
path: (identifier) @module7) path: (identifier) @module7)
;; #61AFEF #000000 0 0 0 0 ;; #61AFEF #000000 0 0 0 0 0
(scoped_use_list (scoped_use_list
path: (scoped_identifier path: (scoped_identifier
(identifier) @module8)) (identifier) @module8))
;; #7DCFFF #000000 0 0 0 0 ;; #7DCFFF #000000 0 0 0 0 0
(use_list (use_list
(scoped_identifier (scoped_identifier
(identifier) @module9 (identifier) @module9
. .
(_))) (_)))
;; #7DCFFF #000000 0 0 0 0 ;; #7DCFFF #000000 0 0 0 0 0
(use_list (use_list
(identifier) @type8 (identifier) @type8
(#match? @type8 "^[A-Z]")) (#match? @type8 "^[A-Z]"))
;; #7DCFFF #000000 0 0 0 0 ;; #7DCFFF #000000 0 0 0 0 0
(use_as_clause (use_as_clause
alias: (identifier) @type9 alias: (identifier) @type9
(#match? @type9 "^[A-Z]")) (#match? @type9 "^[A-Z]"))
@@ -217,7 +217,7 @@
; Enum Constructors & Match Arms ; Enum Constructors & Match Arms
; ============================================================ ; ============================================================
;; #9ADE7A #000000 0 0 0 9 ;; #9ADE7A #000000 0 0 0 0 9
; Correct enum constructors ; Correct enum constructors
(call_expression (call_expression
function: (scoped_identifier function: (scoped_identifier
@@ -225,21 +225,21 @@
name: (identifier) @constant8) name: (identifier) @constant8)
(#match? @constant8 "^[A-Z]")) (#match? @constant8 "^[A-Z]"))
;; #FFD700 #000000 0 0 0 2 ;; #FFD700 #000000 0 0 0 0 2
; Assume uppercase names in a match arm are constants. ; Assume uppercase names in a match arm are constants.
((match_arm ((match_arm
pattern: (match_pattern pattern: (match_pattern
(identifier) @constant9)) (identifier) @constant9))
(#match? @constant9 "^[A-Z]")) (#match? @constant9 "^[A-Z]"))
;; #FFD700 #000000 0 0 0 2 ;; #FFD700 #000000 0 0 0 0 2
((match_arm ((match_arm
pattern: (match_pattern pattern: (match_pattern
(scoped_identifier (scoped_identifier
name: (identifier) @constant10))) name: (identifier) @constant10)))
(#match? @constant10 "^[A-Z]")) (#match? @constant10 "^[A-Z]"))
;; #D2A6FF #000000 0 0 0 3 ;; #D2A6FF #000000 0 0 0 0 3
((identifier) @constant.builtin1 ((identifier) @constant.builtin1
(#match? @constant.builtin1 "^(Some|None|Ok|Err)$")) (#match? @constant.builtin1 "^(Some|None|Ok|Err)$"))
@@ -247,36 +247,36 @@
; Macros ; Macros
; ============================================================ ; ============================================================
;; #FF8F40 #000000 0 0 0 2 ;; #FF8F40 #000000 0 0 0 0 2
"$" @function.macro1 "$" @function.macro1
;; #FF8F40 #000000 0 0 0 2 ;; #FF8F40 #000000 0 0 0 0 2
(metavariable) @function.macro2 (metavariable) @function.macro2
;; #FF8F40 #000000 0 0 0 2 ;; #FF8F40 #000000 0 0 0 0 2
(macro_definition (macro_definition
"macro_rules!" @function.macro3) "macro_rules!" @function.macro3)
;; #FF8F40 #000000 0 0 0 2 ;; #FF8F40 #000000 0 0 0 0 2
(attribute_item (attribute_item
(attribute (attribute
(identifier) @function.macro4)) (identifier) @function.macro4))
;; #FF8F40 #000000 0 0 0 2 ;; #FF8F40 #000000 0 0 0 0 2
(inner_attribute_item (inner_attribute_item
(attribute (attribute
(identifier) @function.macro5)) (identifier) @function.macro5))
;; #FF8F40 #000000 0 0 0 2 ;; #FF8F40 #000000 0 0 0 0 2
(attribute (attribute
(scoped_identifier (scoped_identifier
(identifier) @function.macro6 .)) (identifier) @function.macro6 .))
;; #FF8F40 #000000 0 0 0 2 ;; #FF8F40 #000000 0 0 0 0 2
(macro_invocation (macro_invocation
macro: (identifier) @function.macro7) macro: (identifier) @function.macro7)
;; #FF8F40 #000000 0 0 0 2 ;; #FF8F40 #000000 0 0 0 0 2
(macro_invocation (macro_invocation
macro: (scoped_identifier macro: (scoped_identifier
(identifier) @function.macro8 .)) (identifier) @function.macro8 .))
@@ -285,42 +285,42 @@
; Literals ; Literals
; ============================================================ ; ============================================================
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(boolean_literal) @boolean1 (boolean_literal) @boolean1
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(integer_literal) @number1 (integer_literal) @number1
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(float_literal) @number.float1 (float_literal) @number.float1
;; #AAD94C #000000 0 0 0 0 ;; #AAD94C #000000 0 0 0 0 0
[ [
(raw_string_literal) (raw_string_literal)
(string_literal) (string_literal)
] @string1 ] @string1
;; #AAD94C #000000 0 0 0 0 ;; #AAD94C #000000 0 0 0 0 0
(escape_sequence) @string.escape1 (escape_sequence) @string.escape1
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
(char_literal) @character1 (char_literal) @character1
; ============================================================ ; ============================================================
; Keywords ; Keywords
; ============================================================ ; ============================================================
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"use" "use"
"mod" "mod"
] @keyword.import1 ] @keyword.import1
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
(use_as_clause (use_as_clause
"as" @keyword.import2) "as" @keyword.import2)
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"default" "default"
"impl" "impl"
@@ -330,7 +330,7 @@
"where" "where"
] @keyword1 ] @keyword1
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"enum" "enum"
"struct" "struct"
@@ -339,17 +339,17 @@
"type" "type"
] @keyword.type1 ] @keyword.type1
;; #82AAFF #000000 0 0 0 1 ;; #82AAFF #000000 0 0 0 0 1
[ [
"async" "async"
"await" "await"
"gen" "gen"
] @keyword.coroutine1 ] @keyword.coroutine1
;; #FF6347 #000000 0 0 0 1 ;; #FF6347 #000000 0 0 0 0 1
"try" @keyword.exception1 "try" @keyword.exception1
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"ref" "ref"
"pub" "pub"
@@ -361,45 +361,45 @@
"extern" "extern"
] @keyword.modifier1 ] @keyword.modifier1
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
(lifetime (lifetime
"'" @keyword.modifier2) "'" @keyword.modifier2)
;; #9ADE7A #000000 0 0 0 5 ;; #9ADE7A #000000 0 0 0 0 5
(lifetime (lifetime
(identifier) @attribute1) (identifier) @attribute1)
;; #9ADE7A #000000 0 0 0 5 ;; #9ADE7A #000000 0 0 0 0 5
(lifetime (lifetime
(identifier) @attribute.builtin1 (identifier) @attribute.builtin1
(#match? @attribute.builtin1 "^(static|_)$")) (#match? @attribute.builtin1 "^(static|_)$"))
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
"fn" @keyword.function1 "fn" @keyword.function1
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"return" "return"
"yield" "yield"
] @keyword.return1 ] @keyword.return1
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
(type_cast_expression (type_cast_expression
"as" @keyword.operator1) "as" @keyword.operator1)
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
(qualified_type (qualified_type
"as" @keyword.operator2) "as" @keyword.operator2)
;; #61AFEF #000000 0 0 0 9 ;; #61AFEF #000000 0 0 0 0 9
(use_list (use_list
(self) @module10) (self) @module10)
;; #61AFEF #000000 0 0 0 9 ;; #61AFEF #000000 0 0 0 0 9
(scoped_use_list (scoped_use_list
(self) @module11) (self) @module11)
;; #61AFEF #000000 0 0 0 9 ;; #61AFEF #000000 0 0 0 0 9
(scoped_identifier (scoped_identifier
[ [
(crate) (crate)
@@ -407,7 +407,7 @@
(self) (self)
] @module12) ] @module12)
;; #61AFEF #000000 0 0 0 9 ;; #61AFEF #000000 0 0 0 0 9
(visibility_modifier (visibility_modifier
[ [
(crate) (crate)
@@ -415,14 +415,14 @@
(self) (self)
] @module13) ] @module13)
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"if" "if"
"else" "else"
"match" "match"
] @keyword.conditional1 ] @keyword.conditional1
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
[ [
"break" "break"
"continue" "continue"
@@ -431,10 +431,10 @@
"while" "while"
] @keyword.repeat1 ] @keyword.repeat1
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
"for" @keyword2 "for" @keyword2
;; #FF8F40 #000000 0 0 0 1 ;; #FF8F40 #000000 0 0 0 0 1
(for_expression (for_expression
"for" @keyword.repeat2) "for" @keyword.repeat2)
@@ -442,7 +442,7 @@
; Operators ; Operators
; ============================================================ ; ============================================================
;; #F29668 #000000 0 1 0 1 ;; #F29668 #000000 0 1 0 0 1
[ [
"!" "!"
"!=" "!="
@@ -481,15 +481,15 @@
"||" "||"
] @operator1 ] @operator1
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
(use_wildcard (use_wildcard
"*" @character.special2) "*" @character.special2)
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
(remaining_field_pattern (remaining_field_pattern
".." @character.special3) ".." @character.special3)
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
(range_pattern (range_pattern
[ [
".." ".."
@@ -501,7 +501,7 @@
; Punctuation ; Punctuation
; ============================================================ ; ============================================================
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
[ [
"(" "("
")" ")"
@@ -511,39 +511,39 @@
"}" "}"
] @punctuation.bracket1 ] @punctuation.bracket1
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
(closure_parameters (closure_parameters
"|" @punctuation.bracket2) "|" @punctuation.bracket2)
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
(type_arguments (type_arguments
[ [
"<" "<"
">" ">"
] @punctuation.bracket3) ] @punctuation.bracket3)
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
(type_parameters (type_parameters
[ [
"<" "<"
">" ">"
] @punctuation.bracket4) ] @punctuation.bracket4)
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
(bracketed_type (bracketed_type
[ [
"<" "<"
">" ">"
] @punctuation.bracket5) ] @punctuation.bracket5)
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
(for_lifetimes (for_lifetimes
[ [
"<" "<"
">" ">"
] @punctuation.bracket6) ] @punctuation.bracket6)
;; #BFBDB6 #000000 0 1 0 1 ;; #BFBDB6 #000000 0 1 0 0 1
[ [
"," ","
"." "."
@@ -554,22 +554,22 @@
"=>" "=>"
] @punctuation.delimiter1 ] @punctuation.delimiter1
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
(attribute_item (attribute_item
"#" @punctuation.special1) "#" @punctuation.special1)
;; #BFBDB6 #000000 0 0 0 1 ;; #BFBDB6 #000000 0 0 0 0 1
(inner_attribute_item (inner_attribute_item
[ [
"!" "!"
"#" "#"
] @punctuation.special2) ] @punctuation.special2)
;; #FF8F40 #000000 0 0 0 2 ;; #FF8F40 #000000 0 0 0 0 2
(macro_invocation (macro_invocation
"!" @function.macro9) "!" @function.macro9)
;; #7DCFFF #000000 0 0 0 1 ;; #7DCFFF #000000 0 0 0 0 1
(never_type (never_type
"!" @type.builtin2) "!" @type.builtin2)
@@ -577,19 +577,19 @@
; Panic / Assert / Debug Macros ; Panic / Assert / Debug Macros
; ============================================================ ; ============================================================
;; #FF6347 #000000 0 0 0 2 ;; #FF6347 #000000 0 0 0 0 2
(macro_invocation (macro_invocation
macro: (identifier) @_identifier1 @keyword.exception2 macro: (identifier) @_identifier1 @keyword.exception2
"!" @keyword.exception2 "!" @keyword.exception2
(#match? @_identifier1 "^panic$")) (#match? @_identifier1 "^panic$"))
;; #FF8F40 #000000 0 0 0 2 ;; #FF8F40 #000000 0 0 0 0 2
(macro_invocation (macro_invocation
macro: (identifier) @_identifier2 @keyword.exception3 macro: (identifier) @_identifier2 @keyword.exception3
"!" @keyword.exception3 "!" @keyword.exception3
(#match? @_identifier2 "assert")) (#match? @_identifier2 "assert"))
;; #7DCFFF #000000 0 0 0 2 ;; #7DCFFF #000000 0 0 0 0 2
(macro_invocation (macro_invocation
macro: (identifier) @_identifier3 @keyword.debug1 macro: (identifier) @_identifier3 @keyword.debug1
"!" @keyword.debug1 "!" @keyword.debug1
@@ -599,7 +599,7 @@
; Comments ; Comments
; ============================================================ ; ============================================================
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
[ [
(line_comment) (line_comment)
(block_comment) (block_comment)

View File

@@ -1,8 +1,8 @@
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(object_reference (object_reference
name: (identifier) @type) name: (identifier) @type)
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(invocation (invocation
(object_reference (object_reference
name: (identifier) @function.call)) name: (identifier) @function.call))
@@ -23,41 +23,41 @@
(keyword_object_id) (keyword_object_id)
] @function.call ] @function.call
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(relation (relation
alias: (identifier) @variable) alias: (identifier) @variable)
(term (term
alias: (identifier) @variable) alias: (identifier) @variable)
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(field (field
name: (identifier) @field) name: (identifier) @field)
;; #FF8F40 #000000 0 0 0 2 ;; #FF8F40 #000000 0 0 0 0 2
((literal) @number ((literal) @number
(#match? @number "^[-+0-9]+$")) (#match? @number "^[-+0-9]+$"))
;; #F29668 #000000 0 0 0 2 ;; #F29668 #000000 0 0 0 0 2
((literal) @float ((literal) @float
(#match? @float "^[-+0-9]+\\.[0-9]+$")) (#match? @float "^[-+0-9]+\\.[0-9]+$"))
;; #AAD94C #000000 0 0 0 0 ;; #AAD94C #000000 0 0 0 0 0
(literal) @string (literal) @string
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment @spell (comment) @comment @spell
(marginalia) @comment (marginalia) @comment
(parameter) @parameter (parameter) @parameter
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
[ [
(keyword_true) (keyword_true)
(keyword_false) (keyword_false)
] @boolean ] @boolean
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
[ [
(keyword_asc) (keyword_asc)
(keyword_desc) (keyword_desc)
@@ -88,7 +88,7 @@
(keyword_strict) (keyword_strict)
] @attribute ] @attribute
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
[ [
(keyword_materialized) (keyword_materialized)
(keyword_recursive) (keyword_recursive)
@@ -107,7 +107,7 @@
(keyword_volatile) (keyword_volatile)
] @storageclass ] @storageclass
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
[ [
(keyword_case) (keyword_case)
(keyword_when) (keyword_when)
@@ -115,7 +115,7 @@
(keyword_else) (keyword_else)
] @conditional ] @conditional
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
[ [
(keyword_select) (keyword_select)
(keyword_from) (keyword_from)
@@ -340,7 +340,7 @@
(keyword_while) (keyword_while)
] @keyword ] @keyword
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
[ [
(keyword_restrict) (keyword_restrict)
(keyword_unbounded) (keyword_unbounded)
@@ -367,7 +367,7 @@
(keyword_minvalue) (keyword_minvalue)
] @type.qualifier ] @type.qualifier
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
[ [
(keyword_int) (keyword_int)
(keyword_null) (keyword_null)
@@ -421,7 +421,7 @@
(keyword_interval) (keyword_interval)
] @type.builtin ] @type.builtin
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
[ [
(keyword_in) (keyword_in)
(keyword_and) (keyword_and)
@@ -435,7 +435,7 @@
(keyword_intersect) (keyword_intersect)
] @keyword.operator ] @keyword.operator
;; #F29668 #000000 0 1 0 1 ;; #F29668 #000000 0 1 0 0 1
[ [
"+" "+"
"-" "-"
@@ -455,13 +455,13 @@
(op_unary_other) (op_unary_other)
] @operator ] @operator
;; #888888 #000000 0 0 0 1 ;; #888888 #000000 0 0 0 0 1
[ [
"(" "("
")" ")"
] @punctuation.bracket ] @punctuation.bracket
;; #888888 #000000 0 1 0 1 ;; #888888 #000000 0 1 0 0 1
[ [
";" ";"
"," ","

View File

@@ -1,34 +1,34 @@
;; #F0F8FF #000000 0 0 0 2 ;; #F0F8FF #000000 0 0 0 0 2
(bare_key) @type (bare_key) @type
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
(quoted_key) @string.quoted (quoted_key) @string.quoted
;; #D2A6FF #000000 0 0 0 0 ;; #D2A6FF #000000 0 0 0 0 0
(pair (pair
(bare_key)) @property (bare_key)) @property
;; #D2A6FF #000000 0 0 0 0 ;; #D2A6FF #000000 0 0 0 0 0
(pair (pair
(dotted_key (dotted_key
(bare_key) @property)) (bare_key) @property))
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
(boolean) @boolean (boolean) @boolean
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment (comment) @comment
;; #AAD94C #000000 0 0 0 1 ;; #AAD94C #000000 0 0 0 0 1
(string) @string (string) @string
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
[ [
(integer) (integer)
(float) (float)
] @number ] @number
;; #FFFFFF #000000 0 0 0 1 ;; #FFFFFF #000000 0 0 0 0 1
[ [
(offset_date_time) (offset_date_time)
(local_date_time) (local_date_time)
@@ -36,16 +36,16 @@
(local_time) (local_time)
] @string.special ] @string.special
;; #888888 #000000 0 1 0 3 ;; #888888 #000000 0 1 0 0 3
[ [
"." "."
"," ","
] @punctuation.delimiter ] @punctuation.delimiter
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
"=" @operator "=" @operator
;; #888888 #000000 0 0 0 3 ;; #888888 #000000 0 0 0 0 3
[ [
"[" "["
"]" "]"

316
grammar/typescript.scm Normal file
View File

@@ -0,0 +1,316 @@
; ============================================================
; Identifiers
; ============================================================
;; #FFFFFF #000000 0 0 0 0 1
(identifier) @variable
;; #D2A6FF #000000 0 0 0 0 2
((identifier) @constant
(#match? @constant "^[A-Z_][A-Z0-9_]*$"))
;; #F07178 #000000 0 0 0 0 3
((identifier) @variable.builtin
(#match? @variable.builtin
"^(arguments|console|window|document|globalThis|process|module|exports)$"))
;; #59C2FF #000000 0 0 0 0 1
((identifier) @constructor
(#match? @constructor "^[A-Z][a-zA-Z0-9]*$"))
; ============================================================
; Properties
; ============================================================
;; #F07178 #000000 0 0 0 0 1
(property_identifier) @property
; ============================================================
; Functions
; ============================================================
;; #FFB454 #000000 0 0 0 0 3
(function_declaration
name: (identifier) @function)
(function_expression
name: (identifier) @function)
;; #FFB454 #000000 0 0 0 0 2
(method_definition
name: (property_identifier) @function.method)
(variable_declarator
name: (identifier) @function
value: [(function_expression) (arrow_function)])
(assignment_expression
left: (identifier) @function
right: [(function_expression) (arrow_function)])
(pair
key: (property_identifier) @function.method
value: [(function_expression) (arrow_function)])
; ------------------------------------------------------------
; Function calls
; ------------------------------------------------------------
;; #FFB454 #000000 0 0 0 0 2
(call_expression
function: (identifier) @function.call)
;; #FFB454 #000000 0 0 0 0 2
(call_expression
function: (member_expression
property: (property_identifier) @function.method))
; ============================================================
; Highlighted definitions & references
; ============================================================
;; #FFB454 #000000 0 0 0 0 3
(assignment_expression
left: [
(identifier) @name
(member_expression
property: (property_identifier) @name)
]
right: [(arrow_function) (function_expression)]
) @definition.function
;; #FFB454 #000000 0 0 0 0 3
(pair
key: (property_identifier) @name
value: [(arrow_function) (function_expression)]) @definition.function
;; #59C2FF #000000 0 0 0 0 0
((call_expression
function: (identifier) @name) @reference.call
(#not-match? @name "^(require)$"))
;; #7dcfff #000000 0 0 0 0 2
(new_expression
constructor: (_) @name) @reference.class
;; #D2A6FF #000000 0 0 0 0 2
(export_statement value: (assignment_expression left: (identifier) @name right: ([
(number)
(string)
(identifier)
(undefined)
(null)
(new_expression)
(binary_expression)
(call_expression)
]))) @definition.constant
; ============================================================
; Parameters
; ============================================================
;; #D2A6FF #000000 0 0 0 0 1
(formal_parameters
[
(identifier) @variable.parameter
(array_pattern
(identifier) @variable.parameter)
(object_pattern
[
(pair_pattern value: (identifier) @variable.parameter)
(shorthand_property_identifier_pattern) @variable.parameter
])
])
; ============================================================
; Keywords (split into semantic groups)
; ============================================================
;; #FF8F40 #000000 0 0 0 0 1
; Declarations
[
"var"
"let"
"const"
"function"
"class"
] @keyword.declaration
;; #FF8F40 #000000 0 0 0 0 1
; Control flow
[
"if"
"else"
"switch"
"case"
"default"
"for"
"while"
"do"
"break"
"continue"
"return"
"throw"
"try"
"catch"
"finally"
"extends"
] @keyword.control
;; #FF8F40 #000000 0 0 0 0 1
; Imports / exports
[
"import"
"export"
"from"
"as"
] @keyword.import
;; #F29668 #000000 0 0 0 0 1
; Operators-as-keywords
[
"in"
"instanceof"
"new"
"delete"
"typeof"
"void"
"await"
"yield"
] @keyword.operator
;; #FF8F40 #000000 0 0 0 0 1
; Modifiers
[
"async"
"static"
"get"
"set"
] @keyword.modifier
; ============================================================
; Literals
; ============================================================
;; #F07178 #000000 0 0 0 0 1
(this) @variable.builtin
(super) @variable.builtin
;; #D2A6FF #000000 0 0 0 0 4
[
(true)
(false)
(null)
(undefined)
] @constant.builtin
;; #D2A6FF #000000 0 0 0 0 2
(number) @number
;; #D2A6FF #000000 0 1 0 0 2
((string) @use_strict
(#match? @use_strict "^['\"]use strict['\"]$"))
;; #AAD94C #000000 0 0 0 0 0
(string) @string
;; #AAD94C #000000 0 0 0 0 0
(template_string) @string.special
;; #99ADBF #000000 0 1 0 0 1
(comment) @comment
; ============================================================
; Operators & punctuation
; ============================================================
;; #F29668 #000000 0 1 0 0 1
[
"+"
"-"
"*"
"/"
"%"
"**"
"++"
"--"
"=="
"!="
"==="
"!=="
"<"
"<="
">"
">="
"&&"
"||"
"??"
"!"
"~"
"&"
"|"
"^"
"<<"
">>"
">>>"
"="
"+="
"-="
"*="
"/="
"%="
"<<="
">>="
">>>="
"&="
"|="
"^="
"&&="
"||="
"??="
"=>"
] @operator
;; #BFBDB6 #000000 0 0 0 0 1
[
"."
","
";"
] @punctuation.delimiter
;; #BFBDB6 #000000 0 0 0 0 1
[
"("
")"
"["
"]"
"{"
"}"
] @punctuation.bracket
;; #7dcfff #000000 0 0 0 0 2
(template_substitution
"${" @punctuation.special
"}" @punctuation.special)
; ============================================================
; JSX
; ============================================================
;; #59C2FF #000000 0 0 0 0 4
(jsx_opening_element (identifier) @tag2)
(jsx_closing_element (identifier) @tag2)
(jsx_self_closing_element (identifier) @tag2)
;; #F07178 #000000 0 0 0 0 3
(jsx_attribute (property_identifier) @attribute2)
;; #BFBDB6 #000000 0 0 0 0 3
(jsx_opening_element (["<" ">"]) @punctuation.bracket2)
(jsx_closing_element (["</" ">"]) @punctuation.bracket2)
(jsx_self_closing_element (["<" "/>"]) @punctuation.bracket2)
; Injections
;; !regex
(regex) @string.regex

View File

@@ -1,47 +1,47 @@
;; #F29668 #000000 0 0 0 1 ;; #F29668 #000000 0 0 0 0 1
(boolean_scalar) @boolean (boolean_scalar) @boolean
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
(null_scalar) @constant.builtin (null_scalar) @constant.builtin
;; #AAD94C #000000 0 0 0 0 ;; #AAD94C #000000 0 0 0 0 0
[ [
(double_quote_scalar) (double_quote_scalar)
(single_quote_scalar) (single_quote_scalar)
] @string ] @string
;; #FFFFFF #000000 0 0 0 0 ;; #FFFFFF #000000 0 0 0 0 0
[ [
(block_scalar) (block_scalar)
(string_scalar) (string_scalar)
] @string.abs ] @string.abs
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
[ [
(integer_scalar) (integer_scalar)
(float_scalar) (float_scalar)
] @number ] @number
;; #99ADBF #000000 0 1 0 1 ;; #99ADBF #000000 0 1 0 0 1
(comment) @comment (comment) @comment
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
[ [
(anchor_name) (anchor_name)
(alias_name) (alias_name)
] @label ] @label
;; #7dcfff #000000 0 0 0 2 ;; #7dcfff #000000 0 0 0 0 2
(tag) @type (tag) @type
;; #F07178 #000000 0 0 0 1 ;; #F07178 #000000 0 0 0 0 1
[ [
(yaml_directive) (yaml_directive)
(tag_directive) (tag_directive)
(reserved_directive) (reserved_directive)
] @attribute ] @attribute
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(block_mapping_pair (block_mapping_pair
key: (flow_node key: (flow_node
[ [
@@ -49,13 +49,13 @@
(single_quote_scalar) (single_quote_scalar)
] @property)) ] @property))
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(block_mapping_pair (block_mapping_pair
key: (flow_node key: (flow_node
(plain_scalar (plain_scalar
(string_scalar) @property))) (string_scalar) @property)))
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(flow_mapping (flow_mapping
(_ (_
key: (flow_node key: (flow_node
@@ -64,14 +64,14 @@
(single_quote_scalar) (single_quote_scalar)
] @property))) ] @property)))
;; #D2A6FF #000000 0 0 0 1 ;; #D2A6FF #000000 0 0 0 0 1
(flow_mapping (flow_mapping
(_ (_
key: (flow_node key: (flow_node
(plain_scalar (plain_scalar
(string_scalar) @property)))) (string_scalar) @property))))
;; #F38BA8 #000000 0 1 0 3 ;; #F38BA8 #000000 0 1 0 0 3
[ [
"," ","
"-" "-"
@@ -81,7 +81,7 @@
"|" "|"
] @punctuation.delimiter ] @punctuation.delimiter
;; #888888 #000000 0 0 0 3 ;; #888888 #000000 0 0 0 0 3
[ [
"[" "["
"]" "]"
@@ -89,7 +89,7 @@
"}" "}"
] @punctuation.bracket ] @punctuation.bracket
;; #AAD94C #000000 0 1 0 3 ;; #AAD94C #000000 0 1 0 0 3
[ [
"*" "*"
"&" "&"

View File

@@ -0,0 +1,20 @@
#ifndef BOXES_DIAGNOSTICS_H
#define BOXES_DIAGNOSTICS_H
#include "editor/decl.h"
#include "io/ui.h"
#include "pch.h"
#include "utils/utils.h"
struct DiagnosticBox {
std::vector<VWarn> warnings;
std::vector<ScreenCell> cells;
uint32_t box_width;
uint32_t box_height;
void clear();
void render_first();
void render(Coord pos);
};
#endif

26
include/boxes/hover.h Normal file
View File

@@ -0,0 +1,26 @@
#ifndef BOXES_HOVER_H
#define BOXES_HOVER_H
#include "editor/decl.h"
#include "io/ui.h"
#include "pch.h"
#include "ts/decl.h"
#include "utils/utils.h"
struct HoverBox {
std::string text;
std::atomic<bool> is_markup;
uint32_t scroll_;
std::vector<ScreenCell> cells;
uint32_t box_width;
uint32_t box_height;
std::vector<Highlight> highlights;
std::vector<Span> hover_spans;
void clear();
void scroll(int32_t number);
void render_first(bool scroll = false);
void render(Coord pos);
};
#endif

291
include/config.h Normal file
View File

@@ -0,0 +1,291 @@
#ifndef CONFIG_H
#define CONFIG_H
#include "lsp/lsp.h"
#include "pch.h"
#include "ts/decl.h"
static const std::unordered_map<uint8_t, LSP> kLsps = {
{1,
{"clangd",
{
"clangd",
"--background-index",
"--clang-tidy",
"--completion-style=detailed",
"--header-insertion=never",
"--pch-storage=memory",
"--limit-results=50",
"--log=error",
nullptr,
}}},
{2,
{"ruby-lsp",
{
"ruby-lsp",
nullptr,
}}},
{3,
{"solargraph",
{
"solargraph",
"stdio",
nullptr,
}}},
{4,
{"bash-language-server",
{
"bash-language-server",
"start",
nullptr,
}}},
{5,
{"vscode-css-language-server",
{
"vscode-css-language-server",
"--stdio",
nullptr,
}}},
{6,
{"vscode-json-language-server",
{
"vscode-json-language-server",
"--stdio",
nullptr,
}}},
{7,
{"fish-lsp",
{
"fish-lsp",
"start",
nullptr,
}}},
{8,
{"gopls",
{
"gopls",
"serve",
nullptr,
}}},
{9,
{"haskell-language-server",
{
"haskell-language-server",
"lsp",
nullptr,
}}},
{10,
{"emmet-ls",
{
"emmet-ls",
"--stdio",
nullptr,
}}},
{11,
{"typescript-language-server",
{
"typescript-language-server",
"--stdio",
nullptr,
}}},
{12,
{"lua-language-server",
{
"lua-language-server",
nullptr,
}}},
{13,
{"pyright-langserver",
{
"pyright-langserver",
"--stdio",
nullptr,
}}},
{14,
{"rust-analyzer",
{
"rust-analyzer",
nullptr,
}}},
{15,
{"intelephense",
{
"intelephense",
"--stdio",
nullptr,
}}},
{16,
{"marksman",
{
"marksman",
"server",
nullptr,
}}},
{17,
{"nginx-language-server",
{
"nginx-language-server",
nullptr,
}}},
{18,
{"taplo",
{
"taplo",
"lsp",
"stdio",
nullptr,
}}},
{19,
{"yaml-language-server",
{
"yaml-language-server",
"--stdio",
nullptr,
}}},
{20,
{"sqls",
{
"sqls",
"serve",
nullptr,
}}},
{21,
{"make-language-server",
{
"make-language-server",
nullptr,
}}},
{22,
{"sql-language-server",
{
"sql-language-server",
"up",
"--method",
"stdio",
nullptr,
}}},
};
static const std::unordered_map<std::string, Language> kLanguages = {
{"bash", {"bash", LANG(bash), 4}},
{"c", {"c", LANG(cpp), 1}},
{"cpp", {"cpp", LANG(cpp), 1}},
{"h", {"h", LANG(cpp), 1}},
{"css", {"css", LANG(css), 5}},
{"fish", {"fish", LANG(fish), 7}},
{"go", {"go", LANG(go), 8}},
{"gomod", {"gomod", LANG(gomod), 8}},
{"haskell", {"haskell", LANG(haskell), 9}},
{"html", {"html", LANG(html), 10}},
{"javascript", {"javascript", LANG(javascript), 11}},
{"typescript", {"typescript", LANG(tsx), 11}},
{"json", {"json", LANG(json), 6}},
{"jsonc", {"jsonc", LANG(json), 6}},
{"erb", {"erb", LANG(embedded_template), 10}},
{"ruby", {"ruby", LANG(ruby), 3}},
{"lua", {"lua", LANG(lua), 12}},
{"python", {"python", LANG(python), 13}},
{"rust", {"rust", LANG(rust), 14}},
{"php", {"php", LANG(php), 15}},
{"markdown", {"markdown", LANG(markdown), 16}},
{"markdown_inline", {"markdown_inline", LANG(markdown_inline), 16}},
{"nginx", {"nginx", LANG(nginx), 17}},
{"toml", {"toml", LANG(toml), 18}},
{"yaml", {"yaml", LANG(yaml), 19}},
{"sql", {"sql", LANG(sql), 20}}, // Can use `22` for more accuracy but need
// config to connect to database
{"make", {"make", LANG(make), 21}},
{"gdscript", {"gdscript", LANG(gdscript)}}, // TODO: connect to godot
{"man", {"man", LANG(man)}},
{"diff", {"diff", LANG(diff)}},
{"gitattributes", {"gitattributes", LANG(gitattributes)}},
{"gitignore", {"gitignore", LANG(gitignore)}},
{"query", {"query", LANG(query)}},
{"regex", {"regex", LANG(regex)}},
{"ini", {"ini", LANG(ini)}},
};
static const std::unordered_map<std::string, std::string> kExtToLang = {
{"sh", "bash"},
{"bash", "bash"},
{"c", "c"},
{"cpp", "cpp"},
{"cxx", "cpp"},
{"cc", "cpp"},
{"hpp", "h"},
{"hh", "h"},
{"hxx", "h"},
{"h", "h"},
{"css", "css"},
{"fish", "fish"},
{"go", "go"},
{"hs", "haskell"},
{"html", "html"},
{"htm", "html"},
{"js", "javascript"},
{"jsx", "javascript"},
{"ts", "typescript"},
{"tsx", "typescript"},
{"json", "json"},
{"jsonc", "jsonc"},
{"lua", "lua"},
{"make", "make"},
{"mk", "make"},
{"makefile", "make"},
{"man", "man"},
{"py", "python"},
{"rb", "ruby"},
{"rs", "rust"},
{"diff", "diff"},
{"patch", "diff"},
{"erb", "erb"},
{"gd", "gdscript"},
{"gitattributes", "gitattributes"},
{"gitignore", "gitignore"},
{"mod", "gomod"},
{"ini", "ini"},
{"gitmodules", "ini"},
{"md", "markdown"},
{"markdown", "markdown"},
{"conf", "nginx"},
{"php", "php"},
{"scm", "query"},
{"regex", "regex"},
{"sql", "sql"},
{"toml", "toml"},
{"yaml", "yaml"},
{"yml", "yaml"},
};
static const std::unordered_map<std::string, std::string> kMimeToLang = {
{"text/x-c", "c"},
{"text/x-c++", "cpp"},
{"text/x-shellscript", "bash"},
{"application/json", "json"},
{"text/javascript", "javascript"},
{"text/html", "html"},
{"text/css", "css"},
{"text/x-python", "python"},
{"text/x-ruby", "ruby"},
{"text/x-go", "go"},
{"text/x-haskell", "haskell"},
{"text/x-rust", "rust"},
{"text/x-lua", "lua"},
{"text/x-diff", "diff"},
{"text/x-gdscript", "gdscript"},
{"text/x-gitattributes", "gitattributes"},
{"text/x-gitignore", "gitignore"},
{"text/x-gomod", "gomod"},
{"text/x-ini", "ini"},
{"text/markdown", "markdown"},
{"text/x-nginx-conf", "nginx"},
{"application/x-php", "php"},
{"text/x-tree-sitter-query", "query"},
{"text/x-regex", "regex"},
{"text/x-sql", "sql"},
{"text/x-toml", "toml"},
{"text/x-yaml", "yaml"},
{"text/x-man", "man"},
};
#endif

View File

@@ -1,269 +0,0 @@
#ifndef EDITOR_H
#define EDITOR_H
#include "./knot.h"
#include "./pch.h"
#include "./ui.h"
#include "./utils.h"
#include "ts_def.h"
#include <cstdint>
#include <shared_mutex>
#define CHAR 0
#define WORD 1
#define LINE 2
#define EXTRA_META 4
#define INDENT_WIDTH 2
struct Highlight {
uint32_t fg;
uint32_t bg;
uint32_t flags;
uint8_t priority;
};
struct Span {
uint32_t start;
uint32_t end;
Highlight *hl;
bool operator<(const Span &other) const { return start < other.start; }
};
struct Spans {
std::vector<Span> spans;
Queue<std::pair<uint32_t, int64_t>> edits;
bool mid_parse = false;
std::shared_mutex mtx;
};
struct Fold {
uint32_t start;
uint32_t end;
bool contains(uint32_t line) const { return line >= start && line <= end; }
bool operator<(const Fold &other) const { return start < other.start; }
};
struct SpanCursor {
Spans &spans;
size_t index = 0;
std::vector<Span *> active;
std::shared_lock<std::shared_mutex> lock;
SpanCursor(Spans &s) : spans(s) {}
Highlight *get_highlight(uint32_t byte_offset) {
for (int i = (int)active.size() - 1; i >= 0; i--)
if (active[i]->end <= byte_offset)
active.erase(active.begin() + i);
while (index < spans.spans.size() &&
spans.spans[index].start <= byte_offset) {
if (spans.spans[index].end > byte_offset)
active.push_back(const_cast<Span *>(&spans.spans[index]));
index++;
}
Highlight *best = nullptr;
int max_prio = -1;
for (auto *s : active)
if (s->hl->priority > max_prio) {
max_prio = s->hl->priority;
best = s->hl;
}
return best;
}
void sync(uint32_t byte_offset) {
lock = std::shared_lock(spans.mtx);
active.clear();
size_t left = 0, right = spans.spans.size();
while (left < right) {
size_t mid = (left + right) / 2;
if (spans.spans[mid].start <= byte_offset)
left = mid + 1;
else
right = mid;
}
index = left;
while (left > 0) {
left--;
if (spans.spans[left].end > byte_offset)
active.push_back(const_cast<Span *>(&spans.spans[left]));
else if (byte_offset - spans.spans[left].end > 1000)
break;
}
}
};
struct VHint {
Coord pos;
std::string hint;
bool operator<(const VHint &other) const { return pos < other.pos; }
};
struct VWarn {
uint32_t line;
std::string text;
int8_t type; // For hl
bool operator<(const VWarn &other) const { return line < other.line; }
};
struct VAI {
Coord pos;
char *text;
uint32_t len;
uint32_t lines; // number of \n in text for speed .. the ai part will not
// line wrap but multiline ones need to have its own lines
// after the first one
};
struct TSSetBase {
std::string lang;
TSParser *parser;
std::string query_file;
TSQuery *query;
std::map<uint16_t, Highlight> query_map;
std::map<uint16_t, Language> injection_map;
const TSLanguage *language;
};
struct TSSet : TSSetBase {
std::vector<TSRange> ranges;
};
struct TSSetMain : TSSetBase {
TSTree *tree;
std::unordered_map<std::string, TSSet> injections;
};
struct Editor {
std::string filename;
std::string uri;
Knot *root;
std::shared_mutex knot_mtx;
Coord cursor;
uint32_t cursor_preffered;
Coord selection;
bool selection_active;
int selection_type;
Coord position;
Coord size;
Coord scroll;
TSSetMain ts;
Queue<TSInputEdit> edit_queue;
std::vector<Fold> folds;
Spans spans;
Spans def_spans;
uint32_t hooks[94];
bool jumper_set;
std::shared_mutex v_mtx;
std::vector<VHint> hints;
std::vector<VWarn> warnings;
VAI ai;
std::shared_mutex lsp_mtx;
struct LSPInstance *lsp;
int lsp_version = 1;
};
inline const Fold *fold_for_line(const std::vector<Fold> &folds,
uint32_t line) {
auto it = std::lower_bound(
folds.begin(), folds.end(), line,
[](const Fold &fold, uint32_t value) { return fold.start < value; });
if (it != folds.end() && it->start == line)
return &(*it);
if (it != folds.begin()) {
--it;
if (it->contains(line))
return &(*it);
}
return nullptr;
}
inline Fold *fold_for_line(std::vector<Fold> &folds, uint32_t line) {
const auto *fold =
fold_for_line(static_cast<const std::vector<Fold> &>(folds), line);
return const_cast<Fold *>(fold);
}
inline bool line_is_fold_start(const std::vector<Fold> &folds, uint32_t line) {
const Fold *fold = fold_for_line(folds, line);
return fold && fold->start == line;
}
inline bool line_is_folded(const std::vector<Fold> &folds, uint32_t line) {
return fold_for_line(folds, line) != nullptr;
}
inline uint32_t next_unfolded_row(const Editor *editor, uint32_t row) {
uint32_t limit = editor && editor->root ? editor->root->line_count : 0;
while (row < limit) {
const Fold *fold = fold_for_line(editor->folds, row);
if (!fold)
return row;
row = fold->end + 1;
}
return limit;
}
inline uint32_t prev_unfolded_row(const Editor *editor, uint32_t row) {
while (row > 0) {
const Fold *fold = fold_for_line(editor->folds, row);
if (!fold)
return row;
if (fold->start == 0)
return 0;
row = fold->start - 1;
}
return 0;
}
void apply_edit(std::vector<Span> &spans, uint32_t x, int64_t y);
void apply_hook_insertion(Editor *editor, uint32_t line, uint32_t rows);
void apply_hook_deletion(Editor *editor, uint32_t removal_start,
uint32_t removal_end);
Editor *new_editor(const char *filename_arg, Coord position, Coord size);
void save_file(Editor *editor);
void free_editor(Editor *editor);
void render_editor(Editor *editor);
void fold(Editor *editor, uint32_t start_line, uint32_t end_line);
void cursor_up(Editor *editor, uint32_t number);
void cursor_down(Editor *editor, uint32_t number);
Coord move_left(Editor *editor, Coord cursor, uint32_t number);
Coord move_right(Editor *editor, Coord cursor, uint32_t number);
Coord move_left_pure(Editor *editor, Coord cursor, uint32_t number);
Coord move_right_pure(Editor *editor, Coord cursor, uint32_t number);
void cursor_left(Editor *editor, uint32_t number);
void cursor_right(Editor *editor, uint32_t number);
void scroll_up(Editor *editor, int32_t number);
void scroll_down(Editor *editor, uint32_t number);
void ensure_cursor(Editor *editor);
void indent_line(Editor *editor, uint32_t row);
void dedent_line(Editor *editor, uint32_t row);
void ensure_scroll(Editor *editor);
void handle_editor_event(Editor *editor, KeyEvent event);
void edit_erase(Editor *editor, Coord pos, int64_t len);
void edit_insert(Editor *editor, Coord pos, char *data, uint32_t len);
Coord editor_hit_test(Editor *editor, uint32_t x, uint32_t y);
char *get_selection(Editor *editor, uint32_t *out_len, Coord *out_start);
void editor_worker(Editor *editor);
void move_line_down(Editor *editor);
void move_line_up(Editor *editor);
void word_boundaries(Editor *editor, Coord coord, uint32_t *prev_col,
uint32_t *next_col, uint32_t *prev_clusters,
uint32_t *next_clusters);
void word_boundaries_exclusive(Editor *editor, Coord coord, uint32_t *prev_col,
uint32_t *next_col);
std::vector<Fold>::iterator find_fold_iter(Editor *editor, uint32_t line);
bool add_fold(Editor *editor, uint32_t start, uint32_t end);
bool remove_fold(Editor *editor, uint32_t line);
void apply_line_insertion(Editor *editor, uint32_t line, uint32_t rows);
void apply_line_deletion(Editor *editor, uint32_t removal_start,
uint32_t removal_end);
uint32_t leading_indent(const char *line, uint32_t len);
uint32_t get_indent(Editor *editor, Coord cursor);
bool closing_after_cursor(const char *line, uint32_t len, uint32_t col);
void editor_lsp_handle(Editor *editor, json msg);
#endif

45
include/editor/decl.h Normal file
View File

@@ -0,0 +1,45 @@
#ifndef EDITOR_DECL_H
#define EDITOR_DECL_H
#include "utils/utils.h"
struct Fold {
uint32_t start;
uint32_t end;
bool contains(uint32_t line) const { return line >= start && line <= end; }
bool operator<(const Fold &other) const { return start < other.start; }
};
struct Span {
uint32_t start;
uint32_t end;
Highlight *hl;
bool operator<(const Span &other) const { return start < other.start; }
};
struct VWarn {
uint32_t line;
std::string text;
std::string text_full;
std::string source;
std::string code;
std::vector<std::string> see_also;
int8_t type;
uint32_t start;
uint32_t end{UINT32_MAX};
bool operator<(const VWarn &other) const { return line < other.line; }
};
struct VAI {
Coord pos;
char *text;
uint32_t len;
uint32_t lines; // number of \n in text for speed .. the ai part will not
// line wrap but multiline ones need to have its own lines
// after the first one
};
#endif

106
include/editor/editor.h Normal file
View File

@@ -0,0 +1,106 @@
#ifndef EDITOR_H
#define EDITOR_H
#include "boxes/diagnostics.h"
#include "boxes/hover.h"
#include "editor/spans.h"
#include "io/knot.h"
#include "io/ui.h"
#include "ts/decl.h"
#include "utils/utils.h"
#define CHAR 0
#define WORD 1
#define LINE 2
#define EXTRA_META 4
#define INDENT_WIDTH 2
struct Editor {
std::string filename;
std::string uri;
Knot *root;
std::shared_mutex knot_mtx;
Coord cursor;
uint32_t cursor_preffered;
Coord selection;
bool selection_active;
int selection_type;
Coord position;
Coord size;
Coord scroll;
TSSetMain ts;
Queue<TSInputEdit> edit_queue;
std::vector<Fold> folds;
Spans spans;
Spans word_spans;
Spans hex_color_spans;
uint32_t hooks[94];
bool jumper_set;
std::shared_mutex v_mtx;
std::vector<VWarn> warnings;
bool warnings_dirty;
VAI ai;
std::shared_mutex lsp_mtx;
std::shared_ptr<struct LSPInstance> lsp;
bool hover_active;
HoverBox hover;
bool diagnostics_active;
DiagnosticBox diagnostics;
int lsp_version = 1;
};
Editor *new_editor(const char *filename_arg, Coord position, Coord size);
void save_file(Editor *editor);
void free_editor(Editor *editor);
void render_editor(Editor *editor);
void fold(Editor *editor, uint32_t start_line, uint32_t end_line);
void cursor_up(Editor *editor, uint32_t number);
void cursor_down(Editor *editor, uint32_t number);
Coord move_left(Editor *editor, Coord cursor, uint32_t number);
Coord move_right(Editor *editor, Coord cursor, uint32_t number);
Coord move_left_pure(Editor *editor, Coord cursor, uint32_t number);
Coord move_right_pure(Editor *editor, Coord cursor, uint32_t number);
void cursor_left(Editor *editor, uint32_t number);
void cursor_right(Editor *editor, uint32_t number);
void scroll_up(Editor *editor, int32_t number);
void scroll_down(Editor *editor, uint32_t number);
void ensure_cursor(Editor *editor);
void indent_line(Editor *editor, uint32_t row);
void dedent_line(Editor *editor, uint32_t row);
void ensure_scroll(Editor *editor);
void handle_editor_event(Editor *editor, KeyEvent event);
void edit_erase(Editor *editor, Coord pos, int64_t len);
void edit_insert(Editor *editor, Coord pos, char *data, uint32_t len);
Coord editor_hit_test(Editor *editor, uint32_t x, uint32_t y);
char *get_selection(Editor *editor, uint32_t *out_len, Coord *out_start);
void editor_worker(Editor *editor);
void move_line_down(Editor *editor);
void move_line_up(Editor *editor);
void word_boundaries(Editor *editor, Coord coord, uint32_t *prev_col,
uint32_t *next_col, uint32_t *prev_clusters,
uint32_t *next_clusters);
void word_boundaries_exclusive(Editor *editor, Coord coord, uint32_t *prev_col,
uint32_t *next_col);
std::vector<Fold>::iterator find_fold_iter(Editor *editor, uint32_t line);
bool add_fold(Editor *editor, uint32_t start, uint32_t end);
bool remove_fold(Editor *editor, uint32_t line);
uint32_t leading_indent(const char *line, uint32_t len);
uint32_t get_indent(Editor *editor, Coord cursor);
bool closing_after_cursor(const char *line, uint32_t len, uint32_t col);
void editor_lsp_handle(Editor *editor, json msg);
inline void apply_hook_insertion(Editor *editor, uint32_t line, uint32_t rows) {
for (auto &hook : editor->hooks)
if (hook > line)
hook += rows;
}
inline void apply_hook_deletion(Editor *editor, uint32_t removal_start,
uint32_t removal_end) {
for (auto &hook : editor->hooks)
if (hook > removal_start)
hook -= removal_end - removal_start + 1;
}
#endif

150
include/editor/folds.h Normal file
View File

@@ -0,0 +1,150 @@
#ifndef EDITOR_FOLDS_H
#define EDITOR_FOLDS_H
#include "editor/editor.h"
inline std::vector<Fold>::iterator find_fold_iter(Editor *editor,
uint32_t line) {
auto &folds = editor->folds;
auto it = std::lower_bound(
folds.begin(), folds.end(), line,
[](const Fold &fold, uint32_t value) { return fold.start < value; });
if (it != folds.end() && it->start == line)
return it;
if (it != folds.begin()) {
--it;
if (it->contains(line))
return it;
}
return folds.end();
}
inline bool add_fold(Editor *editor, uint32_t start, uint32_t end) {
if (!editor || !editor->root)
return false;
if (start > end)
std::swap(start, end);
if (start >= editor->root->line_count)
return false;
end = std::min(end, editor->root->line_count - 1);
if (start == end)
return false;
Fold new_fold{start, end};
auto &folds = editor->folds;
auto it = std::lower_bound(
folds.begin(), folds.end(), new_fold.start,
[](const Fold &fold, uint32_t value) { return fold.start < value; });
if (it != folds.begin()) {
auto prev = std::prev(it);
if (prev->end + 1 >= new_fold.start) {
new_fold.start = std::min(new_fold.start, prev->start);
new_fold.end = std::max(new_fold.end, prev->end);
it = folds.erase(prev);
}
}
while (it != folds.end() && it->start <= new_fold.end + 1) {
new_fold.end = std::max(new_fold.end, it->end);
it = folds.erase(it);
}
folds.insert(it, new_fold);
return true;
}
inline bool remove_fold(Editor *editor, uint32_t line) {
auto it = find_fold_iter(editor, line);
if (it == editor->folds.end())
return false;
editor->folds.erase(it);
return true;
}
inline void apply_line_insertion(Editor *editor, uint32_t line, uint32_t rows) {
for (auto it = editor->folds.begin(); it != editor->folds.end();) {
if (line <= it->start) {
it->start += rows;
it->end += rows;
++it;
} else if (line <= it->end) {
it = editor->folds.erase(it);
} else {
++it;
}
}
}
inline void apply_line_deletion(Editor *editor, uint32_t removal_start,
uint32_t removal_end) {
if (removal_start > removal_end)
return;
uint32_t rows_removed = removal_end - removal_start + 1;
std::vector<Fold> updated;
updated.reserve(editor->folds.size());
for (auto fold : editor->folds) {
if (removal_end < fold.start) {
fold.start -= rows_removed;
fold.end -= rows_removed;
updated.push_back(fold);
continue;
}
if (removal_start > fold.end) {
updated.push_back(fold);
continue;
}
}
editor->folds.swap(updated);
}
inline const Fold *fold_for_line(const std::vector<Fold> &folds,
uint32_t line) {
auto it = std::lower_bound(
folds.begin(), folds.end(), line,
[](const Fold &fold, uint32_t value) { return fold.start < value; });
if (it != folds.end() && it->start == line)
return &(*it);
if (it != folds.begin()) {
--it;
if (it->contains(line))
return &(*it);
}
return nullptr;
}
inline Fold *fold_for_line(std::vector<Fold> &folds, uint32_t line) {
const auto *fold =
fold_for_line(static_cast<const std::vector<Fold> &>(folds), line);
return const_cast<Fold *>(fold);
}
inline bool line_is_fold_start(const std::vector<Fold> &folds, uint32_t line) {
const Fold *fold = fold_for_line(folds, line);
return fold && fold->start == line;
}
inline bool line_is_folded(const std::vector<Fold> &folds, uint32_t line) {
return fold_for_line(folds, line) != nullptr;
}
inline uint32_t next_unfolded_row(const Editor *editor, uint32_t row) {
uint32_t limit = editor && editor->root ? editor->root->line_count : 0;
while (row < limit) {
const Fold *fold = fold_for_line(editor->folds, row);
if (!fold)
return row;
row = fold->end + 1;
}
return limit;
}
inline uint32_t prev_unfolded_row(const Editor *editor, uint32_t row) {
while (row > 0) {
const Fold *fold = fold_for_line(editor->folds, row);
if (!fold)
return row;
if (fold->start == 0)
return 0;
row = fold->start - 1;
}
return 0;
}
#endif

85
include/editor/spans.h Normal file
View File

@@ -0,0 +1,85 @@
#ifndef EDITOR_SPANS_H
#define EDITOR_SPANS_H
#include "editor/decl.h"
#include "utils/utils.h"
struct Spans {
std::vector<Span> spans;
Queue<std::pair<uint32_t, int64_t>> edits;
std::atomic<bool> mid_parse = false;
std::shared_mutex mtx;
};
struct SpanCursor {
Spans &spans;
size_t index = 0;
std::vector<Span *> active;
std::shared_lock<std::shared_mutex> lock;
SpanCursor(Spans &s) : spans(s) {}
Highlight *get_highlight(uint32_t byte_offset) {
for (int i = (int)active.size() - 1; i >= 0; i--)
if (active[i]->end <= byte_offset)
active.erase(active.begin() + i);
while (index < spans.spans.size() &&
spans.spans[index].start <= byte_offset) {
if (spans.spans[index].end > byte_offset)
active.push_back(const_cast<Span *>(&spans.spans[index]));
index++;
}
Highlight *best = nullptr;
int max_prio = -1;
for (auto *s : active)
if (s->hl->priority > max_prio) {
max_prio = s->hl->priority;
best = s->hl;
}
return best;
}
void sync(uint32_t byte_offset) {
lock = std::shared_lock(spans.mtx);
active.clear();
size_t left = 0, right = spans.spans.size();
while (left < right) {
size_t mid = (left + right) / 2;
if (spans.spans[mid].start <= byte_offset)
left = mid + 1;
else
right = mid;
}
index = left;
while (left > 0) {
left--;
if (spans.spans[left].end > byte_offset)
active.push_back(const_cast<Span *>(&spans.spans[left]));
else if (byte_offset - spans.spans[left].end > 1000)
break;
}
}
};
inline void apply_edit(std::vector<Span> &spans, uint32_t x, int64_t y) {
Span key{.start = x, .end = 0, .hl = nullptr};
auto it = std::lower_bound(
spans.begin(), spans.end(), key,
[](const Span &a, const Span &b) { return a.start < b.start; });
size_t idx = std::distance(spans.begin(), it);
while (idx > 0 && spans.at(idx - 1).end >= x)
--idx;
for (size_t i = idx; i < spans.size();) {
Span &s = spans.at(i);
if (s.start < x && s.end >= x) {
s.end += y;
} else if (s.start > x) {
s.start += y;
s.end += y;
}
if (s.end <= s.start)
spans.erase(spans.begin() + i);
else
++i;
}
}
#endif

View File

@@ -1,13 +1,11 @@
#ifndef ROPE_H #ifndef ROPE_H
#define ROPE_H #define ROPE_H
#include "./pch.h" #include "pch.h"
#include "./utils.h" #include "utils/utils.h"
#define MIN_CHUNK_SIZE 64 // 64 Bytes #define MIN_CHUNK_SIZE 64 // 64 Bytes
#define MAX_CHUNK_SIZE 1024 * 8 // 8192 Bytes (8 KiB) #define MAX_CHUNK_SIZE 1024 * 8 // 8192 Bytes (8 KiB)
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define DEPTH(n) ((n) ? (n)->depth : 0) #define DEPTH(n) ((n) ? (n)->depth : 0)
// Rope node definition // Rope node definition
@@ -161,9 +159,11 @@ char *leaf_from_offset(Knot *root, uint32_t start_offset, uint32_t *out_len);
// compliant) I.e some forms of backtracking etc. are not supported // compliant) I.e some forms of backtracking etc. are not supported
// root is the root of the rope to be searched // root is the root of the rope to be searched
// Returns a vector of pairs of start and length offsets (in bytes) // Returns a vector of pairs of start and length offsets (in bytes)
std::vector<std::pair<size_t, size_t>> search_rope(Knot *root, std::vector<std::pair<size_t, size_t>> search_rope_dfa(Knot *root,
const char *pattern); const char *pattern);
std::vector<Match> search_rope(Knot *root, const char *pattern);
// Helper function to free the rope // Helper function to free the rope
// root is the root of the rope // root is the root of the rope
// the root is no longer valid after call // the root is no longer valid after call

View File

@@ -1,8 +1,8 @@
#ifndef UI_H #ifndef UI_H
#define UI_H #define UI_H
#include "./pch.h" #include "pch.h"
#include "./utils.h" #include "utils/utils.h"
#define KEY_CHAR 0 #define KEY_CHAR 0
#define KEY_SPECIAL 1 #define KEY_SPECIAL 1
@@ -49,13 +49,16 @@ enum CellFlags : uint8_t {
CF_ITALIC = 1 << 0, CF_ITALIC = 1 << 0,
CF_BOLD = 1 << 1, CF_BOLD = 1 << 1,
CF_UNDERLINE = 1 << 2, CF_UNDERLINE = 1 << 2,
CF_STRIKETHROUGH = 1 << 3
}; };
struct ScreenCell { struct ScreenCell {
std::string utf8 = std::string(""); std::string utf8 = std::string("");
uint8_t width = 1;
uint32_t fg = 0; uint32_t fg = 0;
uint32_t bg = 0; uint32_t bg = 0;
uint8_t flags = CF_NONE; uint8_t flags = CF_NONE;
uint32_t ul_color = 0;
}; };
struct KeyEvent { struct KeyEvent {
@@ -86,6 +89,10 @@ void update(uint32_t row, uint32_t col, std::string utf8, uint32_t fg,
uint32_t bg, uint8_t flags); uint32_t bg, uint8_t flags);
void update(uint32_t row, uint32_t col, const char *utf8, uint32_t fg, void update(uint32_t row, uint32_t col, const char *utf8, uint32_t fg,
uint32_t bg, uint8_t flags); uint32_t bg, uint8_t flags);
void update(uint32_t row, uint32_t col, std::string utf8, uint32_t fg,
uint32_t bg, uint8_t flags, uint32_t ul_color);
void update(uint32_t row, uint32_t col, const char *utf8, uint32_t fg,
uint32_t bg, uint8_t flags, uint32_t ul_color);
void set_cursor(int row, int col, int type, bool show_cursor_param); void set_cursor(int row, int col, int type, bool show_cursor_param);
void render(); void render();
Coord get_size(); Coord get_size();

View File

@@ -1,55 +0,0 @@
#ifndef LSP_H
#define LSP_H
#include "./editor.h"
#include "./pch.h"
#include "utils.h"
struct LSP {
const char *command;
std::vector<const char *> args;
};
struct LSPPending {
std::string method;
Editor *editor = nullptr;
std::function<void(Editor *, std::string, json)> callback;
};
struct LSPOpenRequest {
Language language;
Editor *editor;
};
struct LSPInstance {
std::shared_mutex mtx;
const LSP *lsp;
std::string root_dir;
int pid{-1};
int stdin_fd{-1};
int stdout_fd{-1};
bool initialized = false;
uint32_t last_id = 0;
Queue<json> inbox;
Queue<json> outbox;
std::unordered_map<uint32_t, LSPPending *> pending;
std::vector<Editor *> editors;
};
extern std::shared_mutex active_lsps_mtx;
extern std::unordered_map<uint8_t, LSPInstance *> active_lsps;
void lsp_worker();
void lsp_handle(LSPInstance *lsp, json message);
LSPInstance *get_or_init_lsp(uint8_t lsp_id);
void close_lsp(uint8_t lsp_id);
void request_add_to_lsp(Language language, Editor *editor);
void add_to_lsp(Language language, Editor *editor);
void remove_from_lsp(Editor *editor);
void lsp_send(LSPInstance *lsp, json message, LSPPending *pending);
#endif

81
include/lsp/lsp.h Normal file
View File

@@ -0,0 +1,81 @@
#ifndef LSP_H
#define LSP_H
#include "editor/editor.h"
#include "pch.h"
#include "utils/utils.h"
struct LSP {
const char *command;
std::vector<const char *> args;
};
struct LSPPending {
std::string method;
Editor *editor = nullptr;
std::function<void(Editor *, std::string, json)> callback;
};
struct LSPOpenRequest {
Language language;
Editor *editor;
};
struct LSPInstance {
std::shared_mutex mtx;
const LSP *lsp;
std::string root_dir;
int pid{-1};
int stdin_fd{-1};
int stdout_fd{-1};
std::atomic<bool> initialized = false;
std::atomic<bool> exited = false;
bool incremental_sync = false;
bool allow_hover = false;
bool allow_completion = false;
std::string trigger_chars;
uint32_t last_id = 0;
Queue<json> inbox;
Queue<json> outbox;
Queue<std::pair<Language, Editor *>> open_queue;
std::unordered_map<uint32_t, LSPPending *> pending;
std::vector<Editor *> editors;
};
extern std::shared_mutex active_lsps_mtx;
extern std::unordered_map<uint8_t, std::shared_ptr<LSPInstance>> active_lsps;
extern Queue<LSPOpenRequest> lsp_open_queue;
static json client_capabilities = {
{"textDocument",
{{"publishDiagnostics", {{"relatedInformation", true}}},
{"hover", {{"contentFormat", {"markdown", "plaintext"}}}},
{"completion",
{{"completionItem",
{{"snippetSupport", true},
{"documentationFormat", {"markdown", "plaintext"}},
{"resolveSupport", {{"properties", {"documentation", "detail"}}}},
{"insertReplaceSupport", true},
{"labelDetailsSupport", true},
{"insertTextModeSupport", {{"valueSet", {1}}}}}},
{"completionItemKind", {{"valueSet", {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}}},
{"contextSupport", true},
{"insertTextMode", 1}}}}}};
void lsp_send(std::shared_ptr<LSPInstance> lsp, json message,
LSPPending *pending);
void lsp_worker();
std::shared_ptr<LSPInstance> get_or_init_lsp(uint8_t lsp_id);
void clean_lsp(std::shared_ptr<LSPInstance> lsp, uint8_t lsp_id);
void close_lsp(uint8_t lsp_id);
void open_editor(std::shared_ptr<LSPInstance> lsp,
std::pair<Language, Editor *> entry);
void request_add_to_lsp(Language language, Editor *editor);
void add_to_lsp(Language language, Editor *editor);
void remove_from_lsp(Editor *editor);
void lsp_handle(std::shared_ptr<LSPInstance> lsp, json message);
#endif

View File

@@ -1,7 +1,7 @@
#ifndef MAIN_H #ifndef MAIN_H
#define MAIN_H #define MAIN_H
#include "./pch.h" #include "pch.h"
#define NORMAL 0 #define NORMAL 0
#define INSERT 1 #define INSERT 1

View File

@@ -1,139 +0,0 @@
#ifndef MAPS_H
#define MAPS_H
#include "./lsp.h"
#include "./pch.h"
#include "./ts_def.h"
static const std::unordered_map<uint8_t, LSP> kLsps = {
{1,
{"clangd",
{
"clangd",
"--background-index",
"--clang-tidy",
"--completion-style=detailed",
"--header-insertion=never",
"--pch-storage=memory",
"--limit-results=50",
"--log=error",
nullptr,
}}},
};
static const std::unordered_map<std::string, Language> kLanguages = {
{"bash", {"bash", LANG(bash)}},
{"c", {"c", LANG(cpp), 1}},
{"cpp", {"cpp", LANG(cpp), 1}},
{"h", {"h", LANG(cpp), 1}},
{"css", {"css", LANG(css)}},
{"fish", {"fish", LANG(fish)}},
{"go", {"go", LANG(go)}},
{"haskell", {"haskell", LANG(haskell)}},
{"html", {"html", LANG(html)}},
{"javascript", {"javascript", LANG(javascript)}},
{"json", {"json", LANG(json)}},
{"lua", {"lua", LANG(lua)}},
{"make", {"make", LANG(make)}},
{"python", {"python", LANG(python)}},
{"ruby", {"ruby", LANG(ruby)}},
{"rust", {"rust", LANG(rust)}},
{"diff", {"diff", LANG(diff)}},
{"embedded_template", {"embedded_template", LANG(embedded_template)}},
{"gdscript", {"gdscript", LANG(gdscript)}},
{"gitattributes", {"gitattributes", LANG(gitattributes)}},
{"gitignore", {"gitignore", LANG(gitignore)}},
{"gomod", {"gomod", LANG(gomod)}},
{"ini", {"ini", LANG(ini)}},
{"markdown", {"markdown", LANG(markdown)}},
{"markdown_inline", {"markdown_inline", LANG(markdown_inline)}},
{"nginx", {"nginx", LANG(nginx)}},
{"php", {"php", LANG(php)}},
{"query", {"query", LANG(query)}},
{"regex", {"regex", LANG(regex)}},
{"sql", {"sql", LANG(sql)}},
{"toml", {"toml", LANG(toml)}},
{"yaml", {"yaml", LANG(yaml)}},
};
static const std::unordered_map<std::string, std::string> kExtToLang = {
{"sh", "bash"},
{"bash", "bash"},
{"c", "c"},
{"cpp", "cpp"},
{"cxx", "cpp"},
{"cc", "cpp"},
{"hpp", "h"},
{"hh", "h"},
{"hxx", "h"},
{"h", "h"},
{"css", "css"},
{"fish", "fish"},
{"go", "go"},
{"hs", "haskell"},
{"html", "html"},
{"htm", "html"},
{"js", "javascript"},
{"jsx", "javascript"},
{"json", "json"},
{"jsonc", "json"},
{"lua", "lua"},
{"mk", "make"},
{"makefile", "make"},
{"py", "python"},
{"rb", "ruby"},
{"rs", "rust"},
{"diff", "diff"},
{"patch", "diff"},
{"erb", "embedded_template"},
{"etlua", "embedded_template"},
{"gd", "gdscript"},
{"gitattributes", "gitattributes"},
{"gitignore", "gitignore"},
{"mod", "gomod"},
{"ini", "ini"},
{"gitmodules", "ini"},
{"md", "markdown"},
{"markdown", "markdown"},
{"conf", "nginx"},
{"php", "php"},
{"scm", "query"},
{"regex", "regex"},
{"sql", "sql"},
{"toml", "toml"},
{"yaml", "yaml"},
{"yml", "yaml"},
};
static const std::unordered_map<std::string, std::string> kMimeToLang = {
{"text/x-c", "c"},
{"text/x-c++", "cpp"},
{"text/x-shellscript", "bash"},
{"application/json", "json"},
{"text/javascript", "javascript"},
{"text/html", "html"},
{"text/css", "css"},
{"text/x-python", "python"},
{"text/x-ruby", "ruby"},
{"text/x-go", "go"},
{"text/x-haskell", "haskell"},
{"text/x-rust", "rust"},
{"text/x-lua", "lua"},
{"text/x-diff", "diff"},
{"text/x-embedded-template", "embedded_template"},
{"text/x-gdscript", "gdscript"},
{"text/x-gitattributes", "gitattributes"},
{"text/x-gitignore", "gitignore"},
{"text/x-gomod", "gomod"},
{"text/x-ini", "ini"},
{"text/markdown", "markdown"},
{"text/x-nginx-conf", "nginx"},
{"application/x-php", "php"},
{"text/x-tree-sitter-query", "query"},
{"text/x-regex", "regex"},
{"text/x-sql", "sql"},
{"text/x-toml", "toml"},
{"text/x-yaml", "yaml"},
};
#endif

View File

@@ -4,17 +4,23 @@
#define PCRE2_CODE_UNIT_WIDTH 8 #define PCRE2_CODE_UNIT_WIDTH 8
#define PCRE_WORKSPACE_SIZE 512 #define PCRE_WORKSPACE_SIZE 512
#include "../libs/tree-sitter/lib/include/tree_sitter/api.h" extern "C" {
#include "libgrapheme/grapheme.h"
#include "unicode_width/unicode_width.h"
}
#include "tree-sitter/lib/include/tree_sitter/api.h"
#include <algorithm> #include <algorithm>
#include <atomic> #include <atomic>
#include <cctype> #include <cctype>
#include <chrono> #include <chrono>
#include <cmath>
#include <cstdarg> #include <cstdarg>
#include <cstdint> #include <cstdint>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <deque> #include <deque>
#include <fcntl.h>
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include <functional> #include <functional>
@@ -27,9 +33,13 @@
#include <pcre2.h> #include <pcre2.h>
#include <queue> #include <queue>
#include <shared_mutex> #include <shared_mutex>
#include <signal.h>
#include <string.h> #include <string.h>
#include <string> #include <string>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/poll.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <termios.h> #include <termios.h>
#include <thread> #include <thread>
#include <unistd.h> #include <unistd.h>

View File

@@ -1,7 +1,7 @@
#ifndef TS_DEF_H #ifndef TS_DECL_H
#define TS_DEF_H #define TS_DECL_H
#include "./pch.h" #include "pch.h"
#define LANG(name) tree_sitter_##name #define LANG(name) tree_sitter_##name
#define TS_DEF(name) extern "C" const TSLanguage *LANG(name)() #define TS_DEF(name) extern "C" const TSLanguage *LANG(name)()
@@ -12,6 +12,32 @@ struct Language {
uint8_t lsp_id = 0; uint8_t lsp_id = 0;
}; };
struct Highlight {
uint32_t fg;
uint32_t bg;
uint32_t flags;
uint8_t priority;
};
struct TSSetBase {
std::string lang;
TSParser *parser;
std::string query_file;
TSQuery *query;
TSTree *tree;
std::map<uint16_t, Highlight> query_map;
std::map<uint16_t, Language> injection_map;
const TSLanguage *language;
};
struct TSSet : TSSetBase {
std::vector<TSRange> ranges;
};
struct TSSetMain : TSSetBase {
std::unordered_map<std::string, TSSet> injections;
};
TS_DEF(ruby); TS_DEF(ruby);
TS_DEF(bash); TS_DEF(bash);
TS_DEF(cpp); TS_DEF(cpp);
@@ -21,6 +47,8 @@ TS_DEF(go);
TS_DEF(haskell); TS_DEF(haskell);
TS_DEF(html); TS_DEF(html);
TS_DEF(javascript); TS_DEF(javascript);
TS_DEF(tsx);
TS_DEF(man);
TS_DEF(json); TS_DEF(json);
TS_DEF(lua); TS_DEF(lua);
TS_DEF(regex); TS_DEF(regex);

View File

@@ -1,9 +1,9 @@
#ifndef TS_H #ifndef TS_H
#define TS_H #define TS_H
#include "./editor.h" #include "editor/editor.h"
#include "./pch.h" #include "pch.h"
#include "./utils.h" #include "utils/utils.h"
#define HEX(s) (static_cast<uint32_t>(std::stoul(s, nullptr, 16))) #define HEX(s) (static_cast<uint32_t>(std::stoul(s, nullptr, 16)))
@@ -11,6 +11,8 @@ extern std::unordered_map<std::string, pcre2_code *> regex_cache;
TSQuery *load_query(const char *query_path, TSSetBase *set); TSQuery *load_query(const char *query_path, TSSetBase *set);
void ts_collect_spans(Editor *editor); void ts_collect_spans(Editor *editor);
bool ts_predicate(TSQuery *query, const TSQueryMatch &match,
std::function<std::string(const TSNode *)> subject_fn);
void clear_regex_cache(); void clear_regex_cache();
#endif #endif

View File

@@ -1,8 +1,8 @@
#ifndef UTILS_H #ifndef UTILS_H
#define UTILS_H #define UTILS_H
#include "./pch.h" #include "pch.h"
#include "./ts_def.h" #include "ts/decl.h"
template <typename T> struct Queue { template <typename T> struct Queue {
std::queue<T> q; std::queue<T> q;
@@ -12,8 +12,9 @@ template <typename T> struct Queue {
std::lock_guard<std::mutex> lock(m); std::lock_guard<std::mutex> lock(m);
q.push(val); q.push(val);
} }
T front() { std::optional<T> front() {
std::lock_guard<std::mutex> lock(m); if (q.empty())
return std::nullopt;
return q.front(); return q.front();
} }
bool pop(T &val) { bool pop(T &val) {
@@ -52,22 +53,47 @@ struct Coord {
bool operator>=(const Coord &other) const { return !(*this < other); } bool operator>=(const Coord &other) const { return !(*this < other); }
}; };
std::string path_abs(const std::string &path_str); struct Match {
std::string path_to_file_uri(const std::string &path_str); size_t start;
size_t end;
std::string text;
};
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
std::string clean_text(const std::string &input);
std::string percent_encode(const std::string &s);
std::string percent_decode(const std::string &s);
uint32_t count_clusters(const char *line, size_t len, size_t from, size_t to);
std::string trim(const std::string &s);
int display_width(const char *str, size_t len); int display_width(const char *str, size_t len);
uint32_t get_visual_col_from_bytes(const char *line, uint32_t len, uint32_t get_visual_col_from_bytes(const char *line, uint32_t len,
uint32_t byte_limit); uint32_t byte_limit);
uint32_t get_bytes_from_visual_col(const char *line, uint32_t len, uint32_t get_bytes_from_visual_col(const char *line, uint32_t len,
uint32_t target_visual_col); uint32_t target_visual_col);
int utf8_byte_offset_to_utf16(const char *s, size_t byte_pos);
void log(const char *fmt, ...); void log(const char *fmt, ...);
std::string path_abs(const std::string &path_str);
std::string path_to_file_uri(const std::string &path_str);
std::string get_exe_dir(); std::string get_exe_dir();
char *load_file(const char *path, uint32_t *out_len); char *load_file(const char *path, uint32_t *out_len);
char *detect_file_type(const char *filename); char *detect_file_type(const char *filename);
int utf8_byte_offset_to_utf16(const char *s, size_t byte_pos);
Language language_for_file(const char *filename); Language language_for_file(const char *filename);
void copy_to_clipboard(const char *text, size_t len); void copy_to_clipboard(const char *text, size_t len);
char *get_from_clipboard(uint32_t *out_len); char *get_from_clipboard(uint32_t *out_len);
uint32_t count_clusters(const char *line, size_t len, size_t from, size_t to);
template <typename T>
inline T *safe_get(std::map<uint16_t, T> &m, uint16_t key) {
auto it = m.find(key);
if (it == m.end())
return nullptr;
return &it->second;
}
template <typename Func, typename... Args> template <typename Func, typename... Args>
auto throttle(std::chrono::milliseconds min_duration, Func &&func, auto throttle(std::chrono::milliseconds min_duration, Func &&func,

1
libs/tree-sitter-man Submodule

Submodule libs/tree-sitter-man added at e332ea95d5

View File

@@ -13,7 +13,7 @@ local name = "Lua"
print(self) print(self)
-- Functions -- Functions
function greet(user) local function greet(user)
print("Hello, " .. user) print("Hello, " .. user)
end end

View File

@@ -1,6 +1,9 @@
# Heading 1 # Heading 1
## Heading 2 ones
content
# Heading 2
### Heading 3 ### Heading 3
@@ -31,11 +34,12 @@ This is a paragraph with **bold text**, *italic text*, ~~strikethrough~~, and `i
`Inline code` example and a fenced code block: `Inline code` example and a fenced code block:
```python ```lua
def hello_world(): local s2 = [[Long
print("Hello, world!") multi-line
string]]
``` ```
![Image](https://example.com/image.jpg) ![Image](https://example.com/image.jpg)
> "This is a quote with a link to [OpenAI](https://openai.com)." > "This is a quote with a link to [Top](#Heading%202)."

View File

@@ -12,7 +12,7 @@ end
# Emoji-heavy strings # Emoji-heavy strings
emojis = "👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏" emojis = "👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏👋🌏"
# Mixed-width CJK blocks # Mixed-width CJK block
cjk_samples = [ cjk_samples = [
"漢字テスト", "漢字テスト",
"測試中文字串", "測試中文字串",
@@ -173,6 +173,11 @@ end
# Method definition # Method definition
def greet_person(name) def greet_person(name)
puts "#{Utilities.random_greeting}, #{name}!" puts "#{Utilities.random_greeting}, #{name}!"
if (name == "harry")
return true
else
return "s"
end
end end
# Calling methods # Calling methods

66
samples/yaml.yaml Normal file
View File

@@ -0,0 +1,66 @@
# ============================================================
# Basic types
# ============================================================
title: "Example YAML Configuration"
enabled: true
count: 42
pi: 3.14159
empty: ""
# ============================================================
# Arrays / Lists
# ============================================================
fruits:
- apple
- banana
- cherry
numbers:
- 1
- 2
- 3
- 4
- 5
matrix:
- [1, 2]
- [3, 4]
# ============================================================
# Nested objects / maps
# ============================================================
owner:
name: Alice
dob: 1979-05-27T07:32:00Z
database:
server: 192.168.1.1
ports:
- 8001
- 8001
- 8002
connection_max: 5000
enabled: true
servers:
alpha:
ip: 10.0.0.1
dc: east
beta:
ip: 10.0.0.2
dc: west
# ============================================================
# Multiline string
# ============================================================
description: |
This is a YAML file
used for testing syntax highlighting.
It supports multiple lines.
# ============================================================
# Special characters
# ============================================================
regex_pattern: "^[A-Za-z0-9_]+$"
path: "C:\\Users\\Alice\\Documents"

150
src/boxes/diagnostics.cc Normal file
View File

@@ -0,0 +1,150 @@
#include "boxes/diagnostics.h"
void DiagnosticBox::clear() {
warnings.clear();
cells.clear();
box_width = 0;
box_height = 0;
}
void DiagnosticBox::render_first() {
if (warnings.empty())
return;
uint32_t longest_line = 8 + warnings[0].source.length();
for (auto &warn : warnings) {
longest_line = MAX(longest_line, (uint32_t)warn.text.length() + 7);
longest_line = MAX(longest_line, (uint32_t)warn.code.length() + 4);
for (auto &see_also : warn.see_also)
longest_line = MAX(longest_line, (uint32_t)see_also.length() + 4);
}
uint32_t content_width = MIN(longest_line, 150u);
box_width = content_width + 2;
cells.assign(box_width * 25, {" ", 0, 0, 0, 0, 0});
auto set = [&](uint32_t r, uint32_t c, const char *text, uint32_t fg,
uint32_t bg, uint8_t flags) {
cells[r * box_width + c] = {std::string(text), 0, fg, bg, flags, 0};
};
uint32_t base_bg = 0;
uint32_t border_fg = 0x82AAFF;
uint32_t r = 0;
if (warnings[0].source != "") {
std::string src_txt = "Source: ";
for (uint32_t i = 0; i < src_txt.length() && i < content_width; i++)
set(1, i + 1, (char[2]){src_txt[i], 0}, 0x3EAAFF, base_bg, 0);
for (uint32_t i = 0; i < warnings[0].source.length() && i < content_width;
i++)
set(1, i + 1 + src_txt.length(), (char[2]){warnings[0].source[i], 0},
0xffffff, base_bg, 0);
r++;
}
int idx = 1;
for (auto &warn : warnings) {
char buf[4];
std::snprintf(buf, sizeof(buf), "%2d", idx % 100);
std::string line_txt = std::string(buf) + ". ";
for (uint32_t i = 0; i < line_txt.length(); i++)
set(r + 1, i + 1, (char[2]){line_txt[i], 0}, 0xffffff, base_bg, 0);
if (r >= 23)
break;
const char *err_sym = "";
uint32_t c_sym = 0xAAAAAA;
switch (warn.type) {
case 1:
err_sym = "";
c_sym = 0xFF0000;
break;
case 2:
err_sym = "";
c_sym = 0xFFFF00;
break;
case 3:
err_sym = "";
c_sym = 0xFF00FF;
break;
case 4:
err_sym = "";
c_sym = 0xAAAAAA;
break;
}
std::string text = warn.text_full + " " + err_sym;
uint32_t i = 0;
while (i < text.length() && r < 23) {
uint32_t c = 4;
while (c < content_width && i < text.length()) {
if (text[i] == '\n') {
while (i < text.length() && text[i] == '\n')
i++;
break;
}
uint32_t cluster_len = grapheme_next_character_break_utf8(
text.c_str() + i, text.length() - i);
std::string cluster = text.substr(i, cluster_len);
int width = display_width(cluster.c_str(), cluster_len);
if (c + width > content_width)
break;
set(r + 1, c + 1, cluster.c_str(), c_sym, base_bg, 0);
c += width;
i += cluster_len;
for (int w = 1; w < width; w++)
set(r + 1, c - w + 1, "\x1b", c_sym, base_bg, 0);
}
r++;
}
if (r >= 23)
break;
if (warn.code != "") {
for (uint32_t i = 0; i < warn.code.length() && i + 5 < content_width; i++)
set(r + 1, i + 5, (char[2]){warn.code[i], 0}, 0x81cdc6, base_bg, 0);
r++;
}
if (r >= 23)
break;
for (std::string &see_also : warn.see_also) {
uint32_t fg = 0xB55EFF;
uint8_t colon_count = 0;
for (uint32_t i = 0; i < see_also.length() && i + 5 < content_width;
i++) {
set(r + 1, i + 5, (char[2]){see_also[i], 0}, fg, base_bg, 0);
if (see_also[i] == ':')
colon_count++;
if (colon_count == 2)
fg = 0xFFFFFF;
}
r++;
if (r >= 23)
break;
};
idx++;
}
box_height = 2 + r;
set(0, 0, "", border_fg, base_bg, 0);
for (uint32_t i = 1; i < box_width - 1; i++)
set(0, i, "", border_fg, base_bg, 0);
set(0, box_width - 1, "", border_fg, base_bg, 0);
for (uint32_t r = 1; r < box_height - 1; r++) {
set(r, 0, "", border_fg, base_bg, 0);
set(r, box_width - 1, "", border_fg, base_bg, 0);
}
set(box_height - 1, 0, "", border_fg, base_bg, 0);
for (uint32_t i = 1; i < box_width - 1; i++)
set(box_height - 1, i, "", border_fg, base_bg, 0);
set(box_height - 1, box_width - 1, "", border_fg, base_bg, 0);
cells.resize(box_width * box_height);
}
void DiagnosticBox::render(Coord pos) {
int32_t start_row = (int32_t)pos.row - (int32_t)box_height;
if (start_row < 0)
start_row = pos.row + 1;
int32_t start_col = pos.col;
if (start_col + box_width > cols) {
start_col = cols - box_width;
if (start_col < 0)
start_col = 0;
}
for (uint32_t r = 0; r < box_height; r++)
for (uint32_t c = 0; c < box_width; c++)
update(start_row + r, start_col + c, cells[r * box_width + c].utf8,
cells[r * box_width + c].fg, cells[r * box_width + c].bg,
cells[r * box_width + c].flags);
}

220
src/boxes/hover.cc Normal file
View File

@@ -0,0 +1,220 @@
#include "boxes/hover.h"
#include "ts/ts.h"
void HoverBox::clear() {
text = "";
scroll_ = 0;
is_markup = false;
box_width = 0;
box_height = 0;
cells.clear();
highlights.clear();
hover_spans.clear();
}
void HoverBox::scroll(int32_t number) {
if (text.empty() || number == 0)
return;
uint32_t line_count = 0;
for (uint32_t i = 0; i < text.length(); i++)
if (text[i] == '\n')
line_count++;
scroll_ = MAX((int32_t)scroll_ + number, 0);
if (scroll_ > line_count)
scroll_ = line_count;
render_first(true);
}
void HoverBox::render_first(bool scroll) {
if (!scroll) {
std::vector<Span> base_spans;
std::vector<Span> injected_spans;
TSSetBase ts = TSSetBase{};
if (is_markup) {
highlights.reserve(1024);
base_spans.reserve(1024);
injected_spans.reserve(1024);
hover_spans.reserve(1024);
std::string query_path = get_exe_dir() + "/../grammar/hover.scm";
ts.language = LANG(markdown)();
ts.query = load_query(query_path.c_str(), &ts);
ts.parser = ts_parser_new();
ts_parser_set_language(ts.parser, ts.language);
ts.tree = ts_parser_parse_string(ts.parser, nullptr, text.c_str(),
text.length());
TSQueryCursor *cursor = ts_query_cursor_new();
ts_query_cursor_exec(cursor, ts.query, ts_tree_root_node(ts.tree));
TSQueryMatch match;
while (ts_query_cursor_next_match(cursor, &match)) {
auto subject_fn = [&](const TSNode *node) -> std::string {
uint32_t start = ts_node_start_byte(*node);
uint32_t end = ts_node_end_byte(*node);
return text.substr(start, end - start);
};
if (!ts_predicate(ts.query, match, subject_fn))
continue;
for (uint32_t i = 0; i < match.capture_count; i++) {
TSQueryCapture cap = match.captures[i];
uint32_t start = ts_node_start_byte(cap.node);
uint32_t end = ts_node_end_byte(cap.node);
if (Language *inj_lang = safe_get(ts.injection_map, cap.index)) {
TSSetBase inj_ts = TSSetBase{};
inj_ts.language = inj_lang->fn();
inj_ts.query_file =
get_exe_dir() + "/../grammar/" + inj_lang->name + ".scm";
inj_ts.query = load_query(inj_ts.query_file.c_str(), &inj_ts);
inj_ts.parser = ts_parser_new();
ts_parser_set_language(inj_ts.parser, inj_ts.language);
TSPoint start_p = ts_node_start_point(cap.node);
TSPoint end_p = ts_node_end_point(cap.node);
std::vector<TSRange> ranges = {{start_p, end_p, start, end}};
ts_parser_set_included_ranges(inj_ts.parser, ranges.data(), 1);
inj_ts.tree = ts_parser_parse_string(inj_ts.parser, nullptr,
text.c_str(), text.length());
TSQueryCursor *inj_cursor = ts_query_cursor_new();
ts_query_cursor_exec(inj_cursor, inj_ts.query,
ts_tree_root_node(inj_ts.tree));
TSQueryMatch inj_match;
while (ts_query_cursor_next_match(inj_cursor, &inj_match)) {
auto subject_fn = [&](const TSNode *node) -> std::string {
uint32_t start = ts_node_start_byte(*node);
uint32_t end = ts_node_end_byte(*node);
return text.substr(start, end - start);
};
if (!ts_predicate(inj_ts.query, inj_match, subject_fn))
continue;
for (uint32_t i = 0; i < inj_match.capture_count; i++) {
TSQueryCapture inj_cap = inj_match.captures[i];
uint32_t start = ts_node_start_byte(inj_cap.node);
uint32_t end = ts_node_end_byte(inj_cap.node);
if (Highlight *hl = safe_get(inj_ts.query_map, inj_cap.index)) {
highlights.push_back(*hl);
Highlight *hl_f = &highlights.back();
injected_spans.push_back({start, end, hl_f});
}
}
}
ts_query_cursor_delete(inj_cursor);
ts_tree_delete(inj_ts.tree);
ts_parser_delete(inj_ts.parser);
ts_query_delete(inj_ts.query);
continue;
}
if (Highlight *hl = safe_get(ts.query_map, cap.index)) {
highlights.push_back(*hl);
Highlight *hl_f = &highlights.back();
base_spans.push_back({start, end, hl_f});
}
}
}
ts_query_cursor_delete(cursor);
ts_query_delete(ts.query);
ts_tree_delete(ts.tree);
ts_parser_delete(ts.parser);
}
for (const auto &inj : injected_spans) {
base_spans.erase(std::remove_if(base_spans.begin(), base_spans.end(),
[&](const Span &base) {
return !(base.end <= inj.start ||
base.start >= inj.end);
}),
base_spans.end());
}
hover_spans.insert(hover_spans.end(), base_spans.begin(), base_spans.end());
hover_spans.insert(hover_spans.end(), injected_spans.begin(),
injected_spans.end());
std::sort(hover_spans.begin(), hover_spans.end());
}
uint32_t longest_line = 0;
uint32_t current_width = 0;
for (size_t j = 0; j < text.length(); j++) {
if (text[j] == '\n') {
longest_line = std::max(longest_line, current_width);
current_width = 0;
} else {
current_width += 1;
}
}
// HACK: the 1 is added so the longest line doesnt wrap which should be fixed
// in the loop instead as it was never meant to wrap in the first place
longest_line = MAX(longest_line, current_width) + 1;
uint32_t content_width = MIN(longest_line, 130u);
box_width = content_width + 2;
size_t i = 0;
size_t lines_skipped = 0;
while (i < text.length() && lines_skipped < scroll_) {
if (text[i] == '\n')
lines_skipped++;
i++;
}
Spans spans{};
spans.spans = hover_spans;
uint32_t border_fg = 0x82AAFF;
uint32_t base_bg = 0;
SpanCursor span_cursor(spans);
span_cursor.sync(i);
cells.assign(box_width * 26, ScreenCell{" ", 0, 0, 0, 0, 0});
auto set = [&](uint32_t r, uint32_t c, const char *text, uint32_t fg,
uint32_t bg, uint8_t flags) {
cells[r * box_width + c] = {std::string(text), 0, fg, bg, flags, 0};
};
uint32_t r = 0;
while (i < text.length() && r < 24) {
uint32_t c = 0;
while (c < content_width && i < text.length()) {
if (text[i] == '\n') {
while (i < text.length() && text[i] == '\n')
i++;
break;
}
uint32_t cluster_len = grapheme_next_character_break_utf8(
text.c_str() + i, text.length() - i);
std::string cluster = text.substr(i, cluster_len);
int width = display_width(cluster.c_str(), cluster_len);
if (c + width > content_width)
break;
Highlight *hl = span_cursor.get_highlight(i);
uint32_t fg = hl ? hl->fg : 0xFFFFFF;
uint32_t bg = hl ? hl->bg : 0;
uint32_t flags = hl ? hl->flags : 0;
set(r + 1, c + 1, cluster.c_str(), fg, bg | base_bg, flags);
c += width;
i += cluster_len;
for (int w = 1; w < width; w++)
set(r + 1, c - w + 1, "\x1b", 0xFFFFFF, base_bg, 0);
}
r++;
}
if (!scroll)
box_height = r + 2;
set(0, 0, "", border_fg, base_bg, 0);
for (uint32_t i = 1; i < box_width - 1; i++)
set(0, i, "", border_fg, base_bg, 0);
set(0, box_width - 1, "", border_fg, base_bg, 0);
for (uint32_t r = 1; r < box_height - 1; r++) {
set(r, 0, "", border_fg, base_bg, 0);
set(r, box_width - 1, "", border_fg, base_bg, 0);
}
set(box_height - 1, 0, "", border_fg, base_bg, 0);
for (uint32_t i = 1; i < box_width - 1; i++)
set(box_height - 1, i, "", border_fg, base_bg, 0);
set(box_height - 1, box_width - 1, "", border_fg, base_bg, 0);
cells.resize(box_width * box_height);
}
void HoverBox::render(Coord pos) {
int32_t start_row = (int32_t)pos.row - (int32_t)box_height;
if (start_row < 0)
start_row = pos.row + 1;
int32_t start_col = pos.col;
if (start_col + box_width > cols) {
start_col = cols - box_width;
if (start_col < 0)
start_col = 0;
}
for (uint32_t r = 0; r < box_height; r++)
for (uint32_t c = 0; c < box_width; c++)
update(start_row + r, start_col + c, cells[r * box_width + c].utf8,
cells[r * box_width + c].fg, cells[r * box_width + c].bg,
cells[r * box_width + c].flags);
}

View File

@@ -1,241 +1,5 @@
extern "C" { #include "editor/editor.h"
#include "../libs/libgrapheme/grapheme.h" #include "editor/folds.h"
}
#include "../include/editor.h"
#include "../include/utils.h"
#include <cmath>
void scroll_up(Editor *editor, int32_t number) {
if (!editor || number == 0)
return;
uint32_t numlen =
EXTRA_META + static_cast<int>(std::log10(editor->root->line_count + 1));
uint32_t render_width = editor->size.col - numlen;
uint32_t line_index = editor->scroll.row;
LineIterator *it = begin_l_iter(editor->root, line_index);
if (!it)
return;
uint32_t len;
char *line = next_line(it, &len);
if (!line) {
free(it->buffer);
free(it);
return;
}
if (len > 0 && line[len - 1] == '\n')
len--;
uint32_t current_byte_offset = 0;
uint32_t col = 0;
std::vector<uint32_t> segment_starts;
segment_starts.reserve(16);
if (current_byte_offset < editor->scroll.col)
segment_starts.push_back(0);
while (current_byte_offset < editor->scroll.col &&
current_byte_offset < len) {
uint32_t cluster_len = grapheme_next_character_break_utf8(
line + current_byte_offset, len - current_byte_offset);
int width = display_width(line + current_byte_offset, cluster_len);
if (col + width > render_width) {
segment_starts.push_back(current_byte_offset);
col = 0;
}
current_byte_offset += cluster_len;
col += width;
}
for (auto it_seg = segment_starts.rbegin(); it_seg != segment_starts.rend();
++it_seg) {
if (--number == 0) {
editor->scroll = {line_index, *it_seg};
free(it->buffer);
free(it);
return;
}
}
line = prev_line(it, &len);
if (!line) {
editor->scroll = {0, 0};
free(it->buffer);
free(it);
return;
}
do {
line_index--;
line = prev_line(it, &len);
if (!line) {
editor->scroll = {0, 0};
free(it->buffer);
free(it);
return;
}
const Fold *fold = fold_for_line(editor->folds, line_index);
if (fold) {
while (line && line_index > fold->start) {
free(line);
line = prev_line(it, &len);
line_index--;
if (!line) {
editor->scroll = {0, 0};
free(it->buffer);
free(it);
return;
}
}
if (--number == 0) {
editor->scroll = {fold->start, 0};
free(it->buffer);
free(it);
return;
}
if (fold->start == 0) {
editor->scroll = {0, 0};
free(it->buffer);
free(it);
return;
}
line_index = fold->start - 1;
line = prev_line(it, &len);
if (!line) {
editor->scroll = {0, 0};
free(it->buffer);
free(it);
return;
}
continue;
}
if (len > 0 && line[len - 1] == '\n')
len--;
current_byte_offset = 0;
col = 0;
std::vector<uint32_t> segment_starts;
segment_starts.reserve(16);
segment_starts.push_back(0);
while (current_byte_offset < len) {
uint32_t cluster_len = grapheme_next_character_break_utf8(
line + current_byte_offset, len - current_byte_offset);
int width = display_width(line + current_byte_offset, cluster_len);
if (col + width > render_width) {
segment_starts.push_back(current_byte_offset);
col = 0;
}
current_byte_offset += cluster_len;
col += width;
}
for (auto it_seg = segment_starts.rbegin(); it_seg != segment_starts.rend();
++it_seg) {
if (--number == 0) {
editor->scroll = {line_index, *it_seg};
free(it->buffer);
free(it);
return;
}
}
} while (number > 0);
free(it->buffer);
free(it);
}
void scroll_down(Editor *editor, uint32_t number) {
if (!editor || number == 0)
return;
uint32_t numlen =
EXTRA_META + static_cast<int>(std::log10(editor->root->line_count + 1));
uint32_t render_width = editor->size.col - numlen;
uint32_t line_index = editor->scroll.row;
LineIterator *it = begin_l_iter(editor->root, line_index);
if (!it)
return;
const uint32_t max_visual_lines = editor->size.row;
Coord *scroll_queue = (Coord *)malloc(sizeof(Coord) * max_visual_lines);
uint32_t q_head = 0;
uint32_t q_size = 0;
uint32_t visual_seen = 0;
bool first_visual_line = true;
while (true) {
const Fold *fold = fold_for_line(editor->folds, line_index);
if (fold) {
Coord fold_coord = {fold->start, 0};
if (q_size < max_visual_lines) {
scroll_queue[(q_head + q_size) % max_visual_lines] = fold_coord;
q_size++;
} else {
scroll_queue[q_head] = fold_coord;
q_head = (q_head + 1) % max_visual_lines;
}
visual_seen++;
if (visual_seen >= number + max_visual_lines) {
editor->scroll = scroll_queue[q_head];
break;
}
uint32_t skip_until = fold->end;
while (line_index <= skip_until) {
char *line = next_line(it, nullptr);
if (!line) {
free(scroll_queue);
free(it->buffer);
free(it);
return;
}
line_index++;
}
continue;
}
uint32_t line_len;
char *line = next_line(it, &line_len);
if (!line)
break;
if (line_len && line[line_len - 1] == '\n')
line_len--;
uint32_t current_byte_offset = 0;
if (first_visual_line) {
current_byte_offset += editor->scroll.col;
first_visual_line = false;
}
while (current_byte_offset < line_len ||
(line_len == 0 && current_byte_offset == 0)) {
Coord coord = {line_index, current_byte_offset};
if (q_size < max_visual_lines) {
scroll_queue[(q_head + q_size) % max_visual_lines] = coord;
q_size++;
} else {
scroll_queue[q_head] = coord;
q_head = (q_head + 1) % max_visual_lines;
}
visual_seen++;
if (visual_seen >= number + max_visual_lines) {
editor->scroll = scroll_queue[q_head];
free(scroll_queue);
free(it->buffer);
free(it);
return;
}
uint32_t col = 0;
uint32_t local_render_offset = 0;
uint32_t left = line_len - current_byte_offset;
while (left > 0 && col < render_width) {
uint32_t cluster_len = grapheme_next_character_break_utf8(
line + current_byte_offset + local_render_offset, left);
int width = display_width(
line + current_byte_offset + local_render_offset, cluster_len);
if (col + width > render_width)
break;
local_render_offset += cluster_len;
left -= cluster_len;
col += width;
}
current_byte_offset += local_render_offset;
if (line_len == 0)
break;
}
line_index++;
}
if (q_size > 0) {
uint32_t advance = (q_size > number) ? number : (q_size - 1);
editor->scroll = scroll_queue[(q_head + advance) % max_visual_lines];
}
free(it->buffer);
free(it);
free(scroll_queue);
}
void ensure_cursor(Editor *editor) { void ensure_cursor(Editor *editor) {
std::shared_lock knot_lock(editor->knot_mtx); std::shared_lock knot_lock(editor->knot_mtx);

115
src/editor/boundaries.cc Normal file
View File

@@ -0,0 +1,115 @@
#include "editor/editor.h"
uint32_t scan_left(const char *line, uint32_t len, uint32_t off) {
if (off > len)
off = len;
uint32_t i = off;
while (i > 0) {
unsigned char c = (unsigned char)line[i - 1];
if ((c & 0x80) != 0)
break;
if (!((c == '_') || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z')))
break;
--i;
}
return i;
}
uint32_t scan_right(const char *line, uint32_t len, uint32_t off) {
if (off > len)
off = len;
uint32_t i = off;
while (i < len) {
unsigned char c = (unsigned char)line[i];
if ((c & 0x80) != 0)
break;
if (!((c == '_') || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z')))
break;
++i;
}
return i;
}
void word_boundaries_exclusive(Editor *editor, Coord coord, uint32_t *prev_col,
uint32_t *next_col) {
if (!editor)
return;
std::shared_lock lock(editor->knot_mtx);
LineIterator *it = begin_l_iter(editor->root, coord.row);
if (!it)
return;
uint32_t line_len;
char *line = next_line(it, &line_len);
if (!line)
return;
if (line_len && line[line_len - 1] == '\n')
line_len--;
uint32_t col = coord.col;
if (col > line_len)
col = line_len;
uint32_t left = scan_left(line, line_len, col);
uint32_t right = scan_right(line, line_len, col);
if (prev_col)
*prev_col = left;
if (next_col)
*next_col = right;
free(it->buffer);
free(it);
}
uint32_t word_jump_right(const char *line, size_t len, uint32_t pos) {
if (pos >= len)
return len;
size_t next = grapheme_next_word_break_utf8(line + pos, len - pos);
return static_cast<uint32_t>(pos + next);
}
uint32_t word_jump_left(const char *line, size_t len, uint32_t col) {
if (col == 0)
return 0;
size_t pos = 0;
size_t last = 0;
size_t cursor = col;
while (pos < len) {
size_t next = pos + grapheme_next_word_break_utf8(line + pos, len - pos);
if (next >= cursor)
break;
last = next;
pos = next;
}
return static_cast<uint32_t>(last);
}
void word_boundaries(Editor *editor, Coord coord, uint32_t *prev_col,
uint32_t *next_col, uint32_t *prev_clusters,
uint32_t *next_clusters) {
if (!editor)
return;
std::shared_lock lock(editor->knot_mtx);
LineIterator *it = begin_l_iter(editor->root, coord.row);
if (!it)
return;
uint32_t line_len;
char *line = next_line(it, &line_len);
if (!line)
return;
if (line_len && line[line_len - 1] == '\n')
line_len--;
size_t col = coord.col;
if (col > line_len)
col = line_len;
size_t left = word_jump_left(line, line_len, col);
size_t right = word_jump_right(line, line_len, col);
if (prev_col)
*prev_col = static_cast<uint32_t>(left);
if (next_col)
*next_col = static_cast<uint32_t>(right);
if (prev_clusters)
*prev_clusters = count_clusters(line, line_len, left, col);
if (next_clusters)
*next_clusters = count_clusters(line, line_len, col, right);
free(it->buffer);
free(it);
}

97
src/editor/click.cc Normal file
View File

@@ -0,0 +1,97 @@
#include "editor/editor.h"
#include "editor/folds.h"
#include "main.h"
Coord editor_hit_test(Editor *editor, uint32_t x, uint32_t y) {
if (mode == INSERT)
x++;
uint32_t numlen =
EXTRA_META + static_cast<int>(std::log10(editor->root->line_count + 1));
bool is_gutter_click = (x < numlen);
uint32_t render_width = editor->size.col - numlen;
x = MAX(x, numlen) - numlen;
uint32_t target_visual_row = y;
uint32_t visual_row = 0;
uint32_t line_index = editor->scroll.row;
uint32_t last_line_index = editor->scroll.row;
uint32_t last_col = editor->scroll.col;
bool first_visual_line = true;
std::shared_lock knot_lock(editor->knot_mtx);
LineIterator *it = begin_l_iter(editor->root, line_index);
if (!it)
return editor->scroll;
while (visual_row <= target_visual_row) {
const Fold *fold = fold_for_line(editor->folds, line_index);
if (fold) {
if (visual_row == target_visual_row) {
free(it->buffer);
free(it);
if (is_gutter_click) {
remove_fold(editor, fold->start);
return {UINT32_MAX, UINT32_MAX};
}
return {fold->start > 0 ? fold->start - 1 : 0, 0};
}
visual_row++;
while (line_index <= fold->end) {
char *l = next_line(it, nullptr);
if (!l)
break;
line_index++;
}
last_line_index = fold->end;
last_col = 0;
continue;
}
uint32_t line_len;
char *line = next_line(it, &line_len);
if (!line)
break;
if (line_len && line[line_len - 1] == '\n')
line_len--;
last_line_index = line_index;
last_col = line_len;
uint32_t offset = first_visual_line ? editor->scroll.col : 0;
first_visual_line = false;
while (offset < line_len || (line_len == 0 && offset == 0)) {
uint32_t col = 0;
uint32_t advance = 0;
uint32_t left = line_len - offset;
uint32_t last_good_offset = offset;
while (left > 0 && col < render_width) {
uint32_t g =
grapheme_next_character_break_utf8(line + offset + advance, left);
int w = display_width(line + offset + advance, g);
if (col + w > render_width)
break;
if (visual_row == target_visual_row && x < col + w) {
free(it->buffer);
free(it);
return {line_index, offset + advance};
}
advance += g;
last_good_offset = offset + advance;
left -= g;
col += w;
}
last_col = last_good_offset;
if (visual_row == target_visual_row) {
free(it->buffer);
free(it);
return {line_index, last_good_offset};
}
visual_row++;
if (visual_row > target_visual_row)
break;
if (advance == 0)
break;
offset += advance;
if (line_len == 0)
break;
}
line_index++;
}
free(it->buffer);
free(it);
return {last_line_index, last_col};
}

View File

@@ -1,8 +1,6 @@
extern "C" { #include "editor/editor.h"
#include "../libs/libgrapheme/grapheme.h" #include "editor/folds.h"
} #include "utils/utils.h"
#include "../include/editor.h"
#include "../include/utils.h"
Coord move_right_pure(Editor *editor, Coord cursor, uint32_t number) { Coord move_right_pure(Editor *editor, Coord cursor, uint32_t number) {
Coord result = cursor; Coord result = cursor;

280
src/editor/edit.cc Normal file
View File

@@ -0,0 +1,280 @@
#include "editor/editor.h"
#include "editor/folds.h"
#include "lsp/lsp.h"
void edit_erase(Editor *editor, Coord pos, int64_t len) {
if (len == 0)
return;
if (len < 0) {
std::shared_lock lock_1(editor->knot_mtx);
uint32_t cursor_original =
line_to_byte(editor->root, editor->cursor.row, nullptr) +
editor->cursor.col;
TSPoint old_point = {pos.row, pos.col};
uint32_t byte_pos = line_to_byte(editor->root, pos.row, nullptr) + pos.col;
Coord point = move_left_pure(editor, pos, -len);
json lsp_range;
bool do_lsp = (editor->lsp != nullptr);
if (do_lsp) {
LineIterator *it = begin_l_iter(editor->root, point.row);
char *line = next_line(it, nullptr);
int utf16_start = 0;
if (line)
utf16_start = utf8_byte_offset_to_utf16(line, point.col);
free(it->buffer);
free(it);
it = begin_l_iter(editor->root, pos.row);
line = next_line(it, nullptr);
int utf16_end = 0;
if (line)
utf16_end = utf8_byte_offset_to_utf16(line, pos.col);
free(it->buffer);
free(it);
lsp_range = {{"start", {{"line", point.row}, {"character", utf16_start}}},
{"end", {{"line", pos.row}, {"character", utf16_end}}}};
}
uint32_t start = line_to_byte(editor->root, point.row, nullptr) + point.col;
if (cursor_original > start && cursor_original <= byte_pos) {
editor->cursor = point;
editor->cursor_preffered = UINT32_MAX;
} else if (cursor_original > byte_pos) {
uint32_t cursor_new = cursor_original - (byte_pos - start);
uint32_t new_col;
uint32_t new_row = byte_to_line(editor->root, cursor_new, &new_col);
editor->cursor = {new_row, new_col};
editor->cursor_preffered = UINT32_MAX;
}
lock_1.unlock();
uint32_t start_row = point.row;
uint32_t end_row = pos.row;
apply_line_deletion(editor, start_row + 1, end_row);
apply_hook_deletion(editor, start_row + 1, end_row);
std::unique_lock lock_2(editor->knot_mtx);
editor->root = erase(editor->root, start, byte_pos - start);
if (editor->ts.tree) {
TSInputEdit edit = {
.start_byte = start,
.old_end_byte = byte_pos,
.new_end_byte = start,
.start_point = {point.row, point.col},
.old_end_point = old_point,
.new_end_point = {point.row, point.col},
};
editor->edit_queue.push(edit);
}
std::unique_lock lock_3(editor->spans.mtx);
apply_edit(editor->spans.spans, start, start - byte_pos);
if (editor->spans.mid_parse)
editor->spans.edits.push({start, start - byte_pos});
lock_3.unlock();
lock_2.unlock();
std::unique_lock lock_4(editor->hex_color_spans.mtx);
apply_edit(editor->hex_color_spans.spans, byte_pos, start - byte_pos);
lock_4.unlock();
if (do_lsp) {
if (editor->lsp->incremental_sync) {
json message = {
{"jsonrpc", "2.0"},
{"method", "textDocument/didChange"},
{"params",
{{"textDocument",
{{"uri", editor->uri}, {"version", ++editor->lsp_version}}},
{"contentChanges",
json::array({{{"range", lsp_range}, {"text", ""}}})}}}};
lsp_send(editor->lsp, message, nullptr);
} else {
char *buf = read(editor->root, 0, editor->root->char_count);
std::string text(buf);
free(buf);
json message = {
{"jsonrpc", "2.0"},
{"method", "textDocument/didChange"},
{"params",
{{"textDocument",
{{"uri", editor->uri}, {"version", ++editor->lsp_version}}},
{"contentChanges", json::array({{{"text", text}}})}}}};
lsp_send(editor->lsp, message, nullptr);
}
}
} else {
std::shared_lock lock_1(editor->knot_mtx);
uint32_t cursor_original =
line_to_byte(editor->root, editor->cursor.row, nullptr) +
editor->cursor.col;
TSPoint old_point = {pos.row, pos.col};
uint32_t byte_pos = line_to_byte(editor->root, pos.row, nullptr) + pos.col;
Coord point = move_right_pure(editor, pos, len);
json lsp_range;
bool do_lsp = (editor->lsp != nullptr);
if (do_lsp) {
LineIterator *it = begin_l_iter(editor->root, pos.row);
char *line = next_line(it, nullptr);
int utf16_start = 0;
if (line)
utf16_start = utf8_byte_offset_to_utf16(line, pos.col);
free(it->buffer);
free(it);
it = begin_l_iter(editor->root, point.row);
line = next_line(it, nullptr);
int utf16_end = 0;
if (line)
utf16_end = utf8_byte_offset_to_utf16(line, point.col);
free(it->buffer);
free(it);
lsp_range = {{"start", {{"line", pos.row}, {"character", utf16_start}}},
{"end", {{"line", point.row}, {"character", utf16_end}}}};
}
uint32_t end = line_to_byte(editor->root, point.row, nullptr) + point.col;
if (cursor_original > byte_pos && cursor_original <= end) {
editor->cursor = pos;
editor->cursor_preffered = UINT32_MAX;
} else if (cursor_original > end) {
uint32_t cursor_new = cursor_original - (end - byte_pos);
uint32_t new_col;
uint32_t new_row = byte_to_line(editor->root, cursor_new, &new_col);
editor->cursor = {new_row, new_col};
editor->cursor_preffered = UINT32_MAX;
}
lock_1.unlock();
uint32_t start_row = pos.row;
uint32_t end_row = point.row;
apply_line_deletion(editor, start_row + 1, end_row);
apply_hook_deletion(editor, start_row + 1, end_row);
std::unique_lock lock_2(editor->knot_mtx);
editor->root = erase(editor->root, byte_pos, end - byte_pos);
if (editor->ts.tree) {
TSInputEdit edit = {
.start_byte = byte_pos,
.old_end_byte = end,
.new_end_byte = byte_pos,
.start_point = old_point,
.old_end_point = {point.row, point.col},
.new_end_point = old_point,
};
editor->edit_queue.push(edit);
}
std::unique_lock lock_3(editor->spans.mtx);
apply_edit(editor->spans.spans, byte_pos, byte_pos - end);
if (editor->spans.mid_parse)
editor->spans.edits.push({byte_pos, byte_pos - end});
lock_3.unlock();
lock_2.unlock();
std::unique_lock lock_4(editor->hex_color_spans.mtx);
apply_edit(editor->hex_color_spans.spans, byte_pos, byte_pos - end);
lock_4.unlock();
if (do_lsp) {
if (editor->lsp->incremental_sync) {
json message = {
{"jsonrpc", "2.0"},
{"method", "textDocument/didChange"},
{"params",
{{"textDocument",
{{"uri", editor->uri}, {"version", ++editor->lsp_version}}},
{"contentChanges",
json::array({{{"range", lsp_range}, {"text", ""}}})}}}};
lsp_send(editor->lsp, message, nullptr);
} else {
char *buf = read(editor->root, 0, editor->root->char_count);
std::string text(buf);
free(buf);
json message = {
{"jsonrpc", "2.0"},
{"method", "textDocument/didChange"},
{"params",
{{"textDocument",
{{"uri", editor->uri}, {"version", ++editor->lsp_version}}},
{"contentChanges", json::array({{{"text", text}}})}}}};
lsp_send(editor->lsp, message, nullptr);
}
}
}
}
void edit_insert(Editor *editor, Coord pos, char *data, uint32_t len) {
std::shared_lock lock_1(editor->knot_mtx);
uint32_t cursor_original =
line_to_byte(editor->root, editor->cursor.row, nullptr) +
editor->cursor.col;
uint32_t byte_pos = line_to_byte(editor->root, pos.row, nullptr) + pos.col;
TSPoint start_point = {pos.row, pos.col};
if (cursor_original > byte_pos) {
uint32_t cursor_new = cursor_original + len;
uint32_t new_col;
uint32_t new_row = byte_to_line(editor->root, cursor_new, &new_col);
editor->cursor = {new_row, new_col};
}
lock_1.unlock();
std::unique_lock lock_2(editor->knot_mtx);
editor->root = insert(editor->root, byte_pos, data, len);
uint32_t cols = 0;
uint32_t rows = 0;
for (uint32_t i = 0; i < len; i++) {
if (data[i] == '\n') {
rows++;
cols = 0;
} else {
cols++;
}
}
apply_line_insertion(editor, pos.row, rows);
apply_hook_insertion(editor, pos.row, rows);
if (editor->ts.tree) {
TSInputEdit edit = {
.start_byte = byte_pos,
.old_end_byte = byte_pos,
.new_end_byte = byte_pos + len,
.start_point = start_point,
.old_end_point = start_point,
.new_end_point = {start_point.row + rows,
(rows == 0) ? (start_point.column + cols) : cols},
};
editor->edit_queue.push(edit);
}
std::unique_lock lock_3(editor->spans.mtx);
apply_edit(editor->spans.spans, byte_pos, len);
if (editor->spans.mid_parse)
editor->spans.edits.push({byte_pos, len});
lock_3.unlock();
lock_2.unlock();
std::unique_lock lock_4(editor->hex_color_spans.mtx);
apply_edit(editor->hex_color_spans.spans, byte_pos, len);
lock_4.unlock();
if (editor->lsp) {
if (editor->lsp->incremental_sync) {
lock_1.lock();
LineIterator *it = begin_l_iter(editor->root, pos.row);
char *line = next_line(it, nullptr);
int utf16_col = 0;
if (line)
utf16_col = utf8_byte_offset_to_utf16(line, pos.col);
free(it->buffer);
free(it);
lock_1.unlock();
json message = {
{"jsonrpc", "2.0"},
{"method", "textDocument/didChange"},
{"params",
{{"textDocument",
{{"uri", editor->uri}, {"version", ++editor->lsp_version}}},
{"contentChanges",
json::array(
{{{"range",
{{"start", {{"line", pos.row}, {"character", utf16_col}}},
{"end", {{"line", pos.row}, {"character", utf16_col}}}}},
{"text", std::string(data, len)}}})}}}};
lsp_send(editor->lsp, message, nullptr);
} else {
char *buf = read(editor->root, 0, editor->root->char_count);
std::string text(buf);
free(buf);
json message = {
{"jsonrpc", "2.0"},
{"method", "textDocument/didChange"},
{"params",
{{"textDocument",
{{"uri", editor->uri}, {"version", ++editor->lsp_version}}},
{"contentChanges", json::array({{{"text", text}}})}}}};
lsp_send(editor->lsp, message, nullptr);
}
}
}

80
src/editor/editor.cc Normal file
View File

@@ -0,0 +1,80 @@
#include "editor/editor.h"
#include "lsp/lsp.h"
#include "utils/utils.h"
Editor *new_editor(const char *filename_arg, Coord position, Coord size) {
Editor *editor = new Editor();
if (!editor)
return nullptr;
uint32_t len = 0;
std::string filename = path_abs(filename_arg);
char *str = load_file(filename.c_str(), &len);
if (!str) {
free_editor(editor);
return nullptr;
}
editor->filename = filename;
editor->uri = path_to_file_uri(filename);
editor->position = position;
editor->size = size;
editor->cursor_preffered = UINT32_MAX;
if (len == 0) {
free(str);
str = (char *)malloc(1);
*str = '\n';
len = 1;
}
editor->root = load(str, len, optimal_chunk_size(len));
free(str);
Language language = language_for_file(filename.c_str());
if (language.name != "unknown" && len <= (1024 * 128)) {
editor->ts.parser = ts_parser_new();
editor->ts.language = language.fn();
ts_parser_set_language(editor->ts.parser, editor->ts.language);
editor->ts.query_file =
get_exe_dir() + "/../grammar/" + language.name + ".scm";
}
if (len <= (1024 * 28))
request_add_to_lsp(language, editor);
return editor;
}
void free_tsset(TSSetMain *set) {
if (set->parser)
ts_parser_delete(set->parser);
if (set->tree)
ts_tree_delete(set->tree);
if (set->query)
ts_query_delete(set->query);
for (auto &inj : set->injections) {
if (inj.second.parser)
ts_parser_delete(inj.second.parser);
if (inj.second.query)
ts_query_delete(inj.second.query);
if (inj.second.tree)
ts_tree_delete(inj.second.tree);
}
}
void free_editor(Editor *editor) {
remove_from_lsp(editor);
free_tsset(&editor->ts);
free_rope(editor->root);
delete editor;
}
void save_file(Editor *editor) {
if (!editor || !editor->root)
return;
char *str = read(editor->root, 0, editor->root->char_count);
if (!str)
return;
std::ofstream out(editor->filename);
out.write(str, editor->root->char_count);
free(str);
json msg = {{"jsonrpc", "2.0"},
{"method", "textDocument/didSave"},
{"params", {{"textDocument", {{"uri", editor->uri}}}}}};
if (editor->lsp)
lsp_send(editor->lsp, msg, nullptr);
}

View File

@@ -1,14 +1,16 @@
#include "../include/editor.h" #include "editor/editor.h"
#include "../include/main.h" #include "editor/folds.h"
#include "../include/ts.h" #include "lsp/lsp.h"
#include <cstdint> #include "main.h"
#include <sys/ioctl.h>
void handle_editor_event(Editor *editor, KeyEvent event) { void handle_editor_event(Editor *editor, KeyEvent event) {
static std::chrono::steady_clock::time_point last_click_time = static std::chrono::steady_clock::time_point last_click_time =
std::chrono::steady_clock::now(); std::chrono::steady_clock::now();
static uint32_t click_count = 0; static uint32_t click_count = 0;
static Coord last_click_pos = {UINT32_MAX, UINT32_MAX}; static Coord last_click_pos = {UINT32_MAX, UINT32_MAX};
Coord start = editor->cursor;
if (editor->hover_active)
editor->hover_active = false;
if (event.key_type == KEY_MOUSE) { if (event.key_type == KEY_MOUSE) {
auto now = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>( auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
@@ -205,7 +207,6 @@ void handle_editor_event(Editor *editor, KeyEvent event) {
switch (mode) { switch (mode) {
case NORMAL: case NORMAL:
if (event.key_type == KEY_CHAR && event.len == 1) { if (event.key_type == KEY_CHAR && event.len == 1) {
Coord start = editor->cursor;
switch (event.c[0]) { switch (event.c[0]) {
case 'u': case 'u':
if (editor->root->line_count > 0) { if (editor->root->line_count > 0) {
@@ -230,6 +231,71 @@ void handle_editor_event(Editor *editor, KeyEvent event) {
editor->selection_type = LINE; editor->selection_type = LINE;
} }
break; break;
case CTRL('h'):
editor->hover.scroll(-1);
editor->hover_active = true;
break;
case CTRL('l'):
editor->hover.scroll(1);
editor->hover_active = true;
break;
case 'h':
if (editor->lsp && editor->lsp->allow_hover) {
LineIterator *it = begin_l_iter(editor->root, editor->cursor.row);
char *line = next_line(it, nullptr);
if (!line) {
free(it->buffer);
free(it);
break;
}
uint32_t col = utf8_byte_offset_to_utf16(line, editor->cursor.col);
free(it->buffer);
free(it);
json hover_request = {
{"jsonrpc", "2.0"},
{"method", "textDocument/hover"},
{"params",
{{"textDocument", {{"uri", editor->uri}}},
{"position",
{{"line", editor->cursor.row}, {"character", col}}}}}};
LSPPending *pending = new LSPPending();
pending->editor = editor;
pending->method = "textDocument/hover";
pending->callback = [](Editor *editor, std::string, json hover) {
if (hover.contains("result") && !hover["result"].is_null()) {
auto &contents = hover["result"]["contents"];
std::string hover_text = "";
bool is_markup = false;
if (contents.is_object()) {
hover_text += contents["value"].get<std::string>();
is_markup = (contents["kind"].get<std::string>() == "markdown");
} else if (contents.is_array()) {
for (auto &block : contents) {
if (block.is_string()) {
hover_text += block.get<std::string>() + "\n";
} else if (block.is_object() && block.contains("language") &&
block.contains("value")) {
std::string lang = block["language"].get<std::string>();
std::string val = block["value"].get<std::string>();
is_markup = true;
hover_text += "```" + lang + "\n" + val + "\n```\n";
}
}
} else if (contents.is_string()) {
hover_text += contents.get<std::string>();
}
if (!hover_text.empty()) {
editor->hover.clear();
editor->hover.text = clean_text(hover_text);
editor->hover.is_markup = is_markup;
editor->hover.render_first();
editor->hover_active = true;
}
}
};
lsp_send(editor->lsp, hover_request, pending);
}
break;
case 'a': case 'a':
mode = INSERT; mode = INSERT;
cursor_right(editor, 1); cursor_right(editor, 1);
@@ -298,6 +364,45 @@ void handle_editor_event(Editor *editor, KeyEvent event) {
case CTRL('s'): case CTRL('s'):
save_file(editor); save_file(editor);
break; break;
case CTRL(' '):
if (editor->lsp) {
json msg = {
{"jsonrpc", "2.0"},
{"method", "textDocument/completion"},
{
"params",
{
{
"textDocument",
{
{"uri", editor->uri},
},
},
{
"position",
{
{"line", editor->cursor.row},
{"character", editor->cursor.col},
},
},
{
"context",
{
{"triggerKind", 1},
},
},
},
},
};
LSPPending *pending = new LSPPending();
pending->editor = editor;
pending->method = "textDocument/completion";
pending->callback = [](Editor *editor, std::string, json completion) {
log("%s\n", completion.dump().c_str());
};
lsp_send(editor->lsp, msg, pending);
}
break;
case 'p': case 'p':
uint32_t len; uint32_t len;
char *text = get_from_clipboard(&len); char *text = get_from_clipboard(&len);
@@ -558,65 +663,3 @@ void handle_editor_event(Editor *editor, KeyEvent event) {
if ((event.key_type == KEY_CHAR || event.key_type == KEY_PASTE) && event.c) if ((event.key_type == KEY_CHAR || event.key_type == KEY_PASTE) && event.c)
free(event.c); free(event.c);
} }
static Highlight HL_UNDERLINE = {0, 0, 1 << 2, 100};
void editor_worker(Editor *editor) {
if (!editor || !editor->root)
return;
if (editor->root->char_count > (1024 * 200))
return;
if (editor->ts.query_file != "" && !editor->ts.query)
editor->ts.query = load_query(editor->ts.query_file.c_str(), &editor->ts);
if (editor->ts.parser && editor->ts.query)
ts_collect_spans(editor);
uint32_t prev_col, next_col;
word_boundaries_exclusive(editor, editor->cursor, &prev_col, &next_col);
if (next_col - prev_col > 0 && next_col - prev_col < 256 - 4) {
std::shared_lock lock(editor->knot_mtx);
uint32_t offset = line_to_byte(editor->root, editor->cursor.row, nullptr);
char *word = read(editor->root, offset + prev_col, next_col - prev_col);
if (word) {
char buf[256];
snprintf(buf, sizeof(buf), "\\b%s\\b", word);
std::vector<std::pair<size_t, size_t>> results =
search_rope(editor->root, buf);
std::unique_lock lock(editor->def_spans.mtx);
editor->def_spans.spans.clear();
for (const auto &match : results) {
Span s;
s.start = match.first;
s.end = match.first + match.second;
s.hl = &HL_UNDERLINE;
editor->def_spans.spans.push_back(s);
}
std::sort(editor->def_spans.spans.begin(), editor->def_spans.spans.end());
lock.unlock();
free(word);
}
} else {
std::unique_lock lock(editor->def_spans.mtx);
editor->def_spans.spans.clear();
lock.unlock();
}
}
void editor_lsp_handle(Editor *editor, json msg) {
if (msg.contains("method") &&
msg["method"] == "textDocument/publishDiagnostics") {
std::unique_lock lock(editor->v_mtx);
editor->warnings.clear();
json diagnostics = msg["params"]["diagnostics"];
for (size_t i = 0; i < diagnostics.size(); i++) {
json d = diagnostics[i];
VWarn w;
w.line = d["range"]["start"]["line"];
std::string text = d["message"].get<std::string>();
auto pos = text.find('\n');
w.text = (pos == std::string::npos) ? text : text.substr(0, pos);
w.type = d["severity"].get<int>();
editor->warnings.push_back(w);
}
std::sort(editor->warnings.begin(), editor->warnings.end());
}
}

View File

@@ -1,4 +1,4 @@
#include "../include/editor.h" #include "editor/editor.h"
uint32_t leading_indent(const char *line, uint32_t len) { uint32_t leading_indent(const char *line, uint32_t len) {
uint32_t indent = 0; uint32_t indent = 0;

63
src/editor/lsp.cc Normal file
View File

@@ -0,0 +1,63 @@
#include "editor/editor.h"
void editor_lsp_handle(Editor *editor, json msg) {
if (msg.contains("method") &&
msg["method"] == "textDocument/publishDiagnostics") {
std::unique_lock lock(editor->v_mtx);
editor->warnings.clear();
json diagnostics = msg["params"]["diagnostics"];
for (size_t i = 0; i < diagnostics.size(); i++) {
json d = diagnostics[i];
VWarn w;
// HACK: convert back to utf-8 but as this is only visually affecting it
// is not worth getting the line string from the rope.
w.line = d["range"]["start"]["line"];
w.start = d["range"]["start"]["character"];
uint32_t end = d["range"]["end"]["character"];
if (d["range"]["end"]["line"] == w.line)
w.end = end;
std::string text = trim(d["message"].get<std::string>());
w.text_full = text;
auto pos = text.find('\n');
w.text = (pos == std::string::npos) ? text : text.substr(0, pos);
if (d.contains("source"))
w.source = d["source"].get<std::string>();
if (d.contains("code")) {
w.code = "[";
if (d["code"].is_string())
w.code += d["code"].get<std::string>() + "] ";
else if (d["code"].is_number())
w.code += std::to_string(d["code"].get<int>()) + "] ";
else
w.code.clear();
if (d.contains("codeDescription") &&
d["codeDescription"].contains("href"))
w.code += d["codeDescription"]["href"].get<std::string>();
}
if (d.contains("relatedInformation")) {
json related = d["relatedInformation"];
for (size_t j = 0; j < related.size(); j++) {
json rel = related[j];
std::string message = rel["message"].get<std::string>();
auto pos = message.find('\n');
message =
(pos == std::string::npos) ? message : message.substr(0, pos);
std::string uri =
percent_decode(rel["location"]["uri"].get<std::string>());
auto pos2 = uri.find_last_of('/');
if (pos2 != std::string::npos)
uri = uri.substr(pos2 + 1);
std::string row = std::to_string(
rel["location"]["range"]["start"]["line"].get<int>());
w.see_also.push_back(uri + ":" + row + ": " + message);
}
}
w.type = 1;
if (d.contains("severity"))
w.type = d["severity"].get<int>();
editor->warnings.push_back(w);
}
std::sort(editor->warnings.begin(), editor->warnings.end());
editor->warnings_dirty = true;
}
}

121
src/editor/move_line.cc Normal file
View File

@@ -0,0 +1,121 @@
#include "editor/editor.h"
#include "editor/folds.h"
#include "main.h"
void move_line_up(Editor *editor) {
if (!editor || !editor->root || editor->cursor.row == 0)
return;
if (mode == NORMAL || mode == INSERT) {
uint32_t line_len, line_cluster_len;
std::shared_lock lock(editor->knot_mtx);
LineIterator *it = begin_l_iter(editor->root, editor->cursor.row);
char *line = next_line(it, &line_len);
if (!line) {
lock.unlock();
return;
}
if (line_len > 0 && line[line_len - 1] == '\n')
line_len--;
line_cluster_len = count_clusters(line, line_len, 0, line_len);
uint32_t target_row = prev_unfolded_row(editor, editor->cursor.row - 1);
uint32_t up_by = editor->cursor.row - target_row;
if (up_by > 1)
up_by--;
lock.unlock();
Coord cursor = editor->cursor;
edit_erase(editor, {cursor.row, 0}, line_cluster_len);
edit_erase(editor, {cursor.row, 0}, -1);
edit_insert(editor, {cursor.row - up_by, 0}, (char *)"\n", 1);
edit_insert(editor, {cursor.row - up_by, 0}, line, line_len);
free(it->buffer);
free(it);
editor->cursor = {cursor.row - up_by, cursor.col};
} else if (mode == SELECT) {
uint32_t start_row = MIN(editor->cursor.row, editor->selection.row);
uint32_t end_row = MAX(editor->cursor.row, editor->selection.row);
uint32_t start_byte = line_to_byte(editor->root, start_row, nullptr);
uint32_t end_byte = line_to_byte(editor->root, end_row + 1, nullptr);
char *selected_text = read(editor->root, start_byte, end_byte - start_byte);
if (!selected_text)
return;
uint32_t selected_len = count_clusters(selected_text, end_byte - start_byte,
0, end_byte - start_byte);
Coord cursor = editor->cursor;
Coord selection = editor->selection;
edit_erase(editor, {start_row, 0}, selected_len);
edit_insert(editor, {start_row - 1, 0}, selected_text,
end_byte - start_byte);
free(selected_text);
editor->cursor = {cursor.row - 1, cursor.col};
editor->selection = {selection.row - 1, selection.col};
}
}
void move_line_down(Editor *editor) {
if (!editor || !editor->root)
return;
if (mode == NORMAL || mode == INSERT) {
if (editor->cursor.row >= editor->root->line_count - 1)
return;
uint32_t line_len, line_cluster_len;
std::shared_lock lock(editor->knot_mtx);
LineIterator *it = begin_l_iter(editor->root, editor->cursor.row);
char *line = next_line(it, &line_len);
if (!line) {
lock.unlock();
return;
}
if (line_len && line[line_len - 1] == '\n')
line_len--;
line_cluster_len = count_clusters(line, line_len, 0, line_len);
uint32_t target_row = next_unfolded_row(editor, editor->cursor.row + 1);
if (target_row >= editor->root->line_count) {
free(line);
lock.unlock();
return;
}
uint32_t down_by = target_row - editor->cursor.row;
if (down_by > 1)
down_by--;
uint32_t ln;
line_to_byte(editor->root, editor->cursor.row + down_by - 1, &ln);
lock.unlock();
Coord cursor = editor->cursor;
edit_erase(editor, {cursor.row, 0}, line_cluster_len);
edit_erase(editor, {cursor.row, 0}, -1);
edit_insert(editor, {cursor.row + down_by, 0}, (char *)"\n", 1);
edit_insert(editor, {cursor.row + down_by, 0}, line, line_len);
free(it->buffer);
free(it);
editor->cursor = {cursor.row + down_by, cursor.col};
} else if (mode == SELECT) {
if (editor->cursor.row >= editor->root->line_count - 1 ||
editor->selection.row >= editor->root->line_count - 1)
return;
std::shared_lock lock(editor->knot_mtx);
uint32_t start_row = MIN(editor->cursor.row, editor->selection.row);
uint32_t end_row = MAX(editor->cursor.row, editor->selection.row);
uint32_t target_row = next_unfolded_row(editor, end_row + 1);
if (target_row >= editor->root->line_count)
return;
uint32_t down_by = target_row - end_row;
if (down_by > 1)
down_by--;
uint32_t start_byte = line_to_byte(editor->root, start_row, nullptr);
uint32_t end_byte = line_to_byte(editor->root, end_row + 1, nullptr);
char *selected_text = read(editor->root, start_byte, end_byte - start_byte);
lock.unlock();
if (!selected_text)
return;
uint32_t selected_len = count_clusters(selected_text, end_byte - start_byte,
0, end_byte - start_byte);
Coord cursor = editor->cursor;
Coord selection = editor->selection;
edit_erase(editor, {start_row, 0}, selected_len);
edit_insert(editor, {start_row + down_by, 0}, selected_text,
end_byte - start_byte);
free(selected_text);
editor->cursor = {cursor.row + down_by, cursor.col};
editor->selection = {selection.row + down_by, selection.col};
}
}

View File

@@ -1,73 +1,7 @@
extern "C" { #include "editor/editor.h"
#include "../libs/libgrapheme/grapheme.h" #include "editor/folds.h"
} #include "main.h"
#include "../include/editor.h" #include "ts/decl.h"
#include "../include/lsp.h"
#include "../include/main.h"
#include "../include/utils.h"
Editor *new_editor(const char *filename_arg, Coord position, Coord size) {
Editor *editor = new Editor();
if (!editor)
return nullptr;
uint32_t len = 0;
std::string filename = path_abs(filename_arg);
char *str = load_file(filename.c_str(), &len);
if (!str) {
free_editor(editor);
return nullptr;
}
editor->filename = filename;
editor->uri = path_to_file_uri(filename);
editor->position = position;
editor->size = size;
editor->cursor_preffered = UINT32_MAX;
editor->root = load(str, len, optimal_chunk_size(len));
free(str);
Language language = language_for_file(filename.c_str());
if (language.name != "unknown" && len <= (1024 * 128)) {
editor->ts.parser = ts_parser_new();
editor->ts.language = language.fn();
ts_parser_set_language(editor->ts.parser, editor->ts.language);
editor->ts.query_file =
get_exe_dir() + "/../grammar/" + language.name + ".scm";
request_add_to_lsp(language, editor);
}
return editor;
}
void free_tsset(TSSetMain *set) {
if (set->parser)
ts_parser_delete(set->parser);
if (set->tree)
ts_tree_delete(set->tree);
if (set->query)
ts_query_delete(set->query);
for (auto &inj : set->injections) {
if (inj.second.parser)
ts_parser_delete(inj.second.parser);
if (inj.second.query)
ts_query_delete(inj.second.query);
}
}
void free_editor(Editor *editor) {
remove_from_lsp(editor);
free_tsset(&editor->ts);
free_rope(editor->root);
delete editor;
}
void save_file(Editor *editor) {
if (!editor || !editor->root)
return;
char *str = read(editor->root, 0, editor->root->char_count);
if (!str)
return;
std::ofstream out(editor->filename);
out.write(str, editor->root->char_count);
free(str);
}
void render_editor(Editor *editor) { void render_editor(Editor *editor) {
uint32_t sel_start = 0, sel_end = 0; uint32_t sel_start = 0, sel_end = 0;
@@ -83,6 +17,7 @@ void render_editor(Editor *editor) {
auto hook_it = v.begin(); auto hook_it = v.begin();
while (hook_it != v.end() && hook_it->first <= editor->scroll.row) while (hook_it != v.end() && hook_it->first <= editor->scroll.row)
++hook_it; ++hook_it;
std::unique_lock warn_lock(editor->v_mtx);
auto warn_it = editor->warnings.begin(); auto warn_it = editor->warnings.begin();
while (warn_it != editor->warnings.end() && while (warn_it != editor->warnings.end() &&
warn_it->line < editor->scroll.row) warn_it->line < editor->scroll.row)
@@ -139,15 +74,16 @@ void render_editor(Editor *editor) {
Coord cursor = {UINT32_MAX, UINT32_MAX}; Coord cursor = {UINT32_MAX, UINT32_MAX};
uint32_t line_index = editor->scroll.row; uint32_t line_index = editor->scroll.row;
SpanCursor span_cursor(editor->spans); SpanCursor span_cursor(editor->spans);
SpanCursor def_span_cursor(editor->def_spans); SpanCursor word_span_cursor(editor->word_spans);
SpanCursor hex_span_cursor(editor->hex_color_spans);
LineIterator *it = begin_l_iter(editor->root, line_index); LineIterator *it = begin_l_iter(editor->root, line_index);
if (!it) if (!it)
return; return;
uint32_t rendered_rows = 0; uint32_t rendered_rows = 0;
uint32_t global_byte_offset = line_to_byte(editor->root, line_index, nullptr); uint32_t global_byte_offset = line_to_byte(editor->root, line_index, nullptr);
span_cursor.sync(global_byte_offset); span_cursor.sync(global_byte_offset);
def_span_cursor.sync(global_byte_offset); word_span_cursor.sync(global_byte_offset);
std::shared_lock v_lock(editor->v_mtx); hex_span_cursor.sync(global_byte_offset);
while (rendered_rows < editor->size.row) { while (rendered_rows < editor->size.row) {
const Fold *fold = fold_for_line(editor->folds, line_index); const Fold *fold = fold_for_line(editor->folds, line_index);
if (fold) { if (fold) {
@@ -193,6 +129,14 @@ void render_editor(Editor *editor) {
break; break;
if (line_len > 0 && line[line_len - 1] == '\n') if (line_len > 0 && line[line_len - 1] == '\n')
line_len--; line_len--;
uint32_t content_end = line_len;
while (content_end > 0 &&
(line[content_end - 1] == ' ' || line[content_end - 1] == '\t'))
content_end--;
uint32_t content_start = 0;
while (content_start < line_len &&
(line[content_start] == ' ' || line[content_start] == '\t'))
content_start++;
std::vector<VWarn> line_warnings; std::vector<VWarn> line_warnings;
while (warn_it != editor->warnings.end() && warn_it->line == line_index) { while (warn_it != editor->warnings.end() && warn_it->line == line_index) {
line_warnings.push_back(*warn_it); line_warnings.push_back(*warn_it);
@@ -239,20 +183,51 @@ void render_editor(Editor *editor) {
uint32_t absolute_byte_pos = uint32_t absolute_byte_pos =
global_byte_offset + current_byte_offset + local_render_offset; global_byte_offset + current_byte_offset + local_render_offset;
Highlight *hl = span_cursor.get_highlight(absolute_byte_pos); Highlight *hl = span_cursor.get_highlight(absolute_byte_pos);
Highlight *def_hl = def_span_cursor.get_highlight(absolute_byte_pos); Highlight *word_hl = word_span_cursor.get_highlight(absolute_byte_pos);
Highlight *hex_hl = hex_span_cursor.get_highlight(absolute_byte_pos);
uint32_t fg = hl ? hl->fg : 0xFFFFFF; uint32_t fg = hl ? hl->fg : 0xFFFFFF;
uint32_t bg = hl ? hl->bg : 0; uint32_t bg = hl ? hl->bg : 0;
uint8_t fl = hl ? hl->flags : 0; uint8_t fl = hl ? hl->flags : 0;
if (def_hl) { if (hex_hl) {
if (def_hl->fg != 0) if (hex_hl->fg != 0)
fg = def_hl->fg; fg = hex_hl->fg;
if (def_hl->bg != 0) if (hex_hl->bg != 0)
bg = def_hl->bg; bg = hex_hl->bg;
fl |= def_hl->flags; fl |= hex_hl->flags;
} else if (word_hl) {
if (word_hl->fg != 0)
fg |= word_hl->fg;
if (word_hl->bg != 0)
bg |= word_hl->bg;
fl |= word_hl->flags;
} }
if (editor->selection_active && absolute_byte_pos >= sel_start && if (editor->selection_active && absolute_byte_pos >= sel_start &&
absolute_byte_pos < sel_end) absolute_byte_pos < sel_end)
bg = 0x555555; bg = 0x555555;
uint32_t u_color = 0;
for (const auto &w : line_warnings) {
if (w.start <= current_byte_offset + local_render_offset &&
current_byte_offset + local_render_offset < w.end) {
switch (w.type) {
case 1:
u_color = 0xff0000;
fl |= CF_UNDERLINE;
break;
case 2:
u_color = 0xffff00;
fl |= CF_UNDERLINE;
break;
case 3:
u_color = 0xff00ff;
fl |= CF_UNDERLINE;
break;
case 4:
u_color = 0xA0A0A0;
fl |= CF_UNDERLINE;
break;
}
}
}
uint32_t cluster_len = grapheme_next_character_break_utf8( uint32_t cluster_len = grapheme_next_character_break_utf8(
line + current_byte_offset + local_render_offset, line_left); line + current_byte_offset + local_render_offset, line_left);
std::string cluster(line + current_byte_offset + local_render_offset, std::string cluster(line + current_byte_offset + local_render_offset,
@@ -260,8 +235,19 @@ void render_editor(Editor *editor) {
int width = display_width(cluster.c_str(), cluster_len); int width = display_width(cluster.c_str(), cluster_len);
if (col + width > render_width) if (col + width > render_width)
break; break;
if (current_byte_offset + local_render_offset >= content_start &&
current_byte_offset + local_render_offset < content_end) {
update(editor->position.row + rendered_rows, render_x + col, update(editor->position.row + rendered_rows, render_x + col,
cluster.c_str(), fg, bg | color, fl); cluster.c_str(), fg, bg | color, fl, u_color);
} else {
if (cluster[0] == ' ') {
update(editor->position.row + rendered_rows, render_x + col, "·",
0x282828, bg | color, fl, u_color);
} else {
update(editor->position.row + rendered_rows, render_x + col, "-> ",
0x282828, bg | color, (fl & ~CF_BOLD) | CF_ITALIC, u_color);
}
}
local_render_offset += cluster_len; local_render_offset += cluster_len;
line_left -= cluster_len; line_left -= cluster_len;
col += width; col += width;
@@ -351,7 +337,11 @@ void render_editor(Editor *editor) {
cluster.c_str(), fg_color, color, 0); cluster.c_str(), fg_color, color, 0);
col += width; col += width;
warn_idx += cluster_len; warn_idx += cluster_len;
while (width-- > 1)
update(editor->position.row + rendered_rows, render_x + col - width,
"\x1b", fg_color, color, 0);
} }
line_warnings.clear();
} }
while (col < render_width) { while (col < render_width) {
update(editor->position.row + rendered_rows, render_x + col, " ", 0, update(editor->position.row + rendered_rows, render_x + col, " ", 0,
@@ -393,6 +383,81 @@ void render_editor(Editor *editor) {
0x555555 | color, 0); 0x555555 | color, 0);
col++; col++;
} }
if (!line_warnings.empty()) {
VWarn warn = line_warnings.front();
update(editor->position.row + rendered_rows, render_x + col, " ", 0,
color, 0);
col++;
for (size_t i = 0; i < line_warnings.size(); i++) {
if (line_warnings[i].type < warn.type)
warn = line_warnings[i];
std::string err_sym = " ";
uint32_t fg_color = 0;
switch (line_warnings[i].type) {
case 1:
err_sym = "";
fg_color = 0xFF0000;
goto final2;
case 2:
err_sym = "";
fg_color = 0xFFFF00;
goto final2;
case 3:
err_sym = "";
fg_color = 0xFF00FF;
goto final2;
case 4:
err_sym = "";
fg_color = 0xAAAAAA;
goto final2;
final2:
if (col < render_width) {
update(editor->position.row + rendered_rows, render_x + col,
err_sym, fg_color, color, 0);
col++;
update(editor->position.row + rendered_rows, render_x + col, " ",
fg_color, color, 0);
col++;
}
}
}
if (col < render_width) {
update(editor->position.row + rendered_rows, render_x + col, " ", 0,
0 | color, 0);
col++;
}
size_t warn_idx = 0;
uint32_t fg_color = 0;
switch (warn.type) {
case 1:
fg_color = 0xFF0000;
break;
case 2:
fg_color = 0xFFFF00;
break;
case 3:
fg_color = 0xFF00FF;
break;
case 4:
fg_color = 0xAAAAAA;
break;
}
while (col < render_width && warn_idx < warn.text.length()) {
uint32_t cluster_len = grapheme_next_character_break_utf8(
warn.text.c_str() + warn_idx, warn.text.length() - warn_idx);
std::string cluster = warn.text.substr(warn_idx, cluster_len);
int width = display_width(cluster.c_str(), cluster_len);
if (col + width > render_width)
break;
update(editor->position.row + rendered_rows, render_x + col,
cluster.c_str(), fg_color, color, 0);
col += width;
warn_idx += cluster_len;
while (width-- > 1)
update(editor->position.row + rendered_rows, render_x + col - width,
"\x1b", fg_color, color, 0);
}
}
while (col < render_width) { while (col < render_width) {
update(editor->position.row + rendered_rows, render_x + col, " ", 0, update(editor->position.row + rendered_rows, render_x + col, " ", 0,
0 | color, 0); 0 | color, 0);
@@ -418,6 +483,10 @@ void render_editor(Editor *editor) {
break; break;
} }
set_cursor(cursor.row, cursor.col, type, true); set_cursor(cursor.row, cursor.col, type, true);
if (editor->hover_active)
editor->hover.render(cursor);
else if (editor->diagnostics_active)
editor->diagnostics.render(cursor);
} }
while (rendered_rows < editor->size.row) { while (rendered_rows < editor->size.row) {
for (uint32_t col = 0; col < editor->size.col; col++) for (uint32_t col = 0; col < editor->size.col; col++)

234
src/editor/scroll.cc Normal file
View File

@@ -0,0 +1,234 @@
#include "editor/editor.h"
#include "editor/folds.h"
void scroll_up(Editor *editor, int32_t number) {
if (!editor || number == 0)
return;
uint32_t numlen =
EXTRA_META + static_cast<int>(std::log10(editor->root->line_count + 1));
uint32_t render_width = editor->size.col - numlen;
uint32_t line_index = editor->scroll.row;
LineIterator *it = begin_l_iter(editor->root, line_index);
if (!it)
return;
uint32_t len;
char *line = next_line(it, &len);
if (!line) {
free(it->buffer);
free(it);
return;
}
if (len > 0 && line[len - 1] == '\n')
len--;
uint32_t current_byte_offset = 0;
uint32_t col = 0;
std::vector<uint32_t> segment_starts;
segment_starts.reserve(16);
if (current_byte_offset < editor->scroll.col)
segment_starts.push_back(0);
while (current_byte_offset < editor->scroll.col &&
current_byte_offset < len) {
uint32_t cluster_len = grapheme_next_character_break_utf8(
line + current_byte_offset, len - current_byte_offset);
int width = display_width(line + current_byte_offset, cluster_len);
if (col + width > render_width) {
segment_starts.push_back(current_byte_offset);
col = 0;
}
current_byte_offset += cluster_len;
col += width;
}
for (auto it_seg = segment_starts.rbegin(); it_seg != segment_starts.rend();
++it_seg) {
if (--number == 0) {
editor->scroll = {line_index, *it_seg};
free(it->buffer);
free(it);
return;
}
}
line = prev_line(it, &len);
if (!line) {
editor->scroll = {0, 0};
free(it->buffer);
free(it);
return;
}
do {
line_index--;
line = prev_line(it, &len);
if (!line) {
editor->scroll = {0, 0};
free(it->buffer);
free(it);
return;
}
const Fold *fold = fold_for_line(editor->folds, line_index);
if (fold) {
while (line && line_index > fold->start) {
free(line);
line = prev_line(it, &len);
line_index--;
if (!line) {
editor->scroll = {0, 0};
free(it->buffer);
free(it);
return;
}
}
if (--number == 0) {
editor->scroll = {fold->start, 0};
free(it->buffer);
free(it);
return;
}
if (fold->start == 0) {
editor->scroll = {0, 0};
free(it->buffer);
free(it);
return;
}
line_index = fold->start - 1;
line = prev_line(it, &len);
if (!line) {
editor->scroll = {0, 0};
free(it->buffer);
free(it);
return;
}
continue;
}
if (len > 0 && line[len - 1] == '\n')
len--;
current_byte_offset = 0;
col = 0;
std::vector<uint32_t> segment_starts;
segment_starts.reserve(16);
segment_starts.push_back(0);
while (current_byte_offset < len) {
uint32_t cluster_len = grapheme_next_character_break_utf8(
line + current_byte_offset, len - current_byte_offset);
int width = display_width(line + current_byte_offset, cluster_len);
if (col + width > render_width) {
segment_starts.push_back(current_byte_offset);
col = 0;
}
current_byte_offset += cluster_len;
col += width;
}
for (auto it_seg = segment_starts.rbegin(); it_seg != segment_starts.rend();
++it_seg) {
if (--number == 0) {
editor->scroll = {line_index, *it_seg};
free(it->buffer);
free(it);
return;
}
}
} while (number > 0);
free(it->buffer);
free(it);
}
void scroll_down(Editor *editor, uint32_t number) {
if (!editor || number == 0)
return;
uint32_t numlen =
EXTRA_META + static_cast<int>(std::log10(editor->root->line_count + 1));
uint32_t render_width = editor->size.col - numlen;
uint32_t line_index = editor->scroll.row;
LineIterator *it = begin_l_iter(editor->root, line_index);
if (!it)
return;
const uint32_t max_visual_lines = editor->size.row;
Coord *scroll_queue = (Coord *)malloc(sizeof(Coord) * max_visual_lines);
uint32_t q_head = 0;
uint32_t q_size = 0;
uint32_t visual_seen = 0;
bool first_visual_line = true;
while (true) {
const Fold *fold = fold_for_line(editor->folds, line_index);
if (fold) {
Coord fold_coord = {fold->start, 0};
if (q_size < max_visual_lines) {
scroll_queue[(q_head + q_size) % max_visual_lines] = fold_coord;
q_size++;
} else {
scroll_queue[q_head] = fold_coord;
q_head = (q_head + 1) % max_visual_lines;
}
visual_seen++;
if (visual_seen >= number + max_visual_lines) {
editor->scroll = scroll_queue[q_head];
break;
}
uint32_t skip_until = fold->end;
while (line_index <= skip_until) {
char *line = next_line(it, nullptr);
if (!line) {
free(scroll_queue);
free(it->buffer);
free(it);
return;
}
line_index++;
}
continue;
}
uint32_t line_len;
char *line = next_line(it, &line_len);
if (!line)
break;
if (line_len && line[line_len - 1] == '\n')
line_len--;
uint32_t current_byte_offset = 0;
if (first_visual_line) {
current_byte_offset += editor->scroll.col;
first_visual_line = false;
}
while (current_byte_offset < line_len ||
(line_len == 0 && current_byte_offset == 0)) {
Coord coord = {line_index, current_byte_offset};
if (q_size < max_visual_lines) {
scroll_queue[(q_head + q_size) % max_visual_lines] = coord;
q_size++;
} else {
scroll_queue[q_head] = coord;
q_head = (q_head + 1) % max_visual_lines;
}
visual_seen++;
if (visual_seen >= number + max_visual_lines) {
editor->scroll = scroll_queue[q_head];
free(scroll_queue);
free(it->buffer);
free(it);
return;
}
uint32_t col = 0;
uint32_t local_render_offset = 0;
uint32_t left = line_len - current_byte_offset;
while (left > 0 && col < render_width) {
uint32_t cluster_len = grapheme_next_character_break_utf8(
line + current_byte_offset + local_render_offset, left);
int width = display_width(
line + current_byte_offset + local_render_offset, cluster_len);
if (col + width > render_width)
break;
local_render_offset += cluster_len;
left -= cluster_len;
col += width;
}
current_byte_offset += local_render_offset;
if (line_len == 0)
break;
}
line_index++;
}
if (q_size > 0) {
uint32_t advance = (q_size > number) ? number : (q_size - 1);
editor->scroll = scroll_queue[(q_head + advance) % max_visual_lines];
}
free(it->buffer);
free(it);
free(scroll_queue);
}

58
src/editor/selection.cc Normal file
View File

@@ -0,0 +1,58 @@
#include "editor/editor.h"
char *get_selection(Editor *editor, uint32_t *out_len, Coord *out_start) {
std::shared_lock lock(editor->knot_mtx);
Coord start, end;
if (editor->cursor >= editor->selection) {
uint32_t prev_col, next_col;
switch (editor->selection_type) {
case CHAR:
start = editor->selection;
end = move_right(editor, editor->cursor, 1);
break;
case WORD:
word_boundaries(editor, editor->selection, &prev_col, &next_col, nullptr,
nullptr);
start = {editor->selection.row, prev_col};
end = editor->cursor;
break;
case LINE:
start = {editor->selection.row, 0};
end = editor->cursor;
break;
}
} else {
start = editor->cursor;
uint32_t prev_col, next_col, line_len;
switch (editor->selection_type) {
case CHAR:
end = move_right(editor, editor->selection, 1);
break;
case WORD:
word_boundaries(editor, editor->selection, &prev_col, &next_col, nullptr,
nullptr);
end = {editor->selection.row, next_col};
break;
case LINE:
LineIterator *it = begin_l_iter(editor->root, editor->selection.row);
char *line = next_line(it, &line_len);
if (!line)
return nullptr;
if (line_len > 0 && line[line_len - 1] == '\n')
line_len--;
end = {editor->selection.row, line_len};
free(it->buffer);
free(it);
break;
}
}
if (out_start)
*out_start = start;
uint32_t start_byte =
line_to_byte(editor->root, start.row, nullptr) + start.col;
uint32_t end_byte = line_to_byte(editor->root, end.row, nullptr) + end.col;
char *text = read(editor->root, start_byte, end_byte - start_byte);
if (out_len)
*out_len = end_byte - start_byte;
return text;
}

106
src/editor/worker.cc Normal file
View File

@@ -0,0 +1,106 @@
#include "editor/editor.h"
#include "ts/ts.h"
static Highlight HL_UNDERLINE = {0, 0, CF_UNDERLINE, UINT8_MAX - 1};
void hover_diagnostic(Editor *editor) {
std::shared_lock lock(editor->v_mtx);
static uint32_t last_line = UINT32_MAX;
if (last_line == editor->cursor.row && !editor->warnings_dirty)
return;
VWarn dummy;
dummy.line = editor->cursor.row;
editor->warnings_dirty = false;
last_line = editor->cursor.row;
auto first =
std::lower_bound(editor->warnings.begin(), editor->warnings.end(), dummy);
auto last =
std::upper_bound(editor->warnings.begin(), editor->warnings.end(), dummy);
std::vector<VWarn> warnings_at_line(first, last);
if (warnings_at_line.size() == 0) {
editor->diagnostics_active = false;
return;
}
editor->diagnostics.clear();
editor->diagnostics.warnings.swap(warnings_at_line);
editor->diagnostics.render_first();
editor->diagnostics_active = true;
}
void editor_worker(Editor *editor) {
if (!editor || !editor->root)
return;
if (editor->root->char_count > (1024 * 128))
return;
if (editor->ts.query_file != "" && !editor->ts.query)
editor->ts.query = load_query(editor->ts.query_file.c_str(), &editor->ts);
if (editor->ts.parser && editor->ts.query)
ts_collect_spans(editor);
if (editor->root->char_count > (1024 * 32))
return;
uint32_t prev_col, next_col;
word_boundaries_exclusive(editor, editor->cursor, &prev_col, &next_col);
std::unique_lock lock(editor->word_spans.mtx);
editor->word_spans.spans.clear();
lock.unlock();
if (next_col - prev_col > 0 && next_col - prev_col < 256 - 4) {
std::shared_lock lockk(editor->knot_mtx);
uint32_t offset = line_to_byte(editor->root, editor->cursor.row, nullptr);
char *word = read(editor->root, offset + prev_col, next_col - prev_col);
lockk.unlock();
if (word) {
char buf[256];
snprintf(buf, sizeof(buf), "\\b%s\\b", word);
std::shared_lock lockk(editor->knot_mtx);
std::vector<std::pair<size_t, size_t>> results =
search_rope_dfa(editor->root, buf);
lockk.unlock();
std::unique_lock lock2(editor->word_spans.mtx);
editor->word_spans.spans.reserve(results.size());
for (const auto &match : results) {
Span s;
s.start = match.first;
s.end = match.first + match.second;
s.hl = &HL_UNDERLINE;
editor->word_spans.spans.push_back(s);
}
free(word);
lock2.unlock();
}
}
static uint16_t limit = 150;
static Highlight *hl_s = (Highlight *)calloc(limit, sizeof(Highlight));
if (!hl_s)
exit(ENOMEM);
std::shared_lock lockk(editor->knot_mtx);
std::vector<Match> results =
search_rope(editor->root, "(?:0x|#)[0-9a-fA-F]{6}");
if (results.size() > limit) {
limit = results.size() + 50;
free(hl_s);
hl_s = (Highlight *)calloc(limit, sizeof(Highlight));
if (!hl_s)
exit(ENOMEM);
}
lockk.unlock();
std::unique_lock lock2(editor->hex_color_spans.mtx);
editor->hex_color_spans.spans.clear();
editor->hex_color_spans.spans.reserve(results.size());
for (size_t i = 0; i < results.size(); ++i) {
Span s;
s.start = results[i].start;
s.end = results[i].end;
int x = results[i].text[0] == '#' ? 1 : 2;
uint32_t bg = HEX(results[i].text.substr(x));
uint8_t r = bg >> 16;
uint8_t g = (bg >> 8) & 0xFF;
uint8_t b = bg & 0xFF;
double luminance = 0.299 * r + 0.587 * g + 0.114 * b;
uint32_t fg = (luminance > 128) ? 0x010101 : 0xFEFEFE;
hl_s[i] = {fg, bg, CF_BOLD, UINT8_MAX};
s.hl = &hl_s[i];
editor->hex_color_spans.spans.push_back(s);
}
lock2.unlock();
hover_diagnostic(editor);
}

View File

@@ -1,745 +0,0 @@
extern "C" {
#include "../libs/libgrapheme/grapheme.h"
}
#include "../include/editor.h"
#include "../include/lsp.h"
#include "../include/main.h"
#include "../include/utils.h"
uint32_t scan_left(const char *line, uint32_t len, uint32_t off) {
if (off > len)
off = len;
uint32_t i = off;
while (i > 0) {
unsigned char c = (unsigned char)line[i - 1];
if ((c & 0x80) != 0)
break;
if (!((c == '_') || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z')))
break;
--i;
}
return i;
}
uint32_t scan_right(const char *line, uint32_t len, uint32_t off) {
if (off > len)
off = len;
uint32_t i = off;
while (i < len) {
unsigned char c = (unsigned char)line[i];
if ((c & 0x80) != 0)
break;
if (!((c == '_') || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z')))
break;
++i;
}
return i;
}
void word_boundaries_exclusive(Editor *editor, Coord coord, uint32_t *prev_col,
uint32_t *next_col) {
if (!editor)
return;
std::shared_lock lock(editor->knot_mtx);
LineIterator *it = begin_l_iter(editor->root, coord.row);
if (!it)
return;
uint32_t line_len;
char *line = next_line(it, &line_len);
if (!line)
return;
if (line_len && line[line_len - 1] == '\n')
line_len--;
uint32_t col = coord.col;
if (col > line_len)
col = line_len;
uint32_t left = scan_left(line, line_len, col);
uint32_t right = scan_right(line, line_len, col);
if (prev_col)
*prev_col = left;
if (next_col)
*next_col = right;
free(it->buffer);
free(it);
}
uint32_t word_jump_right(const char *line, size_t len, uint32_t pos) {
if (pos >= len)
return len;
size_t next = grapheme_next_word_break_utf8(line + pos, len - pos);
return static_cast<uint32_t>(pos + next);
}
uint32_t word_jump_left(const char *line, size_t len, uint32_t col) {
if (col == 0)
return 0;
size_t pos = 0;
size_t last = 0;
size_t cursor = col;
while (pos < len) {
size_t next = pos + grapheme_next_word_break_utf8(line + pos, len - pos);
if (next >= cursor)
break;
last = next;
pos = next;
}
return static_cast<uint32_t>(last);
}
void word_boundaries(Editor *editor, Coord coord, uint32_t *prev_col,
uint32_t *next_col, uint32_t *prev_clusters,
uint32_t *next_clusters) {
if (!editor)
return;
std::shared_lock lock(editor->knot_mtx);
LineIterator *it = begin_l_iter(editor->root, coord.row);
if (!it)
return;
uint32_t line_len;
char *line = next_line(it, &line_len);
if (!line)
return;
if (line_len && line[line_len - 1] == '\n')
line_len--;
size_t col = coord.col;
if (col > line_len)
col = line_len;
size_t left = word_jump_left(line, line_len, col);
size_t right = word_jump_right(line, line_len, col);
if (prev_col)
*prev_col = static_cast<uint32_t>(left);
if (next_col)
*next_col = static_cast<uint32_t>(right);
if (prev_clusters)
*prev_clusters = count_clusters(line, line_len, left, col);
if (next_clusters)
*next_clusters = count_clusters(line, line_len, col, right);
free(it->buffer);
free(it);
}
Coord editor_hit_test(Editor *editor, uint32_t x, uint32_t y) {
if (mode == INSERT)
x++;
uint32_t numlen =
EXTRA_META + static_cast<int>(std::log10(editor->root->line_count + 1));
bool is_gutter_click = (x < numlen);
uint32_t render_width = editor->size.col - numlen;
x = MAX(x, numlen) - numlen;
uint32_t target_visual_row = y;
uint32_t visual_row = 0;
uint32_t line_index = editor->scroll.row;
uint32_t last_line_index = editor->scroll.row;
uint32_t last_col = editor->scroll.col;
bool first_visual_line = true;
std::shared_lock knot_lock(editor->knot_mtx);
LineIterator *it = begin_l_iter(editor->root, line_index);
if (!it)
return editor->scroll;
while (visual_row <= target_visual_row) {
const Fold *fold = fold_for_line(editor->folds, line_index);
if (fold) {
if (visual_row == target_visual_row) {
free(it->buffer);
free(it);
if (is_gutter_click) {
remove_fold(editor, fold->start);
return {UINT32_MAX, UINT32_MAX};
}
return {fold->start > 0 ? fold->start - 1 : 0, 0};
}
visual_row++;
while (line_index <= fold->end) {
char *l = next_line(it, nullptr);
if (!l)
break;
line_index++;
}
last_line_index = fold->end;
last_col = 0;
continue;
}
uint32_t line_len;
char *line = next_line(it, &line_len);
if (!line)
break;
if (line_len && line[line_len - 1] == '\n')
line_len--;
last_line_index = line_index;
last_col = line_len;
uint32_t offset = first_visual_line ? editor->scroll.col : 0;
first_visual_line = false;
while (offset < line_len || (line_len == 0 && offset == 0)) {
uint32_t col = 0;
uint32_t advance = 0;
uint32_t left = line_len - offset;
uint32_t last_good_offset = offset;
while (left > 0 && col < render_width) {
uint32_t g =
grapheme_next_character_break_utf8(line + offset + advance, left);
int w = display_width(line + offset + advance, g);
if (col + w > render_width)
break;
if (visual_row == target_visual_row && x < col + w) {
free(it->buffer);
free(it);
return {line_index, offset + advance};
}
advance += g;
last_good_offset = offset + advance;
left -= g;
col += w;
}
last_col = last_good_offset;
if (visual_row == target_visual_row) {
free(it->buffer);
free(it);
return {line_index, last_good_offset};
}
visual_row++;
if (visual_row > target_visual_row)
break;
if (advance == 0)
break;
offset += advance;
if (line_len == 0)
break;
}
line_index++;
}
free(it->buffer);
free(it);
return {last_line_index, last_col};
}
void move_line_up(Editor *editor) {
if (!editor || !editor->root || editor->cursor.row == 0)
return;
if (mode == NORMAL || mode == INSERT) {
uint32_t line_len, line_cluster_len;
std::shared_lock lock(editor->knot_mtx);
LineIterator *it = begin_l_iter(editor->root, editor->cursor.row);
char *line = next_line(it, &line_len);
if (!line) {
lock.unlock();
return;
}
if (line_len > 0 && line[line_len - 1] == '\n')
line_len--;
line_cluster_len = count_clusters(line, line_len, 0, line_len);
uint32_t target_row = prev_unfolded_row(editor, editor->cursor.row - 1);
uint32_t up_by = editor->cursor.row - target_row;
if (up_by > 1)
up_by--;
lock.unlock();
Coord cursor = editor->cursor;
edit_erase(editor, {cursor.row, 0}, line_cluster_len);
edit_erase(editor, {cursor.row, 0}, -1);
edit_insert(editor, {cursor.row - up_by, 0}, (char *)"\n", 1);
edit_insert(editor, {cursor.row - up_by, 0}, line, line_len);
free(it->buffer);
free(it);
editor->cursor = {cursor.row - up_by, cursor.col};
} else if (mode == SELECT) {
uint32_t start_row = MIN(editor->cursor.row, editor->selection.row);
uint32_t end_row = MAX(editor->cursor.row, editor->selection.row);
uint32_t start_byte = line_to_byte(editor->root, start_row, nullptr);
uint32_t end_byte = line_to_byte(editor->root, end_row + 1, nullptr);
char *selected_text = read(editor->root, start_byte, end_byte - start_byte);
if (!selected_text)
return;
uint32_t selected_len = count_clusters(selected_text, end_byte - start_byte,
0, end_byte - start_byte);
Coord cursor = editor->cursor;
Coord selection = editor->selection;
edit_erase(editor, {start_row, 0}, selected_len);
edit_insert(editor, {start_row - 1, 0}, selected_text,
end_byte - start_byte);
free(selected_text);
editor->cursor = {cursor.row - 1, cursor.col};
editor->selection = {selection.row - 1, selection.col};
}
}
void move_line_down(Editor *editor) {
if (!editor || !editor->root)
return;
if (mode == NORMAL || mode == INSERT) {
if (editor->cursor.row >= editor->root->line_count - 1)
return;
uint32_t line_len, line_cluster_len;
std::shared_lock lock(editor->knot_mtx);
LineIterator *it = begin_l_iter(editor->root, editor->cursor.row);
char *line = next_line(it, &line_len);
if (!line) {
lock.unlock();
return;
}
if (line_len && line[line_len - 1] == '\n')
line_len--;
line_cluster_len = count_clusters(line, line_len, 0, line_len);
uint32_t target_row = next_unfolded_row(editor, editor->cursor.row + 1);
if (target_row >= editor->root->line_count) {
free(line);
lock.unlock();
return;
}
uint32_t down_by = target_row - editor->cursor.row;
if (down_by > 1)
down_by--;
uint32_t ln;
line_to_byte(editor->root, editor->cursor.row + down_by - 1, &ln);
lock.unlock();
Coord cursor = editor->cursor;
edit_erase(editor, {cursor.row, 0}, line_cluster_len);
edit_erase(editor, {cursor.row, 0}, -1);
edit_insert(editor, {cursor.row + down_by, 0}, (char *)"\n", 1);
edit_insert(editor, {cursor.row + down_by, 0}, line, line_len);
free(it->buffer);
free(it);
editor->cursor = {cursor.row + down_by, cursor.col};
} else if (mode == SELECT) {
if (editor->cursor.row >= editor->root->line_count - 1 ||
editor->selection.row >= editor->root->line_count - 1)
return;
std::shared_lock lock(editor->knot_mtx);
uint32_t start_row = MIN(editor->cursor.row, editor->selection.row);
uint32_t end_row = MAX(editor->cursor.row, editor->selection.row);
uint32_t target_row = next_unfolded_row(editor, end_row + 1);
if (target_row >= editor->root->line_count)
return;
uint32_t down_by = target_row - end_row;
if (down_by > 1)
down_by--;
uint32_t start_byte = line_to_byte(editor->root, start_row, nullptr);
uint32_t end_byte = line_to_byte(editor->root, end_row + 1, nullptr);
char *selected_text = read(editor->root, start_byte, end_byte - start_byte);
lock.unlock();
if (!selected_text)
return;
uint32_t selected_len = count_clusters(selected_text, end_byte - start_byte,
0, end_byte - start_byte);
Coord cursor = editor->cursor;
Coord selection = editor->selection;
edit_erase(editor, {start_row, 0}, selected_len);
edit_insert(editor, {start_row + down_by, 0}, selected_text,
end_byte - start_byte);
free(selected_text);
editor->cursor = {cursor.row + down_by, cursor.col};
editor->selection = {selection.row + down_by, selection.col};
}
}
void edit_erase(Editor *editor, Coord pos, int64_t len) {
if (len == 0)
return;
if (len < 0) {
std::shared_lock lock_1(editor->knot_mtx);
uint32_t cursor_original =
line_to_byte(editor->root, editor->cursor.row, nullptr) +
editor->cursor.col;
TSPoint old_point = {pos.row, pos.col};
uint32_t byte_pos = line_to_byte(editor->root, pos.row, nullptr) + pos.col;
Coord point = move_left_pure(editor, pos, -len);
json lsp_range;
bool do_lsp = (editor->lsp != nullptr);
if (do_lsp) {
LineIterator *it = begin_l_iter(editor->root, point.row);
char *line = next_line(it, nullptr);
int utf16_start = 0;
if (line)
utf16_start = utf8_byte_offset_to_utf16(line, point.col);
free(it->buffer);
free(it);
it = begin_l_iter(editor->root, pos.row);
line = next_line(it, nullptr);
int utf16_end = 0;
if (line)
utf16_end = utf8_byte_offset_to_utf16(line, pos.col);
free(it->buffer);
free(it);
lsp_range = {{"start", {{"line", point.row}, {"character", utf16_start}}},
{"end", {{"line", pos.row}, {"character", utf16_end}}}};
}
uint32_t start = line_to_byte(editor->root, point.row, nullptr) + point.col;
if (cursor_original > start && cursor_original <= byte_pos) {
editor->cursor = point;
editor->cursor_preffered = UINT32_MAX;
} else if (cursor_original > byte_pos) {
uint32_t cursor_new = cursor_original - (byte_pos - start);
uint32_t new_col;
uint32_t new_row = byte_to_line(editor->root, cursor_new, &new_col);
editor->cursor = {new_row, new_col};
editor->cursor_preffered = UINT32_MAX;
}
lock_1.unlock();
uint32_t start_row = point.row;
uint32_t end_row = pos.row;
apply_line_deletion(editor, start_row + 1, end_row);
apply_hook_deletion(editor, start_row + 1, end_row);
std::unique_lock lock_2(editor->knot_mtx);
editor->root = erase(editor->root, start, byte_pos - start);
lock_2.unlock();
if (editor->ts.tree) {
TSInputEdit edit = {
.start_byte = start,
.old_end_byte = byte_pos,
.new_end_byte = start,
.start_point = {point.row, point.col},
.old_end_point = old_point,
.new_end_point = {point.row, point.col},
};
editor->edit_queue.push(edit);
}
if (do_lsp) {
json message = {
{"jsonrpc", "2.0"},
{"method", "textDocument/didChange"},
{"params",
{{"textDocument",
{{"uri", editor->uri}, {"version", ++editor->lsp_version}}},
{"contentChanges",
json::array({{{"range", lsp_range}, {"text", ""}}})}}}};
lsp_send(editor->lsp, message, nullptr);
}
std::unique_lock lock_3(editor->spans.mtx);
apply_edit(editor->spans.spans, start, start - byte_pos);
if (editor->spans.mid_parse)
editor->spans.edits.push({start, start - byte_pos});
std::unique_lock lock_4(editor->def_spans.mtx);
apply_edit(editor->def_spans.spans, byte_pos, start - byte_pos);
} else {
std::shared_lock lock_1(editor->knot_mtx);
uint32_t cursor_original =
line_to_byte(editor->root, editor->cursor.row, nullptr) +
editor->cursor.col;
TSPoint old_point = {pos.row, pos.col};
uint32_t byte_pos = line_to_byte(editor->root, pos.row, nullptr) + pos.col;
Coord point = move_right_pure(editor, pos, len);
json lsp_range;
bool do_lsp = (editor->lsp != nullptr);
if (do_lsp) {
LineIterator *it = begin_l_iter(editor->root, pos.row);
char *line = next_line(it, nullptr);
int utf16_start = 0;
if (line)
utf16_start = utf8_byte_offset_to_utf16(line, pos.col);
free(it->buffer);
free(it);
it = begin_l_iter(editor->root, point.row);
line = next_line(it, nullptr);
int utf16_end = 0;
if (line)
utf16_end = utf8_byte_offset_to_utf16(line, point.col);
free(it->buffer);
free(it);
lsp_range = {{"start", {{"line", pos.row}, {"character", utf16_start}}},
{"end", {{"line", point.row}, {"character", utf16_end}}}};
}
uint32_t end = line_to_byte(editor->root, point.row, nullptr) + point.col;
if (cursor_original > byte_pos && cursor_original <= end) {
editor->cursor = pos;
editor->cursor_preffered = UINT32_MAX;
} else if (cursor_original > end) {
uint32_t cursor_new = cursor_original - (end - byte_pos);
uint32_t new_col;
uint32_t new_row = byte_to_line(editor->root, cursor_new, &new_col);
editor->cursor = {new_row, new_col};
editor->cursor_preffered = UINT32_MAX;
}
lock_1.unlock();
uint32_t start_row = pos.row;
uint32_t end_row = point.row;
apply_line_deletion(editor, start_row + 1, end_row);
apply_hook_deletion(editor, start_row + 1, end_row);
std::unique_lock lock_2(editor->knot_mtx);
editor->root = erase(editor->root, byte_pos, end - byte_pos);
lock_2.unlock();
if (editor->ts.tree) {
TSInputEdit edit = {
.start_byte = byte_pos,
.old_end_byte = end,
.new_end_byte = byte_pos,
.start_point = old_point,
.old_end_point = {point.row, point.col},
.new_end_point = old_point,
};
editor->edit_queue.push(edit);
}
if (do_lsp) {
json message = {
{"jsonrpc", "2.0"},
{"method", "textDocument/didChange"},
{"params",
{{"textDocument",
{{"uri", editor->uri}, {"version", ++editor->lsp_version}}},
{"contentChanges",
json::array({{{"range", lsp_range}, {"text", ""}}})}}}};
lsp_send(editor->lsp, message, nullptr);
}
std::unique_lock lock_3(editor->spans.mtx);
apply_edit(editor->spans.spans, byte_pos, byte_pos - end);
if (editor->spans.mid_parse)
editor->spans.edits.push({byte_pos, byte_pos - end});
std::unique_lock lock_4(editor->def_spans.mtx);
apply_edit(editor->def_spans.spans, byte_pos, byte_pos - end);
}
}
void edit_insert(Editor *editor, Coord pos, char *data, uint32_t len) {
std::shared_lock lock_1(editor->knot_mtx);
uint32_t cursor_original =
line_to_byte(editor->root, editor->cursor.row, nullptr) +
editor->cursor.col;
uint32_t byte_pos = line_to_byte(editor->root, pos.row, nullptr) + pos.col;
TSPoint start_point = {pos.row, pos.col};
if (cursor_original > byte_pos) {
uint32_t cursor_new = cursor_original + len;
uint32_t new_col;
uint32_t new_row = byte_to_line(editor->root, cursor_new, &new_col);
editor->cursor = {new_row, new_col};
}
lock_1.unlock();
std::unique_lock lock_2(editor->knot_mtx);
editor->root = insert(editor->root, byte_pos, data, len);
lock_2.unlock();
uint32_t cols = 0;
uint32_t rows = 0;
for (uint32_t i = 0; i < len; i++) {
if (data[i] == '\n') {
rows++;
cols = 0;
} else {
cols++;
}
}
apply_line_insertion(editor, pos.row, rows);
apply_hook_insertion(editor, pos.row, rows);
if (editor->ts.tree) {
TSInputEdit edit = {
.start_byte = byte_pos,
.old_end_byte = byte_pos,
.new_end_byte = byte_pos + len,
.start_point = start_point,
.old_end_point = start_point,
.new_end_point = {start_point.row + rows,
(rows == 0) ? (start_point.column + cols) : cols},
};
editor->edit_queue.push(edit);
}
if (editor->lsp) {
lock_1.lock();
LineIterator *it = begin_l_iter(editor->root, pos.row);
char *line = next_line(it, nullptr);
int utf16_col = 0;
if (line)
utf16_col = utf8_byte_offset_to_utf16(line, pos.col);
free(it->buffer);
free(it);
lock_1.unlock();
json message = {
{"jsonrpc", "2.0"},
{"method", "textDocument/didChange"},
{"params",
{{"textDocument",
{{"uri", editor->uri}, {"version", ++editor->lsp_version}}},
{"contentChanges",
json::array(
{{{"range",
{{"start", {{"line", pos.row}, {"character", utf16_col}}},
{"end", {{"line", pos.row}, {"character", utf16_col}}}}},
{"text", std::string(data, len)}}})}}}};
lsp_send(editor->lsp, message, nullptr);
}
std::unique_lock lock_3(editor->spans.mtx);
apply_edit(editor->spans.spans, byte_pos, len);
if (editor->spans.mid_parse)
editor->spans.edits.push({byte_pos, len});
std::unique_lock lock_4(editor->def_spans.mtx);
apply_edit(editor->def_spans.spans, byte_pos, len);
}
char *get_selection(Editor *editor, uint32_t *out_len, Coord *out_start) {
std::shared_lock lock(editor->knot_mtx);
Coord start, end;
if (editor->cursor >= editor->selection) {
uint32_t prev_col, next_col;
switch (editor->selection_type) {
case CHAR:
start = editor->selection;
end = move_right(editor, editor->cursor, 1);
break;
case WORD:
word_boundaries(editor, editor->selection, &prev_col, &next_col, nullptr,
nullptr);
start = {editor->selection.row, prev_col};
end = editor->cursor;
break;
case LINE:
start = {editor->selection.row, 0};
end = editor->cursor;
break;
}
} else {
start = editor->cursor;
uint32_t prev_col, next_col, line_len;
switch (editor->selection_type) {
case CHAR:
end = move_right(editor, editor->selection, 1);
break;
case WORD:
word_boundaries(editor, editor->selection, &prev_col, &next_col, nullptr,
nullptr);
end = {editor->selection.row, next_col};
break;
case LINE:
LineIterator *it = begin_l_iter(editor->root, editor->selection.row);
char *line = next_line(it, &line_len);
if (!line)
return nullptr;
if (line_len > 0 && line[line_len - 1] == '\n')
line_len--;
end = {editor->selection.row, line_len};
free(it->buffer);
free(it);
break;
}
}
if (out_start)
*out_start = start;
uint32_t start_byte =
line_to_byte(editor->root, start.row, nullptr) + start.col;
uint32_t end_byte = line_to_byte(editor->root, end.row, nullptr) + end.col;
char *text = read(editor->root, start_byte, end_byte - start_byte);
if (out_len)
*out_len = end_byte - start_byte;
return text;
}
void apply_edit(std::vector<Span> &spans, uint32_t x, int64_t y) {
Span key{.start = x, .end = 0, .hl = nullptr};
auto it = std::lower_bound(
spans.begin(), spans.end(), key,
[](const Span &a, const Span &b) { return a.start < b.start; });
size_t idx = std::distance(spans.begin(), it);
while (idx > 0 && spans.at(idx - 1).end >= x)
--idx;
for (size_t i = idx; i < spans.size();) {
Span &s = spans.at(i);
if (s.start < x && s.end >= x) {
s.end += y;
} else if (s.start > x) {
s.start += y;
s.end += y;
}
if (s.end <= s.start)
spans.erase(spans.begin() + i);
else
++i;
}
}
std::vector<Fold>::iterator find_fold_iter(Editor *editor, uint32_t line) {
auto &folds = editor->folds;
auto it = std::lower_bound(
folds.begin(), folds.end(), line,
[](const Fold &fold, uint32_t value) { return fold.start < value; });
if (it != folds.end() && it->start == line)
return it;
if (it != folds.begin()) {
--it;
if (it->contains(line))
return it;
}
return folds.end();
}
bool add_fold(Editor *editor, uint32_t start, uint32_t end) {
if (!editor || !editor->root)
return false;
if (start > end)
std::swap(start, end);
if (start >= editor->root->line_count)
return false;
end = std::min(end, editor->root->line_count - 1);
if (start == end)
return false;
Fold new_fold{start, end};
auto &folds = editor->folds;
auto it = std::lower_bound(
folds.begin(), folds.end(), new_fold.start,
[](const Fold &fold, uint32_t value) { return fold.start < value; });
if (it != folds.begin()) {
auto prev = std::prev(it);
if (prev->end + 1 >= new_fold.start) {
new_fold.start = std::min(new_fold.start, prev->start);
new_fold.end = std::max(new_fold.end, prev->end);
it = folds.erase(prev);
}
}
while (it != folds.end() && it->start <= new_fold.end + 1) {
new_fold.end = std::max(new_fold.end, it->end);
it = folds.erase(it);
}
folds.insert(it, new_fold);
return true;
}
bool remove_fold(Editor *editor, uint32_t line) {
auto it = find_fold_iter(editor, line);
if (it == editor->folds.end())
return false;
editor->folds.erase(it);
return true;
}
void apply_line_insertion(Editor *editor, uint32_t line, uint32_t rows) {
for (auto it = editor->folds.begin(); it != editor->folds.end();) {
if (line <= it->start) {
it->start += rows;
it->end += rows;
++it;
} else if (line <= it->end) {
it = editor->folds.erase(it);
} else {
++it;
}
}
}
void apply_line_deletion(Editor *editor, uint32_t removal_start,
uint32_t removal_end) {
if (removal_start > removal_end)
return;
uint32_t rows_removed = removal_end - removal_start + 1;
std::vector<Fold> updated;
updated.reserve(editor->folds.size());
for (auto fold : editor->folds) {
if (removal_end < fold.start) {
fold.start -= rows_removed;
fold.end -= rows_removed;
updated.push_back(fold);
continue;
}
if (removal_start > fold.end) {
updated.push_back(fold);
continue;
}
}
editor->folds.swap(updated);
}
void apply_hook_insertion(Editor *editor, uint32_t line, uint32_t rows) {
for (auto &hook : editor->hooks)
if (hook > line)
hook += rows;
}
void apply_hook_deletion(Editor *editor, uint32_t removal_start,
uint32_t removal_end) {
for (auto &hook : editor->hooks)
if (hook > removal_start)
hook -= removal_end - removal_start + 1;
}

View File

@@ -1,12 +1,4 @@
extern "C" { #include "io/ui.h"
#include "../libs/libgrapheme/grapheme.h"
}
#include "../include/ui.h"
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
static Queue<char> input_queue; static Queue<char> input_queue;

View File

@@ -1,12 +1,4 @@
#include "../include/knot.h" #include "io/knot.h"
#include <assert.h>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <pcre2.h>
#include <stdio.h>
#include <string.h>
static void update(Knot *n) { static void update(Knot *n) {
if (!n) if (!n)
@@ -796,7 +788,7 @@ char *leaf_from_offset(Knot *root, uint32_t start_offset, uint32_t *out_len) {
return nullptr; return nullptr;
} }
std::vector<std::pair<size_t, size_t>> search_rope(Knot *root, std::vector<std::pair<size_t, size_t>> search_rope_dfa(Knot *root,
const char *pattern) { const char *pattern) {
std::vector<std::pair<size_t, size_t>> results; std::vector<std::pair<size_t, size_t>> results;
int errorcode; int errorcode;
@@ -815,15 +807,17 @@ std::vector<std::pair<size_t, size_t>> search_rope(Knot *root,
pcre2_match_data_free(mdata); pcre2_match_data_free(mdata);
return results; return results;
} }
size_t limit = 256;
results.reserve(limit);
size_t chunk_abs_offset = 0; size_t chunk_abs_offset = 0;
size_t saved_match_start = 0; size_t saved_match_start = 0;
bool match_in_progress = false; bool match_in_progress = false;
int flags = PCRE2_PARTIAL_SOFT; int flags = PCRE2_PARTIAL_SOFT;
while (1) { while (1) {
const char *chunk_start = next_leaf(it, nullptr); uint32_t chunk_len;
const char *chunk_start = next_leaf(it, &chunk_len);
if (!chunk_start) if (!chunk_start)
break; break;
size_t chunk_len = strlen(chunk_start);
const char *current_ptr = chunk_start; const char *current_ptr = chunk_start;
size_t remaining_len = chunk_len; size_t remaining_len = chunk_len;
while (remaining_len > 0) { while (remaining_len > 0) {
@@ -845,6 +839,10 @@ std::vector<std::pair<size_t, size_t>> search_rope(Knot *root,
chunk_abs_offset + (current_ptr - chunk_start) + ov[1]; chunk_abs_offset + (current_ptr - chunk_start) + ov[1];
} }
size_t total_len = match_end_abs - match_start_abs; size_t total_len = match_end_abs - match_start_abs;
if (results.size() >= limit) {
limit *= 2;
results.reserve(limit);
}
results.push_back(std::make_pair(match_start_abs, total_len)); results.push_back(std::make_pair(match_start_abs, total_len));
size_t consumed = ov[1]; size_t consumed = ov[1];
if (consumed == 0) if (consumed == 0)
@@ -876,7 +874,6 @@ std::vector<std::pair<size_t, size_t>> search_rope(Knot *root,
} else { } else {
break; break;
} }
// if (rc != PCRE2_ERROR_NOMATCH) {} // handle error
} }
} }
chunk_abs_offset += chunk_len; chunk_abs_offset += chunk_len;
@@ -889,125 +886,69 @@ std::vector<std::pair<size_t, size_t>> search_rope(Knot *root,
return results; return results;
} }
// TODO: Optimize and make it actually utilize capture groups etc. static const size_t MAX_OVERLAP = 1024;
//
// static const size_t MAX_OVERLAP = 1024; std::vector<Match> search_rope(Knot *root, const char *pattern) {
// std::vector<Match> results;
// std::vector<std::pair<size_t, size_t>> search_rope_new(Knot *root, int errorcode;
// const char *pattern) { PCRE2_SIZE erroffset;
// std::vector<std::pair<size_t, size_t>> results; pcre2_code *re = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, 0,
// int errorcode; &errorcode, &erroffset, nullptr);
// PCRE2_SIZE erroffset; if (!re)
// return results;
// // 1. Compile (Standard compilation) pcre2_match_data *mdata = pcre2_match_data_create_from_pattern(re, nullptr);
// pcre2_code *re = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, LeafIterator *it = begin_k_iter(root, 0);
// 0, if (!it) {
// &errorcode, &erroffset, nullptr); pcre2_match_data_free(mdata);
// if (!re) { pcre2_code_free(re);
// fprintf(stderr, "PCRE2 compile error: %d\n", errorcode); return results;
// return results; }
// } size_t limit = 256;
// results.reserve(limit);
// pcre2_match_data *mdata = pcre2_match_data_create_from_pattern(re, std::string buffer;
// nullptr); buffer.reserve(MAX_OVERLAP * 2);
// size_t buffer_abs_offset = 0;
// LeafIterator *it = begin_k_iter(root, 0); size_t processed_up_to = 0;
// if (!it) { while (true) {
// pcre2_code_free(re); uint32_t chunk_len;
// pcre2_match_data_free(mdata); const char *chunk = next_leaf(it, &chunk_len);
// return results; if (!chunk)
// } break;
// buffer.append(chunk, chunk_len);
// // Buffer to hold (Last X chars) + (Current Chunk) PCRE2_SPTR subject = (PCRE2_SPTR)buffer.data();
// std::string buffer; size_t subject_len = buffer.size();
// size_t start_offset = 0;
// // Tracks where the *start* of the current buffer is located relative to while (true) {
// the int rc = pcre2_match(re, subject, subject_len, start_offset, 0, mdata,
// // whole rope nullptr);
// size_t buffer_abs_offset = 0; if (rc < 0)
// break;
// // Tracks the absolute offset up to which we have already "cleared" PCRE2_SIZE *ov = pcre2_get_ovector_pointer(mdata);
// matches. size_t local_start = ov[0];
// // This prevents reporting a match twice if it sits inside the overlap size_t local_end = ov[1];
// region. size_t processed_up_to_abs = 0; size_t abs_start = buffer_abs_offset + local_start;
// if (abs_start >= processed_up_to) {
// while (1) { if (results.size() >= limit) {
// // 2. Get next chunk limit *= 2;
// const char *chunk_start = next_leaf(it, nullptr); results.reserve(limit);
// if (!chunk_start) }
// break; results.push_back({abs_start, abs_start + local_end - local_start,
// std::string(buffer.data() + local_start,
// // 3. Update Buffer: Append new data local_end - local_start)});
// size_t chunk_len = strlen(chunk_start); processed_up_to = abs_start + 1;
// buffer.append(chunk_start, chunk_len); }
// start_offset = (local_end > local_start) ? local_end : local_start + 1;
// PCRE2_SPTR subject = (PCRE2_SPTR)buffer.c_str(); if (start_offset >= subject_len)
// size_t subject_len = buffer.length(); break;
// size_t start_offset = 0; }
// if (buffer.size() > MAX_OVERLAP) {
// // 4. Run pcre2_match loop on the current window size_t trim = buffer.size() - MAX_OVERLAP;
// while (true) { buffer.erase(0, trim);
// int rc = pcre2_match(re, subject, subject_len, start_offset, buffer_abs_offset += trim;
// 0, // Default options }
// mdata, nullptr); }
// pcre2_match_data_free(mdata);
// if (rc < 0) { pcre2_code_free(re);
// // No match (or error) in the rest of this buffer free(it);
// break; return results;
// } }
//
// PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(mdata);
// size_t match_local_start = ovector[0];
// size_t match_local_end = ovector[1];
//
// // Calculate Absolute Coordinates
// size_t match_abs_start = buffer_abs_offset + match_local_start;
// size_t match_len = match_local_end - match_local_start;
//
// // 5. Deduplication Check
// // If we find a match that starts *before* where we finished processing
// // the previous chunk, it means this match is entirely inside the
// // overlap region and was reported in the previous iteration.
// if (match_abs_start >= processed_up_to_abs) {
// results.push_back(std::make_pair(match_abs_start, match_len));
// // Update processed marker so we don't report this again
// // (Using start + 1 ensures we allow overlapping matches if regex
// // allows, but strictly prevents the exact same start index being
// // reported twice)
// processed_up_to_abs = match_abs_start + 1;
// }
//
// // Prepare for next match in this buffer
// start_offset = match_local_end;
//
// // Handle empty matches (e.g. "a*" matching empty string) to prevent
// // infinite loop
// if (match_local_end == match_local_start) {
// if (start_offset < subject_len) {
// start_offset++;
// } else {
// break; // End of buffer
// }
// }
// }
//
// // 6. Maintenance: Shrink buffer to keep only the last MAX_OVERLAP
// // characters
// if (buffer.length() > MAX_OVERLAP) {
// size_t to_remove = buffer.length() - MAX_OVERLAP;
//
// // Remove from the beginning of the string
// buffer.erase(0, to_remove);
//
// // The buffer's start has now moved forward in absolute terms
// buffer_abs_offset += to_remove;
// }
// }
//
// // Cleanup
// pcre2_match_data_free(mdata);
// pcre2_code_free(re);
// free(it); // Assuming iter needs free based on original code usage
//
// return results;
// }

View File

@@ -1,4 +1,4 @@
#include "../include/ui.h" #include "io/ui.h"
uint32_t rows, cols; uint32_t rows, cols;
bool show_cursor = 0; bool show_cursor = 0;
@@ -55,9 +55,13 @@ void update(uint32_t row, uint32_t col, std::string utf8, uint32_t fg,
uint32_t idx = row * cols + col; uint32_t idx = row * cols + col;
std::lock_guard<std::mutex> lock(screen_mutex); std::lock_guard<std::mutex> lock(screen_mutex);
screen[idx].utf8 = utf8 != "" ? utf8 : ""; screen[idx].utf8 = utf8 != "" ? utf8 : "";
if (utf8 == "")
return;
screen[idx].width = display_width(utf8.c_str(), utf8.size());
screen[idx].fg = fg; screen[idx].fg = fg;
screen[idx].bg = bg; screen[idx].bg = bg;
screen[idx].flags = flags; screen[idx].flags = flags;
screen[idx].ul_color = 0;
} }
void update(uint32_t row, uint32_t col, const char *utf8, uint32_t fg, void update(uint32_t row, uint32_t col, const char *utf8, uint32_t fg,
@@ -67,17 +71,59 @@ void update(uint32_t row, uint32_t col, const char *utf8, uint32_t fg,
uint32_t idx = row * cols + col; uint32_t idx = row * cols + col;
std::lock_guard<std::mutex> lock(screen_mutex); std::lock_guard<std::mutex> lock(screen_mutex);
screen[idx].utf8 = utf8 ? utf8 : ""; screen[idx].utf8 = utf8 ? utf8 : "";
if (utf8 == nullptr)
return;
screen[idx].width = display_width(utf8, strlen(utf8));
screen[idx].fg = fg; screen[idx].fg = fg;
screen[idx].bg = bg; screen[idx].bg = bg;
screen[idx].flags = flags; screen[idx].flags = flags;
screen[idx].ul_color = 0;
}
void update(uint32_t row, uint32_t col, std::string utf8, uint32_t fg,
uint32_t bg, uint8_t flags, uint32_t ul_color) {
if (row >= rows || col >= cols)
return;
uint32_t idx = row * cols + col;
std::lock_guard<std::mutex> lock(screen_mutex);
screen[idx].utf8 = utf8 != "" ? utf8 : "";
if (utf8 == "")
return;
screen[idx].width = display_width(utf8.c_str(), utf8.size());
screen[idx].fg = fg;
screen[idx].bg = bg;
screen[idx].flags = flags;
screen[idx].ul_color = ul_color;
}
void update(uint32_t row, uint32_t col, const char *utf8, uint32_t fg,
uint32_t bg, uint8_t flags, uint32_t ul_color) {
if (row >= rows || col >= cols)
return;
uint32_t idx = row * cols + col;
std::lock_guard<std::mutex> lock(screen_mutex);
screen[idx].utf8 = utf8 ? utf8 : "";
if (utf8 == nullptr)
return;
screen[idx].width = display_width(utf8, strlen(utf8));
screen[idx].fg = fg;
screen[idx].bg = bg;
screen[idx].flags = flags;
screen[idx].ul_color = ul_color;
}
inline bool is_empty_cell(const ScreenCell &c) {
return c.utf8.empty() || c.utf8 == " " || c.utf8 == "\x1b";
} }
void render() { void render() {
static bool first_render = true; static bool first_render = true;
uint32_t current_fg = 0; uint32_t current_fg = 0;
uint32_t current_bg = 0; uint32_t current_bg = 0;
uint32_t current_ul_color = 0;
bool current_italic = false; bool current_italic = false;
bool current_bold = false; bool current_bold = false;
bool current_strikethrough = false;
bool current_underline = false; bool current_underline = false;
std::lock_guard<std::mutex> lock(screen_mutex); std::lock_guard<std::mutex> lock(screen_mutex);
std::string out; std::string out;
@@ -94,15 +140,25 @@ void render() {
uint32_t idx = row * cols + col; uint32_t idx = row * cols + col;
ScreenCell &old_cell = old_screen[idx]; ScreenCell &old_cell = old_screen[idx];
ScreenCell &new_cell = screen[idx]; ScreenCell &new_cell = screen[idx];
bool content_changed = old_cell.utf8 != new_cell.utf8; bool content_changed =
bool style_changed = old_cell.utf8 != new_cell.utf8 || old_cell.fg != new_cell.fg ||
(old_cell.fg != new_cell.fg) || (old_cell.bg != new_cell.bg) || old_cell.bg != new_cell.bg || old_cell.flags != new_cell.flags ||
((old_cell.flags & CF_ITALIC) != (new_cell.flags & CF_ITALIC)) || old_cell.ul_color != new_cell.ul_color;
((old_cell.flags & CF_BOLD) != (new_cell.flags & CF_BOLD)) || if (content_changed) {
((old_cell.flags & CF_UNDERLINE) != (new_cell.flags & CF_UNDERLINE)); if (first_change_col == -1) {
if (content_changed || style_changed) {
if (first_change_col == -1)
first_change_col = col; first_change_col = col;
if (first_change_col > 0) {
for (int back = 1; back <= 3 && first_change_col - back >= 0;
++back) {
ScreenCell &prev_cell =
screen[row * cols + (first_change_col - back)];
if (prev_cell.width > 1) {
first_change_col -= back;
break;
}
}
}
}
last_change_col = col; last_change_col = col;
} }
} }
@@ -115,6 +171,20 @@ void render() {
int idx = row * cols + col; int idx = row * cols + col;
ScreenCell &old_cell = old_screen[idx]; ScreenCell &old_cell = old_screen[idx];
ScreenCell &new_cell = screen[idx]; ScreenCell &new_cell = screen[idx];
int width = new_cell.width > 0 ? new_cell.width : 1;
bool overlap = false;
if (width > 1) {
for (int i = 1; i < width; ++i) {
int next_col = col + i;
if (next_col >= cols)
break;
const ScreenCell &next = screen[row * cols + next_col];
if (!is_empty_cell(next)) {
overlap = true;
break;
}
}
}
if (current_fg != new_cell.fg) { if (current_fg != new_cell.fg) {
if (new_cell.fg) { if (new_cell.fg) {
char fb[64]; char fb[64];
@@ -149,25 +219,49 @@ void render() {
out += bold ? "\x1b[1m" : "\x1b[22m"; out += bold ? "\x1b[1m" : "\x1b[22m";
current_bold = bold; current_bold = bold;
} }
bool strikethrough = (new_cell.flags & CF_STRIKETHROUGH) != 0;
if (strikethrough != current_strikethrough) {
out += strikethrough ? "\x1b[9m" : "\x1b[29m";
current_strikethrough = strikethrough;
}
bool underline = (new_cell.flags & CF_UNDERLINE) != 0; bool underline = (new_cell.flags & CF_UNDERLINE) != 0;
if (underline) {
if (new_cell.ul_color != current_ul_color) {
if (new_cell.ul_color) {
char ubuf[64];
snprintf(ubuf, sizeof(ubuf), "\x1b[58;2;%d;%d;%dm",
(new_cell.ul_color >> 16) & 0xFF,
(new_cell.ul_color >> 8) & 0xFF,
(new_cell.ul_color >> 0) & 0xFF);
out.append(ubuf);
} else {
out += "\x1b[59m";
}
current_ul_color = new_cell.ul_color;
}
}
if (underline != current_underline) { if (underline != current_underline) {
out += underline ? "\x1b[4m" : "\x1b[24m"; out += underline ? "\x1b[4m" : "\x1b[24m";
current_underline = underline; current_underline = underline;
} }
if (width > 1 && overlap) {
for (int i = 1; i < width; ++i)
out.push_back(' ');
} else {
if (!new_cell.utf8.empty()) { if (!new_cell.utf8.empty()) {
if (new_cell.utf8[0] == '\t') if (new_cell.utf8[0] == '\t')
out.append(" "); out.append(" ");
else if (new_cell.utf8[0] == '\x1b') else if (new_cell.utf8[0] != '\x1b')
out.append("");
else
out.append(new_cell.utf8); out.append(new_cell.utf8);
} else { } else {
out.append(1, ' '); out.push_back(' ');
}
} }
old_cell.utf8 = new_cell.utf8; old_cell.utf8 = new_cell.utf8;
old_cell.fg = new_cell.fg; old_cell.fg = new_cell.fg;
old_cell.bg = new_cell.bg; old_cell.bg = new_cell.bg;
old_cell.flags = new_cell.flags; old_cell.flags = new_cell.flags;
old_cell.width = new_cell.width;
} }
} }
out += "\x1b[0m"; out += "\x1b[0m";

View File

@@ -1,326 +0,0 @@
#include "../include/lsp.h"
#include "../include/maps.h"
#include <fcntl.h>
#include <signal.h>
#include <sys/poll.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
std::shared_mutex active_lsps_mtx;
std::unordered_map<uint8_t, LSPInstance *> active_lsps;
Queue<LSPOpenRequest> lsp_open_queue;
static bool init_lsp(LSPInstance *lsp) {
int in_pipe[2];
int out_pipe[2];
if (pipe(in_pipe) == -1 || pipe(out_pipe) == -1) {
perror("pipe");
return false;
}
pid_t pid = fork();
if (pid == -1) {
perror("fork");
return false;
}
if (pid == 0) {
dup2(in_pipe[0], STDIN_FILENO);
dup2(out_pipe[1], STDOUT_FILENO);
int devnull = open("/dev/null", O_WRONLY);
if (devnull >= 0) {
dup2(devnull, STDERR_FILENO);
close(devnull);
}
close(in_pipe[1]);
close(out_pipe[0]);
execvp(lsp->lsp->command, (char *const *)(lsp->lsp->args.data()));
perror("execvp");
return false;
}
lsp->pid = pid;
lsp->stdin_fd = in_pipe[1];
lsp->stdout_fd = out_pipe[0];
close(in_pipe[0]);
close(out_pipe[1]);
return true;
}
LSPInstance *get_or_init_lsp(uint8_t lsp_id) {
std::unique_lock lock(active_lsps_mtx);
auto it = active_lsps.find(lsp_id);
if (it == active_lsps.end()) {
auto map_it = kLsps.find(lsp_id);
if (map_it == kLsps.end())
return nullptr;
LSPInstance *lsp = new LSPInstance();
lsp->lsp = &map_it->second;
if (!init_lsp(lsp)) {
delete lsp;
return nullptr;
}
LSPPending *pending = new LSPPending();
pending->method = "initialize";
pending->editor = nullptr;
pending->callback = [lsp](Editor *, std::string, json) {
lsp->initialized = true;
json initialized = {{"jsonrpc", "2.0"},
{"method", "initialized"},
{"params", json::object()}};
lsp_send(lsp, initialized, nullptr);
};
json init_message = {
{"jsonrpc", "2.0"},
{"method", "initialize"},
{"params",
{{"processId", getpid()},
{"rootUri", "file://" + std::filesystem::current_path().string()},
{"capabilities", json::object()}}}};
lsp_send(lsp, init_message, pending);
active_lsps[lsp_id] = lsp;
return lsp;
}
return it->second;
}
void lsp_send(LSPInstance *lsp, json message, LSPPending *pending) {
if (!lsp || lsp->stdin_fd == -1)
return;
std::unique_lock lock(lsp->mtx);
if (pending) {
message["id"] = lsp->last_id++;
uint32_t id = message["id"].get<uint32_t>();
lsp->pending[id] = pending;
}
lsp->outbox.push(message);
}
void close_lsp(uint8_t lsp_id) {
std::shared_lock active_lsps_lock(active_lsps_mtx);
auto it = active_lsps.find(lsp_id);
if (it == active_lsps.end())
return;
LSPInstance *lsp = it->second;
active_lsps_lock.unlock();
LSPPending *shutdown_pending = new LSPPending();
shutdown_pending->method = "shutdown";
shutdown_pending->callback = [lsp, lsp_id](Editor *, std::string, json) {
json exit = {{"jsonrpc", "2.0"}, {"method", "exit"}};
lsp_send(lsp, exit, nullptr);
};
json shutdown = {{"jsonrpc", "2.0"}, {"method", "shutdown"}};
lsp_send(lsp, shutdown, shutdown_pending);
std::thread t([lsp, lsp_id] {
std::this_thread::sleep_for(100ms);
std::unique_lock active_lsps_lock(active_lsps_mtx);
std::unique_lock lock(lsp->mtx);
if (kill(lsp->pid, 0) == 0)
kill(lsp->pid, SIGKILL);
waitpid(lsp->pid, nullptr, 0);
close(lsp->stdin_fd);
close(lsp->stdout_fd);
while (!lsp->outbox.empty())
lsp->outbox.pop();
while (!lsp->inbox.empty())
lsp->inbox.pop();
for (auto &kv : lsp->pending)
delete kv.second;
delete lsp;
active_lsps.erase(lsp_id);
});
t.detach();
}
static std::optional<json> read_lsp_message(int fd) {
std::string header;
char c;
while (true) {
ssize_t n = read(fd, &c, 1);
if (n <= 0)
return std::nullopt;
header.push_back(c);
if (header.size() >= 4 && header.substr(header.size() - 4) == "\r\n\r\n")
break;
}
size_t pos = header.find("Content-Length:");
if (pos == std::string::npos)
return std::nullopt;
pos += strlen("Content-Length:");
while (pos < header.size() && std::isspace(header[pos]))
pos++;
size_t end = pos;
while (end < header.size() && std::isdigit(header[end]))
end++;
size_t len = std::stoul(header.substr(pos, end - pos));
std::string body(len, '\0');
size_t got = 0;
while (got < len) {
ssize_t n = read(fd, &body[got], len - got);
if (n <= 0)
return std::nullopt;
got += n;
}
return json::parse(body);
}
static Editor *editor_for_uri(LSPInstance *lsp, std::string uri) {
if (uri.empty())
return nullptr;
for (auto &editor : lsp->editors)
if (editor->uri == uri)
return editor;
return nullptr;
}
void lsp_worker() {
LSPOpenRequest request;
while (lsp_open_queue.pop(request))
add_to_lsp(request.language, request.editor);
std::shared_lock active_lsps_lock(active_lsps_mtx);
for (auto &kv : active_lsps) {
LSPInstance *lsp = kv.second;
std::unique_lock lock(lsp->mtx);
while (!lsp->outbox.empty()) {
json message;
message = lsp->outbox.front();
if (!lsp->initialized) {
std::string m = message.value("method", "");
if (m != "initialize")
break;
}
lsp->outbox.pop(message);
std::string payload = message.dump();
std::string header =
"Content-Length: " + std::to_string(payload.size()) + "\r\n\r\n";
std::string out = header + payload;
const char *ptr = out.data();
size_t remaining = out.size();
while (remaining > 0) {
ssize_t written = write(lsp->stdin_fd, ptr, remaining);
if (written == 0)
break;
else if (written == -1) {
if (errno == EINTR)
continue;
perror("write");
break;
} else {
ptr += written;
remaining -= written;
}
}
}
pollfd pfd{lsp->stdout_fd, POLLIN, 0};
while (poll(&pfd, 1, 0) > 0) {
auto msg = read_lsp_message(lsp->stdout_fd);
if (!msg)
break;
if (msg->contains("id")) {
uint32_t id = msg->at("id").get<uint32_t>();
auto it = lsp->pending.find(id);
if (it != lsp->pending.end()) {
LSPPending *pend = it->second;
lock.unlock();
if (pend->callback)
pend->callback(pend->editor, pend->method, *msg);
delete pend;
lock.lock();
lsp->pending.erase(it);
}
} else if (msg->contains("method")) {
std::string uri;
if (msg->contains("params")) {
auto &p = (*msg)["params"];
if (p.contains("textDocument") && p["textDocument"].contains("uri"))
uri = p["textDocument"]["uri"].get<std::string>();
else if (p.contains("uri"))
uri = p["uri"].get<std::string>();
}
Editor *ed = editor_for_uri(lsp, uri);
lock.unlock();
if (ed)
editor_lsp_handle(ed, *msg);
else
lsp_handle(lsp, *msg);
lock.lock();
}
}
}
}
void request_add_to_lsp(Language language, Editor *editor) {
lsp_open_queue.push({language, editor});
}
void add_to_lsp(Language language, Editor *editor) {
LSPInstance *lsp = get_or_init_lsp(language.lsp_id);
if (!lsp)
return;
std::unique_lock lock(lsp->mtx);
if (editor->lsp == lsp)
return;
lsp->editors.push_back(editor);
lock.unlock();
std::unique_lock lock2(editor->lsp_mtx);
editor->lsp = lsp;
lock2.unlock();
std::unique_lock lock3(editor->knot_mtx);
char *buf = read(editor->root, 0, editor->root->char_count);
std::string text(buf);
free(buf);
json message = {{"jsonrpc", "2.0"},
{"method", "textDocument/didOpen"},
{"params",
{{"textDocument",
{{"uri", editor->uri},
{"languageId", language.name},
{"version", 1},
{"text", text}}}}}};
lock3.unlock();
lsp_send(lsp, message, nullptr);
}
static uint8_t find_lsp_id(LSPInstance *needle) {
for (const auto &[id, lsp] : active_lsps)
if (lsp == needle)
return id;
return 0;
}
void remove_from_lsp(Editor *editor) {
auto lsp = editor->lsp;
if (!lsp)
return;
std::unique_lock lock1(lsp->mtx);
lsp->editors.erase(
std::remove(lsp->editors.begin(), lsp->editors.end(), editor),
lsp->editors.end());
lock1.unlock();
std::unique_lock lock2(editor->lsp_mtx);
editor->lsp = nullptr;
lock2.unlock();
json message = {{"jsonrpc", "2.0"},
{"method", "textDocument/didClose"},
{"params", {{"textDocument", {{"uri", editor->uri}}}}}};
lsp_send(lsp, message, nullptr);
uint8_t lsp_id = find_lsp_id(lsp);
if (lsp_id && lsp->editors.empty())
close_lsp(lsp_id);
}
void lsp_handle(LSPInstance *, json message) {
std::string method = message.value("method", "");
if (method == "window/showMessage") {
if (message.contains("params")) {
auto &p = message["params"];
if (p.contains("message"))
log("%s\n", p["message"].get<std::string>().c_str());
}
} else if (method == "window/logMessage") {
if (message.contains("params")) {
auto &p = message["params"];
if (p.contains("message"))
log("%s\n", p["message"].get<std::string>().c_str());
}
}
}

87
src/lsp/handlers.cc Normal file
View File

@@ -0,0 +1,87 @@
#include "lsp/lsp.h"
Queue<LSPOpenRequest> lsp_open_queue;
void request_add_to_lsp(Language language, Editor *editor) {
lsp_open_queue.push({language, editor});
}
void add_to_lsp(Language language, Editor *editor) {
std::shared_ptr<LSPInstance> lsp = get_or_init_lsp(language.lsp_id);
if (!lsp)
return;
std::unique_lock lock(lsp->mtx);
if (editor->lsp == lsp)
return;
lsp->editors.push_back(editor);
lsp->open_queue.push({language, editor});
lock.unlock();
}
void open_editor(std::shared_ptr<LSPInstance> lsp,
std::pair<Language, Editor *> entry) {
Language language = entry.first;
Editor *editor = entry.second;
if (editor->lsp == lsp)
return;
editor->lsp = lsp;
std::unique_lock lock3(editor->knot_mtx);
char *buf = read(editor->root, 0, editor->root->char_count);
std::string text(buf);
free(buf);
json message = {{"jsonrpc", "2.0"},
{"method", "textDocument/didOpen"},
{"params",
{{"textDocument",
{{"uri", editor->uri},
{"languageId", language.name},
{"version", 1},
{"text", text}}}}}};
lock3.unlock();
lsp_send(lsp, message, nullptr);
}
static uint8_t find_lsp_id(std::shared_ptr<LSPInstance> needle) {
for (const auto &[id, lsp] : active_lsps)
if (lsp == needle)
return id;
return 0;
}
void remove_from_lsp(Editor *editor) {
auto lsp = editor->lsp;
if (!lsp)
return;
std::unique_lock lock1(lsp->mtx);
lsp->editors.erase(
std::remove(lsp->editors.begin(), lsp->editors.end(), editor),
lsp->editors.end());
lock1.unlock();
std::unique_lock lock2(editor->lsp_mtx);
editor->lsp = nullptr;
lock2.unlock();
json message = {{"jsonrpc", "2.0"},
{"method", "textDocument/didClose"},
{"params", {{"textDocument", {{"uri", editor->uri}}}}}};
lsp_send(lsp, message, nullptr);
uint8_t lsp_id = find_lsp_id(lsp);
if (lsp_id && lsp->editors.empty())
close_lsp(lsp_id);
}
void lsp_handle(std::shared_ptr<LSPInstance>, json message) {
std::string method = message.value("method", "");
if (method == "window/showMessage") {
if (message.contains("params")) {
auto &p = message["params"];
if (p.contains("message"))
log("%s\n", p["message"].get<std::string>().c_str());
}
} else if (method == "window/logMessage") {
if (message.contains("params")) {
auto &p = message["params"];
if (p.contains("message"))
log("%s\n", p["message"].get<std::string>().c_str());
}
}
}

150
src/lsp/process.cc Normal file
View File

@@ -0,0 +1,150 @@
#include "config.h"
#include "lsp/lsp.h"
static bool init_lsp(std::shared_ptr<LSPInstance> lsp) {
int in_pipe[2];
int out_pipe[2];
if (pipe(in_pipe) == -1 || pipe(out_pipe) == -1) {
perror("pipe");
return false;
}
pid_t pid = fork();
if (pid == -1) {
perror("fork");
return false;
}
if (pid == 0) {
dup2(in_pipe[0], STDIN_FILENO);
dup2(out_pipe[1], STDOUT_FILENO);
#ifdef __clang__
int devnull = open("/dev/null", O_WRONLY);
if (devnull >= 0) {
dup2(devnull, STDERR_FILENO);
close(devnull);
}
#else
int log = open("/tmp/lsp.log", O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (log >= 0) {
dup2(log, STDERR_FILENO);
close(log);
}
#endif
close(in_pipe[0]);
close(in_pipe[1]);
close(out_pipe[0]);
close(out_pipe[1]);
execvp(lsp->lsp->command, (char *const *)(lsp->lsp->args.data()));
perror("execvp");
_exit(127);
}
lsp->pid = pid;
lsp->stdin_fd = in_pipe[1];
lsp->stdout_fd = out_pipe[0];
close(in_pipe[0]);
close(out_pipe[1]);
return true;
}
std::shared_ptr<LSPInstance> get_or_init_lsp(uint8_t lsp_id) {
std::unique_lock lock(active_lsps_mtx);
auto it = active_lsps.find(lsp_id);
if (it == active_lsps.end()) {
auto map_it = kLsps.find(lsp_id);
if (map_it == kLsps.end())
return nullptr;
std::shared_ptr<LSPInstance> lsp = std::make_shared<LSPInstance>();
lsp->lsp = &map_it->second;
if (!init_lsp(lsp))
return nullptr;
LSPPending *pending = new LSPPending();
pending->method = "initialize";
pending->editor = nullptr;
pending->callback = [lsp](Editor *, std::string, json msg) {
if (msg.contains("result") && msg["result"].contains("capabilities")) {
auto &caps = msg["result"]["capabilities"];
if (caps.contains("textDocumentSync")) {
auto &sync = caps["textDocumentSync"];
if (sync.is_number()) {
int change_type = sync.get<int>();
lsp->incremental_sync = (change_type == 2);
} else if (sync.is_object() && sync.contains("change")) {
int change_type = sync["change"].get<int>();
lsp->incremental_sync = (change_type == 2);
}
}
if (caps.contains("hoverProvider"))
lsp->allow_hover = caps["hoverProvider"].get<bool>();
else
lsp->allow_hover = false;
if (caps.contains("completionProvider"))
lsp->allow_completion = true;
}
lsp->initialized = true;
json initialized = {{"jsonrpc", "2.0"},
{"method", "initialized"},
{"params", json::object()}};
lsp_send(lsp, initialized, nullptr);
};
json init_message = {
{"jsonrpc", "2.0"},
{"method", "initialize"},
{"params",
{{"processId", getpid()},
{"rootUri", "file://" + percent_encode(path_abs("."))},
{"capabilities", client_capabilities}}}};
lsp_send(lsp, init_message, pending);
active_lsps[lsp_id] = lsp;
return lsp;
}
return it->second;
}
void close_lsp(uint8_t lsp_id) {
std::shared_lock active_lsps_lock(active_lsps_mtx);
auto it = active_lsps.find(lsp_id);
if (it == active_lsps.end())
return;
std::shared_ptr<LSPInstance> lsp = it->second;
active_lsps_lock.unlock();
lsp->exited = true;
lsp->initialized = false;
LSPPending *shutdown_pending = new LSPPending();
shutdown_pending->method = "shutdown";
shutdown_pending->callback = [lsp, lsp_id](Editor *, std::string, json) {
json exit = {{"jsonrpc", "2.0"}, {"method", "exit"}};
lsp_send(lsp, exit, nullptr);
};
json shutdown = {{"jsonrpc", "2.0"}, {"method", "shutdown"}};
lsp_send(lsp, shutdown, shutdown_pending);
std::thread t([lsp, lsp_id] {
std::this_thread::sleep_for(100ms);
std::unique_lock active_lsps_lock(active_lsps_mtx);
std::unique_lock lock(lsp->mtx);
if (lsp->pid != -1 && kill(lsp->pid, 0) == 0)
kill(lsp->pid, SIGKILL);
waitpid(lsp->pid, nullptr, 0);
close(lsp->stdin_fd);
close(lsp->stdout_fd);
for (auto &kv : lsp->pending)
delete kv.second;
for (auto &editor : lsp->editors) {
std::unique_lock editor_lock(editor->lsp_mtx);
editor->lsp = nullptr;
}
active_lsps.erase(lsp_id);
});
t.detach();
}
void clean_lsp(std::shared_ptr<LSPInstance> lsp, uint8_t lsp_id) {
for (auto &kv : lsp->pending)
delete kv.second;
lsp->pid = -1;
close(lsp->stdin_fd);
close(lsp->stdout_fd);
for (auto &editor : lsp->editors) {
std::unique_lock editor_lock(editor->lsp_mtx);
editor->lsp = nullptr;
}
active_lsps.erase(lsp_id);
}

170
src/lsp/workers.cc Normal file
View File

@@ -0,0 +1,170 @@
#include "lsp/lsp.h"
std::shared_mutex active_lsps_mtx;
std::unordered_map<uint8_t, std::shared_ptr<LSPInstance>> active_lsps;
void lsp_send(std::shared_ptr<LSPInstance> lsp, json message,
LSPPending *pending) {
if (!lsp || lsp->stdin_fd == -1)
return;
std::unique_lock lock(lsp->mtx);
if (pending) {
message["id"] = lsp->last_id++;
uint32_t id = message["id"].get<uint32_t>();
lsp->pending[id] = pending;
}
lsp->outbox.push(message);
}
static std::optional<json> read_lsp_message(int fd) {
std::string header;
char c;
while (true) {
ssize_t n = read(fd, &c, 1);
if (n <= 0)
return std::nullopt;
header.push_back(c);
if (header.size() >= 4 && header.substr(header.size() - 4) == "\r\n\r\n")
break;
}
size_t pos = header.find("Content-Length:");
if (pos == std::string::npos)
return std::nullopt;
pos += strlen("Content-Length:");
while (pos < header.size() && std::isspace(header[pos]))
pos++;
size_t end = pos;
while (end < header.size() && std::isdigit(header[end]))
end++;
size_t len = std::stoul(header.substr(pos, end - pos));
std::string body(len, '\0');
size_t got = 0;
while (got < len) {
ssize_t n = read(fd, &body[got], len - got);
if (n <= 0)
return std::nullopt;
got += n;
}
return json::parse(body);
}
static Editor *editor_for_uri(std::shared_ptr<LSPInstance> lsp,
std::string uri) {
if (uri.empty())
return nullptr;
for (auto &editor : lsp->editors)
if (editor->uri == uri)
return editor;
return nullptr;
}
void lsp_worker() {
LSPOpenRequest request;
while (lsp_open_queue.pop(request))
add_to_lsp(request.language, request.editor);
std::unique_lock active_lsps_lock(active_lsps_mtx);
for (auto &kv : active_lsps) {
std::shared_ptr<LSPInstance> lsp = kv.second;
std::unique_lock lock(lsp->mtx);
int status;
pid_t res = waitpid(lsp->pid, &status, WNOHANG);
if (res == lsp->pid) {
clean_lsp(lsp, kv.first);
return;
}
if (lsp->initialized) {
std::pair<Language, Editor *> request;
while (lsp->open_queue.pop(request)) {
lock.unlock();
open_editor(lsp, request);
lock.lock();
}
}
while (!lsp->outbox.empty()) {
json message = lsp->outbox.front();
std::string m = message.value("method", "");
if (lsp->exited) {
if (m != "exit" && m != "shutdown") {
lsp->outbox.pop(message);
continue;
}
}
if (!lsp->initialized) {
if (m != "initialize" && m != "exit" && m != "shutdown")
break;
}
lsp->outbox.pop(message);
std::string payload = message.dump();
std::string header =
"Content-Length: " + std::to_string(payload.size()) + "\r\n\r\n";
std::string out = header + payload;
const char *ptr = out.data();
size_t remaining = out.size();
while (remaining > 0) {
int status;
pid_t res = waitpid(lsp->pid, &status, WNOHANG);
if (res == lsp->pid) {
clean_lsp(lsp, kv.first);
return;
}
ssize_t written = write(lsp->stdin_fd, ptr, remaining);
if (written == 0)
break;
else if (written == -1) {
if (errno == EINTR)
continue;
perror("write");
clean_lsp(lsp, kv.first);
return;
} else {
ptr += written;
remaining -= written;
}
}
}
pollfd pfd{lsp->stdout_fd, POLLIN | POLLHUP | POLLERR, 0};
int r = poll(&pfd, 1, 0);
if (r > 0 && pfd.revents & (POLLHUP | POLLERR)) {
clean_lsp(lsp, kv.first);
return;
}
while ((r = poll(&pfd, 1, 0) > 0)) {
if (r > 0 && pfd.revents & (POLLHUP | POLLERR)) {
clean_lsp(lsp, kv.first);
return;
}
auto msg = read_lsp_message(lsp->stdout_fd);
if (!msg)
break;
if (msg->contains("id")) {
uint32_t id = msg->at("id").get<uint32_t>();
auto it = lsp->pending.find(id);
if (it != lsp->pending.end()) {
LSPPending *pend = it->second;
lock.unlock();
if (pend->callback)
pend->callback(pend->editor, pend->method, *msg);
delete pend;
lock.lock();
lsp->pending.erase(it);
}
} else if (msg->contains("method")) {
std::string uri;
if (msg->contains("params")) {
auto &p = (*msg)["params"];
if (p.contains("textDocument") && p["textDocument"].contains("uri"))
uri = p["textDocument"]["uri"].get<std::string>();
else if (p.contains("uri"))
uri = p["uri"].get<std::string>();
}
Editor *ed = editor_for_uri(lsp, uri);
lock.unlock();
if (ed)
editor_lsp_handle(ed, *msg);
else
lsp_handle(lsp, *msg);
lock.lock();
}
}
}
}

View File

@@ -1,12 +1,8 @@
#include "../include/main.h" #include "main.h"
#include "../include/editor.h" #include "editor/editor.h"
#include "../include/lsp.h" #include "io/ui.h"
#include "../include/ts.h" #include "lsp/lsp.h"
#include "../include/ui.h" #include "ts/ts.h"
#include <atomic>
#include <cstdint>
#include <sys/ioctl.h>
#include <thread>
std::atomic<bool> running{true}; std::atomic<bool> running{true};
Queue<KeyEvent> event_queue; Queue<KeyEvent> event_queue;

340
src/ts.cc
View File

@@ -1,340 +0,0 @@
#include "../include/ts.h"
#include "../include/editor.h"
#include "../include/knot.h"
#include "../include/maps.h"
#include <algorithm>
#include <cstdint>
#include <fstream>
#include <string>
#include <unordered_map>
std::unordered_map<std::string, pcre2_code *> regex_cache;
void clear_regex_cache() {
for (auto &kv : regex_cache)
pcre2_code_free(kv.second);
regex_cache.clear();
}
pcre2_code *get_re(const std::string &pattern) {
auto it = regex_cache.find(pattern);
if (it != regex_cache.end())
return it->second;
int errornum;
PCRE2_SIZE erroffset;
pcre2_code *re =
pcre2_compile((PCRE2_SPTR)pattern.c_str(), PCRE2_ZERO_TERMINATED, 0,
&errornum, &erroffset, nullptr);
regex_cache[pattern] = re;
return re;
}
TSQuery *load_query(const char *query_path, TSSetBase *set) {
const TSLanguage *lang = set->language;
std::ifstream file(query_path, std::ios::in | std::ios::binary);
if (!file.is_open())
return nullptr;
std::string highlight_query((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
int errornumber = 0;
PCRE2_SIZE erroroffset = 0;
pcre2_code *re = pcre2_compile(
(PCRE2_SPTR) R"((@[A-Za-z0-9_.]+)|(;; \#[0-9a-fA-F]{6} \#[0-9a-fA-F]{6} [01] [01] [01] \d+)|(;; !(\w+)))",
PCRE2_ZERO_TERMINATED, 0, &errornumber, &erroroffset, nullptr);
if (!re)
return nullptr;
pcre2_match_data *match_data =
pcre2_match_data_create_from_pattern(re, nullptr);
std::map<std::string, int> capture_name_cache;
Highlight *c_hl = nullptr;
Language c_lang = {"unknown", nullptr, 0};
int i = 0;
PCRE2_SIZE offset = 0;
PCRE2_SIZE subject_length = highlight_query.size();
while (offset < subject_length) {
int rc = pcre2_match(re, (PCRE2_SPTR)highlight_query.c_str(),
subject_length, offset, 0, match_data, nullptr);
if (rc <= 0)
break;
PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
std::string mct =
highlight_query.substr(ovector[0], ovector[1] - ovector[0]);
if (!mct.empty() && mct[0] == '@') {
std::string capture_name = mct;
if (!capture_name_cache.count(capture_name)) {
if (c_hl) {
set->query_map[i] = *c_hl;
delete c_hl;
c_hl = nullptr;
}
if (c_lang.fn != nullptr) {
set->injection_map[i] = c_lang;
c_lang = {"unknown", nullptr, 0};
}
capture_name_cache[capture_name] = i;
i++;
}
} else if (mct.substr(0, 4) == ";; #") {
if (c_hl)
delete c_hl;
c_hl = new Highlight();
c_hl->fg = HEX(mct.substr(4, 6));
c_hl->bg = HEX(mct.substr(12, 6));
int bold = std::stoi(mct.substr(19, 1));
int italic = std::stoi(mct.substr(21, 1));
int underline = std::stoi(mct.substr(23, 1));
c_hl->priority = std::stoi(mct.substr(25));
c_hl->flags = (bold ? CF_BOLD : 0) | (italic ? CF_ITALIC : 0) |
(underline ? CF_UNDERLINE : 0);
} else if (mct.substr(0, 4) == ";; !") {
auto it = kLanguages.find(mct.substr(4));
if (it != kLanguages.end())
c_lang = it->second;
else
c_lang = {"unknown", nullptr, 0};
}
offset = ovector[1];
}
if (c_hl)
delete c_hl;
pcre2_match_data_free(match_data);
pcre2_code_free(re);
uint32_t error_offset = 0;
TSQueryError error_type = (TSQueryError)0;
TSQuery *q = ts_query_new(lang, highlight_query.c_str(),
(uint32_t)highlight_query.length(), &error_offset,
&error_type);
if (!q)
log("Failed to create TSQuery at offset %u, error type %d", error_offset,
(int)error_type);
return q;
}
static inline const TSNode *find_capture_node(const TSQueryMatch &match,
uint32_t capture_id) {
for (uint32_t i = 0; i < match.capture_count; i++)
if (match.captures[i].index == capture_id)
return &match.captures[i].node;
return nullptr;
}
static inline std::string node_text(const TSNode &node, Knot *source) {
uint32_t start = ts_node_start_byte(node);
uint32_t end = ts_node_end_byte(node);
char *text = read(source, start, end - start);
std::string final = std::string(text, end - start);
free(text);
return final;
}
static inline bool ts_predicate(TSQuery *query, const TSQueryMatch &match,
Knot *source) {
uint32_t step_count;
const TSQueryPredicateStep *steps =
ts_query_predicates_for_pattern(query, match.pattern_index, &step_count);
if (!steps || step_count != 4)
return true;
if (source->char_count >= (1024 * 64))
return false;
std::string command;
std::string regex_txt;
uint32_t subject_id = 0;
for (uint32_t i = 0; i < step_count; i++) {
const TSQueryPredicateStep *step = &steps[i];
if (step->type == TSQueryPredicateStepTypeDone)
break;
switch (step->type) {
case TSQueryPredicateStepTypeString: {
uint32_t length = 0;
const char *s =
ts_query_string_value_for_id(query, step->value_id, &length);
if (i == 0)
command.assign(s, length);
else
regex_txt.assign(s, length);
break;
}
case TSQueryPredicateStepTypeCapture: {
subject_id = step->value_id;
break;
}
case TSQueryPredicateStepTypeDone:
break;
}
}
const TSNode *node = find_capture_node(match, subject_id);
std::string subject = node_text(*node, source);
pcre2_code *re = get_re(regex_txt);
pcre2_match_data *md = pcre2_match_data_create_from_pattern(re, nullptr);
int rc = pcre2_match(re, (PCRE2_SPTR)subject.c_str(), subject.size(), 0, 0,
md, nullptr);
pcre2_match_data_free(md);
bool ok = (rc >= 0);
return (command == "match?" ? ok : !ok);
}
const char *read_ts(void *payload, uint32_t byte_index, TSPoint,
uint32_t *bytes_read) {
Editor *editor = (Editor *)payload;
if (byte_index >= editor->root->char_count) {
*bytes_read = 0;
return "";
}
return leaf_from_offset(editor->root, byte_index, bytes_read);
}
template <typename T>
static inline T *safe_get(std::map<uint16_t, T> &m, uint16_t key) {
auto it = m.find(key);
if (it == m.end())
return nullptr;
return &it->second;
}
void ts_collect_spans(Editor *editor) {
static int parse_counter = 0;
if (!editor->ts.parser || !editor->root || !editor->ts.query)
return;
const bool injections_enabled = editor->root->char_count < (1024 * 32);
for (auto &inj : editor->ts.injections)
inj.second.ranges.clear();
TSInput tsinput{
.payload = editor,
.read = read_ts,
.encoding = TSInputEncodingUTF8,
.decode = nullptr,
};
TSTree *tree = nullptr;
TSTree *copy = nullptr;
std::unique_lock knot_mtx(editor->knot_mtx);
if (editor->ts.tree)
copy = ts_tree_copy(editor->ts.tree);
knot_mtx.unlock();
std::vector<TSInputEdit> edits;
TSInputEdit edit;
if (copy)
while (editor->edit_queue.pop(edit)) {
edits.push_back(edit);
ts_tree_edit(copy, &edits.back());
}
if (copy && edits.empty() && parse_counter < 64) {
parse_counter++;
ts_tree_delete(copy);
return;
}
parse_counter = 0;
editor->spans.mid_parse = true;
std::shared_lock lock(editor->knot_mtx);
tree = ts_parser_parse(editor->ts.parser, copy, tsinput);
lock.unlock();
if (copy)
ts_tree_delete(copy);
if (editor->ts.tree)
ts_tree_delete(editor->ts.tree);
editor->ts.tree = tree;
copy = ts_tree_copy(tree);
std::vector<Span> new_spans;
new_spans.reserve(4096);
struct PendingRanges {
std::vector<TSRange> ranges;
TSSet *tsset = nullptr;
};
struct WorkItem {
TSSetBase *tsset;
TSTree *tree;
int depth;
TSSet *as_injection;
};
const int kMaxInjectionDepth = 4;
std::vector<WorkItem> work;
work.push_back(
{reinterpret_cast<TSSetBase *>(&editor->ts), copy, 0, nullptr});
auto overlaps = [](const Span &s, const TSRange &r) {
return !(s.end <= r.start_byte || s.start >= r.end_byte);
};
auto remove_overlapping_spans = [&](const std::vector<TSRange> &ranges) {
if (ranges.empty())
return;
new_spans.erase(
std::remove_if(new_spans.begin(), new_spans.end(),
[&](const Span &sp) {
return std::any_of(
ranges.begin(), ranges.end(),
[&](const TSRange &r) { return overlaps(sp, r); });
}),
new_spans.end());
};
while (!work.empty()) {
WorkItem item = work.back();
work.pop_back();
TSQuery *q = item.tsset->query;
if (!q) {
ts_tree_delete(item.tree);
continue;
}
TSQueryCursor *cursor = ts_query_cursor_new();
ts_query_cursor_exec(cursor, q, ts_tree_root_node(item.tree));
std::unordered_map<std::string, PendingRanges> pending_injections;
TSQueryMatch match;
while (ts_query_cursor_next_match(cursor, &match)) {
if (!ts_predicate(q, match, editor->root))
continue;
for (uint32_t i = 0; i < match.capture_count; i++) {
TSQueryCapture cap = match.captures[i];
uint32_t start = ts_node_start_byte(cap.node);
uint32_t end = ts_node_end_byte(cap.node);
if (Highlight *hl = safe_get(item.tsset->query_map, cap.index))
new_spans.push_back({start, end, hl});
if (!injections_enabled)
continue;
if (Language *inj_lang =
safe_get(item.tsset->injection_map, cap.index)) {
auto &pending = pending_injections[inj_lang->name];
TSSet &tsset =
editor->ts.injections.try_emplace(inj_lang->name).first->second;
if (!tsset.parser) {
tsset.lang = inj_lang->name;
tsset.parser = ts_parser_new();
ts_parser_set_language(tsset.parser, inj_lang->fn());
tsset.language = inj_lang->fn();
tsset.query_file =
get_exe_dir() + "/../grammar/" + inj_lang->name + ".scm";
tsset.query = load_query(tsset.query_file.c_str(), &tsset);
}
pending.tsset = &tsset;
pending.ranges.push_back(TSRange{
ts_node_start_point(cap.node),
ts_node_end_point(cap.node),
start,
end,
});
}
}
}
ts_query_cursor_delete(cursor);
if (injections_enabled && item.depth < kMaxInjectionDepth) {
for (auto &[lang_name, pending] : pending_injections) {
TSSet *tsset = pending.tsset;
if (!tsset || pending.ranges.empty() || !tsset->parser || !tsset->query)
continue;
tsset->ranges = std::move(pending.ranges);
remove_overlapping_spans(tsset->ranges);
ts_parser_set_included_ranges(tsset->parser, tsset->ranges.data(),
tsset->ranges.size());
lock.lock();
TSTree *inj_tree = ts_parser_parse(tsset->parser, nullptr, tsinput);
lock.unlock();
work.push_back({reinterpret_cast<TSSetBase *>(tsset), inj_tree,
item.depth + 1, tsset});
}
}
ts_tree_delete(item.tree);
}
std::pair<uint32_t, int64_t> span_edit;
while (editor->spans.edits.pop(span_edit))
apply_edit(new_spans, span_edit.first, span_edit.second);
std::sort(new_spans.begin(), new_spans.end());
std::unique_lock span_mtx(editor->spans.mtx);
editor->spans.mid_parse = false;
editor->spans.spans.swap(new_spans);
}

167
src/ts/ts.cc Normal file
View File

@@ -0,0 +1,167 @@
#include "ts/ts.h"
#include "editor/editor.h"
#include "io/knot.h"
const char *read_ts(void *payload, uint32_t byte_index, TSPoint,
uint32_t *bytes_read) {
Editor *editor = (Editor *)payload;
if (byte_index >= editor->root->char_count) {
*bytes_read = 0;
return "";
}
return leaf_from_offset(editor->root, byte_index, bytes_read);
}
void ts_collect_spans(Editor *editor) {
static int parse_counter = 64;
if (!editor->ts.parser || !editor->root || !editor->ts.query)
return;
const bool injections_enabled = editor->root->char_count < (1024 * 20);
for (auto &inj : editor->ts.injections)
inj.second.ranges.clear();
TSInput tsinput{
.payload = editor,
.read = read_ts,
.encoding = TSInputEncodingUTF8,
.decode = nullptr,
};
std::vector<TSInputEdit> edits;
TSInputEdit edit;
if (!editor->edit_queue.empty()) {
while (editor->edit_queue.pop(edit))
edits.push_back(edit);
if (editor->ts.tree)
for (auto &e : edits)
ts_tree_edit(editor->ts.tree, &e);
for (auto &inj : editor->ts.injections)
if (inj.second.tree)
for (auto &e : edits)
ts_tree_edit(inj.second.tree, &e);
} else if (editor->ts.tree && parse_counter++ < 64) {
return;
}
parse_counter = 0;
std::shared_lock lock(editor->knot_mtx);
editor->spans.mid_parse = true;
TSTree *tree = ts_parser_parse(editor->ts.parser, editor->ts.tree, tsinput);
if (!tree)
return;
if (editor->ts.tree)
ts_tree_delete(editor->ts.tree);
editor->ts.tree = tree;
lock.unlock();
std::vector<Span> new_spans;
new_spans.reserve(4096);
struct PendingRanges {
std::vector<TSRange> ranges;
TSSet *tsset = nullptr;
};
struct WorkItem {
TSSetBase *tsset;
TSTree *tree;
int depth;
};
const int kMaxInjectionDepth = 4;
std::vector<WorkItem> work;
work.push_back(
{reinterpret_cast<TSSetBase *>(&editor->ts), editor->ts.tree, 0});
auto overlaps = [](const Span &s, const TSRange &r) {
return !(s.end <= r.start_byte || s.start >= r.end_byte);
};
auto remove_overlapping_spans = [&](const std::vector<TSRange> &ranges) {
if (ranges.empty())
return;
new_spans.erase(
std::remove_if(new_spans.begin(), new_spans.end(),
[&](const Span &sp) {
return std::any_of(
ranges.begin(), ranges.end(),
[&](const TSRange &r) { return overlaps(sp, r); });
}),
new_spans.end());
};
while (!work.empty()) {
WorkItem item = work.back();
work.pop_back();
TSQuery *q = item.tsset->query;
if (!q)
continue;
TSQueryCursor *cursor = ts_query_cursor_new();
ts_query_cursor_exec(cursor, q, ts_tree_root_node(item.tsset->tree));
std::unordered_map<std::string, PendingRanges> pending_injections;
TSQueryMatch match;
while (ts_query_cursor_next_match(cursor, &match)) {
auto subject_fn = [&](const TSNode *node) -> std::string {
uint32_t start = ts_node_start_byte(*node);
uint32_t end = ts_node_end_byte(*node);
char *text = read(editor->root, start, end - start);
std::string final = std::string(text, end - start);
free(text);
return final;
};
if (!ts_predicate(q, match, subject_fn))
continue;
for (uint32_t i = 0; i < match.capture_count; i++) {
TSQueryCapture cap = match.captures[i];
uint32_t start = ts_node_start_byte(cap.node);
uint32_t end = ts_node_end_byte(cap.node);
if (Highlight *hl = safe_get(item.tsset->query_map, cap.index))
new_spans.push_back({start, end, hl});
if (!injections_enabled)
continue;
if (Language *inj_lang =
safe_get(item.tsset->injection_map, cap.index)) {
auto &pending = pending_injections[inj_lang->name];
TSSet &tsset =
editor->ts.injections.try_emplace(inj_lang->name).first->second;
if (!tsset.parser) {
tsset.lang = inj_lang->name;
tsset.parser = ts_parser_new();
ts_parser_set_language(tsset.parser, inj_lang->fn());
tsset.language = inj_lang->fn();
tsset.query_file =
get_exe_dir() + "/../grammar/" + inj_lang->name + ".scm";
tsset.query = load_query(tsset.query_file.c_str(), &tsset);
}
pending.tsset = &tsset;
pending.ranges.push_back(TSRange{
ts_node_start_point(cap.node),
ts_node_end_point(cap.node),
start,
end,
});
}
}
}
ts_query_cursor_delete(cursor);
if (injections_enabled && item.depth < kMaxInjectionDepth) {
for (auto &[lang_name, pending] : pending_injections) {
TSSet *tsset = pending.tsset;
if (!tsset || pending.ranges.empty() || !tsset->parser || !tsset->query)
continue;
tsset->ranges = std::move(pending.ranges);
remove_overlapping_spans(tsset->ranges);
ts_parser_set_included_ranges(tsset->parser, tsset->ranges.data(),
tsset->ranges.size());
lock.lock();
TSTree *tree = ts_parser_parse(tsset->parser, tsset->tree, tsinput);
if (!tree)
continue;
if (tsset->tree)
ts_tree_delete(tsset->tree);
tsset->tree = tree;
lock.unlock();
work.push_back({reinterpret_cast<TSSetBase *>(tsset), tsset->tree,
item.depth + 1});
}
}
}
lock.lock();
std::pair<uint32_t, int64_t> span_edit;
while (editor->spans.edits.pop(span_edit))
apply_edit(new_spans, span_edit.first, span_edit.second);
std::sort(new_spans.begin(), new_spans.end());
editor->spans.mid_parse = false;
std::unique_lock span_mtx(editor->spans.mtx);
editor->spans.spans.swap(new_spans);
}

159
src/ts/utils.cc Normal file
View File

@@ -0,0 +1,159 @@
#include "config.h"
#include "io/ui.h"
#include "ts/ts.h"
std::unordered_map<std::string, pcre2_code *> regex_cache;
static inline const TSNode *find_capture_node(const TSQueryMatch &match,
uint32_t capture_id) {
for (uint32_t i = 0; i < match.capture_count; i++)
if (match.captures[i].index == capture_id)
return &match.captures[i].node;
return nullptr;
}
void clear_regex_cache() {
for (auto &kv : regex_cache)
pcre2_code_free(kv.second);
regex_cache.clear();
}
pcre2_code *get_re(const std::string &pattern) {
auto it = regex_cache.find(pattern);
if (it != regex_cache.end())
return it->second;
int errornum;
PCRE2_SIZE erroffset;
pcre2_code *re =
pcre2_compile((PCRE2_SPTR)pattern.c_str(), PCRE2_ZERO_TERMINATED, 0,
&errornum, &erroffset, nullptr);
regex_cache[pattern] = re;
return re;
}
TSQuery *load_query(const char *query_path, TSSetBase *set) {
const TSLanguage *lang = set->language;
std::ifstream file(query_path, std::ios::in | std::ios::binary);
if (!file.is_open())
return nullptr;
std::string highlight_query((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
int errornumber = 0;
PCRE2_SIZE erroroffset = 0;
pcre2_code *re = pcre2_compile(
(PCRE2_SPTR) R"((@[A-Za-z0-9_.]+)|(;; \#[0-9a-fA-F]{6} \#[0-9a-fA-F]{6} [01] [01] [01] [01] \d+)|(;; !(\w+)))",
PCRE2_ZERO_TERMINATED, 0, &errornumber, &erroroffset, nullptr);
if (!re)
return nullptr;
pcre2_match_data *match_data =
pcre2_match_data_create_from_pattern(re, nullptr);
std::map<std::string, int> capture_name_cache;
Highlight *c_hl = nullptr;
Language c_lang = {"unknown", nullptr, 0};
int i = 0;
PCRE2_SIZE offset = 0;
PCRE2_SIZE subject_length = highlight_query.size();
while (offset < subject_length) {
int rc = pcre2_match(re, (PCRE2_SPTR)highlight_query.c_str(),
subject_length, offset, 0, match_data, nullptr);
if (rc <= 0)
break;
PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
std::string mct =
highlight_query.substr(ovector[0], ovector[1] - ovector[0]);
if (!mct.empty() && mct[0] == '@') {
std::string capture_name = mct;
if (!capture_name_cache.count(capture_name)) {
if (c_hl) {
set->query_map[i] = *c_hl;
delete c_hl;
c_hl = nullptr;
}
if (c_lang.fn != nullptr) {
set->injection_map[i] = c_lang;
c_lang = {"unknown", nullptr, 0};
}
capture_name_cache[capture_name] = i;
i++;
}
} else if (mct.substr(0, 4) == ";; #") {
if (c_hl)
delete c_hl;
c_hl = new Highlight();
c_hl->fg = HEX(mct.substr(4, 6));
c_hl->bg = HEX(mct.substr(12, 6));
int bold = std::stoi(mct.substr(19, 1));
int italic = std::stoi(mct.substr(21, 1));
int underline = std::stoi(mct.substr(23, 1));
int strike = std::stoi(mct.substr(25, 1));
c_hl->priority = std::stoi(mct.substr(27));
c_hl->flags = (bold ? CF_BOLD : 0) | (italic ? CF_ITALIC : 0) |
(underline ? CF_UNDERLINE : 0) |
(strike ? CF_STRIKETHROUGH : 0);
} else if (mct.substr(0, 4) == ";; !") {
auto it = kLanguages.find(mct.substr(4));
if (it != kLanguages.end())
c_lang = it->second;
else
c_lang = {"unknown", nullptr, 0};
}
offset = ovector[1];
}
if (c_hl)
delete c_hl;
pcre2_match_data_free(match_data);
pcre2_code_free(re);
uint32_t error_offset = 0;
TSQueryError error_type = (TSQueryError)0;
TSQuery *q = ts_query_new(lang, highlight_query.c_str(),
(uint32_t)highlight_query.length(), &error_offset,
&error_type);
if (!q)
log("Failed to create TSQuery at offset %u, error type %d", error_offset,
(int)error_type);
return q;
}
bool ts_predicate(TSQuery *query, const TSQueryMatch &match,
std::function<std::string(const TSNode *)> subject_fn) {
uint32_t step_count;
const TSQueryPredicateStep *steps =
ts_query_predicates_for_pattern(query, match.pattern_index, &step_count);
if (!steps || step_count != 4)
return true;
std::string command;
std::string regex_txt;
uint32_t subject_id = 0;
for (uint32_t i = 0; i < step_count; i++) {
const TSQueryPredicateStep *step = &steps[i];
if (step->type == TSQueryPredicateStepTypeDone)
break;
switch (step->type) {
case TSQueryPredicateStepTypeString: {
uint32_t length = 0;
const char *s =
ts_query_string_value_for_id(query, step->value_id, &length);
if (i == 0)
command.assign(s, length);
else
regex_txt.assign(s, length);
break;
}
case TSQueryPredicateStepTypeCapture: {
subject_id = step->value_id;
break;
}
case TSQueryPredicateStepTypeDone:
break;
}
}
const TSNode *node = find_capture_node(match, subject_id);
pcre2_code *re = get_re(regex_txt);
std::string subject = subject_fn(node);
pcre2_match_data *md = pcre2_match_data_create_from_pattern(re, nullptr);
int rc = pcre2_match(re, (PCRE2_SPTR)subject.c_str(), subject.size(), 0, 0,
md, nullptr);
pcre2_match_data_free(md);
bool ok = (rc >= 0);
return (command == "match?" ? ok : !ok);
}

View File

@@ -1,292 +0,0 @@
extern "C" {
#include "../libs/libgrapheme/grapheme.h"
#include "../libs/unicode_width/unicode_width.h"
}
#include "../include/maps.h"
#include "../include/utils.h"
static std::string percent_encode(const std::string &s) {
static const char *hex = "0123456789ABCDEF";
std::string out;
for (unsigned char c : s) {
if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~' ||
c == '/') {
out.push_back(c);
} else {
out.push_back('%');
out.push_back(hex[c >> 4]);
out.push_back(hex[c & 0xF]);
}
}
return out;
}
std::string path_abs(const std::string &path_str) {
namespace fs = std::filesystem;
fs::path p = fs::weakly_canonical(fs::absolute(fs::path(path_str)));
return p.generic_string();
}
std::string path_to_file_uri(const std::string &path_str) {
return "file://" + percent_encode(path_abs(path_str));
}
uint64_t fnv1a_64(const char *s, size_t len) {
uint64_t hash = 1469598103934665603ull;
for (size_t i = 0; i < len; ++i) {
hash ^= (uint8_t)s[i];
hash *= 1099511628211ull;
}
return hash;
}
char *get_from_clipboard(uint32_t *out_len) {
FILE *pipe = popen("xclip -selection clipboard -o", "r");
if (!pipe) {
*out_len = 0;
return nullptr;
}
size_t capacity = 4096;
size_t length = 0;
char *buffer = (char *)malloc(capacity);
if (!buffer) {
pclose(pipe);
*out_len = 0;
return nullptr;
}
size_t n;
while ((n = fread(buffer + length, 1, capacity - length, pipe)) > 0) {
length += n;
if (length == capacity) {
capacity *= 2;
char *tmp = (char *)realloc(buffer, capacity);
if (!tmp) {
free(buffer);
pclose(pipe);
*out_len = 0;
return nullptr;
}
buffer = tmp;
}
}
pclose(pipe);
char *result = (char *)realloc(buffer, length + 1);
if (result) {
result[length] = '\0';
buffer = result;
} else {
buffer[length] = '\0';
}
*out_len = length;
return buffer;
}
void copy_to_clipboard(const char *text, size_t len) {
FILE *pipe = popen("xclip -selection clipboard", "w");
if (!pipe)
return;
fwrite(text, sizeof(char), len, pipe);
pclose(pipe);
}
int display_width(const char *str, size_t len) {
if (!str || !*str)
return 0;
if (str[0] == '\t')
return 4;
unicode_width_state_t state;
unicode_width_init(&state);
int width = 0;
for (size_t j = 0; j < len; j++) {
unsigned char c = str[j];
if (c < 128) {
int char_width = unicode_width_process(&state, c);
if (char_width > 0)
width += char_width;
} else {
uint_least32_t cp;
size_t bytes = grapheme_decode_utf8(str + j, strlen(str) - j, &cp);
if (bytes > 1) {
int char_width = unicode_width_process(&state, cp);
if (char_width > 0)
width += char_width;
j += bytes - 1;
}
}
}
return width;
}
std::string get_exe_dir() {
char exe_path[PATH_MAX];
ssize_t count = readlink("/proc/self/exe", exe_path, PATH_MAX);
if (count == -1)
return "";
exe_path[count] = '\0';
std::string path(exe_path);
return path.substr(0, path.find_last_of('/'));
}
uint32_t get_visual_col_from_bytes(const char *line, uint32_t len,
uint32_t byte_limit) {
if (!line)
return 0;
uint32_t visual_col = 0;
uint32_t current_byte = 0;
if (len > 0 && line[len - 1] == '\n')
len--;
while (current_byte < byte_limit && current_byte < len) {
uint32_t inc = grapheme_next_character_break_utf8(line + current_byte,
len - current_byte);
if (current_byte + inc > byte_limit)
break;
int w = display_width(line + current_byte, inc);
if (w < 0)
w = 0;
visual_col += (uint32_t)w;
current_byte += inc;
}
return visual_col;
}
uint32_t get_bytes_from_visual_col(const char *line, uint32_t len,
uint32_t target_visual_col) {
if (!line)
return 0;
uint32_t current_byte = 0;
uint32_t visual_col = 0;
if (len > 0 && line[len - 1] == '\n')
len--;
while (current_byte < len && visual_col < target_visual_col) {
uint32_t inc = grapheme_next_character_break_utf8(line + current_byte,
len - current_byte);
int w = display_width(line + current_byte, inc);
if (w < 0)
w = 0;
if (visual_col + (uint32_t)w > target_visual_col)
return current_byte;
visual_col += (uint32_t)w;
current_byte += inc;
}
return current_byte;
}
uint32_t count_clusters(const char *line, size_t len, size_t from, size_t to) {
uint32_t count = 0;
size_t pos = from;
while (pos < to && pos < len) {
size_t next =
pos + grapheme_next_character_break_utf8(line + pos, len - pos);
if (next > to)
break;
pos = next;
count++;
}
return count;
}
void log(const char *fmt, ...) {
FILE *fp = fopen("/tmp/log.txt", "a");
if (!fp)
return;
va_list args;
va_start(args, fmt);
vfprintf(fp, fmt, args);
va_end(args);
fputc('\n', fp);
fclose(fp);
}
char *load_file(const char *path, uint32_t *out_len) {
std::ifstream file(path, std::ios::in | std::ios::binary | std::ios::ate);
if (!file.is_open())
return nullptr;
std::streamsize len = file.tellg();
if (len < 0 || (std::uint32_t)len > 0xFFFFFFFF)
return nullptr;
file.seekg(0, std::ios::beg);
char *buf = (char *)malloc(static_cast<std::uint32_t>(len));
if (!buf)
return nullptr;
if (file.read(buf, len)) {
*out_len = static_cast<uint32_t>(len);
return buf;
} else {
free(buf);
return nullptr;
}
}
static std::string file_extension(const char *filename) {
std::string name(filename);
auto pos = name.find_last_of('.');
if (pos == std::string::npos) {
auto pos2 = name.find_last_of('/');
if (pos2 != std::string::npos)
pos = pos2;
else
return "";
}
std::string ext = name.substr(pos + 1);
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
return ext;
}
char *detect_file_type(const char *filename) {
magic_t magic = magic_open(MAGIC_MIME_TYPE);
if (!magic)
return nullptr;
if (magic_load(magic, nullptr) != 0) {
magic_close(magic);
return nullptr;
}
const char *type = magic_file(magic, filename);
if (!type) {
magic_close(magic);
return nullptr;
}
char *result = strdup(type);
magic_close(magic);
return result;
}
Language language_for_file(const char *filename) {
std::string ext = file_extension(filename);
std::string lang_name;
if (!ext.empty()) {
auto it = kExtToLang.find(ext);
if (it != kExtToLang.end())
return kLanguages.find(it->second)->second;
}
char *mime = detect_file_type(filename);
if (mime) {
std::string mime_type(mime);
free(mime);
auto it = kMimeToLang.find(mime_type);
if (it != kMimeToLang.end())
return kLanguages.find(it->second)->second;
}
return {"unknown", nullptr};
}
int utf8_byte_offset_to_utf16(const char *s, size_t byte_pos) {
int utf16_units = 0;
size_t i = 0;
while (i < byte_pos) {
unsigned char c = s[i];
if ((c & 0x80) == 0x00) {
i += 1;
utf16_units += 1;
} else if ((c & 0xE0) == 0xC0) {
i += 2;
utf16_units += 1;
} else if ((c & 0xF0) == 0xE0) {
i += 3;
utf16_units += 1;
} else {
i += 4;
utf16_units += 2;
}
}
return utf16_units;
}

166
src/utils/system.cc Normal file
View File

@@ -0,0 +1,166 @@
#include "config.h"
#include "utils/utils.h"
void log(const char *fmt, ...) {
FILE *fp = fopen("/tmp/log.txt", "a");
if (!fp)
return;
va_list args;
va_start(args, fmt);
vfprintf(fp, fmt, args);
va_end(args);
fputc('\n', fp);
fclose(fp);
}
std::string path_abs(const std::string &path_str) {
namespace fs = std::filesystem;
fs::path p = fs::weakly_canonical(fs::absolute(fs::path(path_str)));
return p.generic_string();
}
std::string path_to_file_uri(const std::string &path_str) {
return "file://" + percent_encode(path_abs(path_str));
}
std::string get_exe_dir() {
char exe_path[PATH_MAX];
ssize_t count = readlink("/proc/self/exe", exe_path, PATH_MAX);
if (count == -1)
return "";
exe_path[count] = '\0';
std::string path(exe_path);
return path.substr(0, path.find_last_of('/'));
}
char *load_file(const char *path, uint32_t *out_len) {
std::ifstream file(path, std::ios::in | std::ios::binary | std::ios::ate);
if (!file.is_open())
return nullptr;
std::streamsize len = file.tellg();
if (len < 0 || static_cast<uint32_t>(len) > 0xFFFFFFFF)
return nullptr;
file.seekg(0, std::ios::beg);
bool add_newline = false;
if (len > 0) {
file.seekg(-1, std::ios::end);
char last_char;
file.read(&last_char, 1);
if (last_char != '\n')
add_newline = true;
}
file.seekg(0, std::ios::beg);
uint32_t alloc_size = static_cast<uint32_t>(len) + (add_newline ? 1 : 0);
char *buf = (char *)malloc(alloc_size);
if (!buf)
return nullptr;
if (!file.read(buf, len)) {
free(buf);
return nullptr;
}
if (add_newline)
buf[len++] = '\n';
*out_len = static_cast<uint32_t>(len);
return buf;
}
static std::string file_extension(const char *filename) {
std::string name(filename);
auto pos = name.find_last_of('.');
if (pos == std::string::npos) {
auto pos2 = name.find_last_of('/');
if (pos2 != std::string::npos)
pos = pos2;
else
return "";
}
std::string ext = name.substr(pos + 1);
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
return ext;
}
char *detect_file_type(const char *filename) {
magic_t magic = magic_open(MAGIC_MIME_TYPE);
if (!magic)
return nullptr;
if (magic_load(magic, nullptr) != 0) {
magic_close(magic);
return nullptr;
}
const char *type = magic_file(magic, filename);
if (!type) {
magic_close(magic);
return nullptr;
}
char *result = strdup(type);
magic_close(magic);
return result;
}
Language language_for_file(const char *filename) {
std::string ext = file_extension(filename);
std::string lang_name;
if (!ext.empty()) {
auto it = kExtToLang.find(ext);
if (it != kExtToLang.end())
return kLanguages.find(it->second)->second;
}
char *mime = detect_file_type(filename);
if (mime) {
std::string mime_type(mime);
free(mime);
auto it = kMimeToLang.find(mime_type);
if (it != kMimeToLang.end())
return kLanguages.find(it->second)->second;
}
return {"unknown", nullptr};
}
char *get_from_clipboard(uint32_t *out_len) {
FILE *pipe = popen("xclip -selection clipboard -o", "r");
if (!pipe) {
*out_len = 0;
return nullptr;
}
size_t capacity = 4096;
size_t length = 0;
char *buffer = (char *)malloc(capacity);
if (!buffer) {
pclose(pipe);
*out_len = 0;
return nullptr;
}
size_t n;
while ((n = fread(buffer + length, 1, capacity - length, pipe)) > 0) {
length += n;
if (length == capacity) {
capacity *= 2;
char *tmp = (char *)realloc(buffer, capacity);
if (!tmp) {
free(buffer);
pclose(pipe);
*out_len = 0;
return nullptr;
}
buffer = tmp;
}
}
pclose(pipe);
char *result = (char *)realloc(buffer, length + 1);
if (result) {
result[length] = '\0';
buffer = result;
} else {
buffer[length] = '\0';
}
*out_len = length;
return buffer;
}
void copy_to_clipboard(const char *text, size_t len) {
FILE *pipe = popen("xclip -selection clipboard", "w");
if (!pipe)
return;
fwrite(text, sizeof(char), len, pipe);
pclose(pipe);
}

105
src/utils/text.cc Normal file
View File

@@ -0,0 +1,105 @@
#include "utils/utils.h"
std::string percent_decode(const std::string &s) {
std::string out;
out.reserve(s.size());
for (size_t i = 0; i < s.size(); ++i) {
if (s[i] == '%' && i + 2 < s.size() && std::isxdigit(s[i + 1]) &&
std::isxdigit(s[i + 2])) {
auto hex = [](char c) -> int {
if ('0' <= c && c <= '9')
return c - '0';
if ('a' <= c && c <= 'f')
return c - 'a' + 10;
if ('A' <= c && c <= 'F')
return c - 'A' + 10;
return 0;
};
char decoded = (hex(s[i + 1]) << 4) | hex(s[i + 2]);
out.push_back(decoded);
i += 2;
} else {
out.push_back(s[i]);
}
}
return out;
}
std::string percent_encode(const std::string &s) {
static const char *hex = "0123456789ABCDEF";
std::string out;
out.reserve(s.size() * 3);
for (unsigned char c : s) {
if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~' ||
c == '/') {
out.push_back(c);
} else {
out.push_back('%');
out.push_back(hex[c >> 4]);
out.push_back(hex[c & 0xF]);
}
}
return out;
}
std::string trim(const std::string &s) {
size_t start = s.find_first_not_of(" \t\n\r");
if (start == std::string::npos)
return "";
size_t end = s.find_last_not_of(" \t\n\r");
return s.substr(start, end - start + 1);
}
std::string clean_text(const std::string &input) {
std::string result = input;
static const std::unordered_map<std::string, std::string> entities = {
{"&nbsp;", " "}, {"&lt;", "<"}, {"&gt;", ">"},
{"&amp;", "&"}, {"&quot;", "\""}, {"&apos;", "'"}};
for (const auto &e : entities) {
size_t pos = 0;
while ((pos = result.find(e.first, pos)) != std::string::npos) {
result.replace(pos, e.first.length(), e.second);
pos += e.second.length();
}
}
int errorcode;
PCRE2_SIZE erroroffset;
pcre2_code *re =
pcre2_compile((PCRE2_SPTR) "(\n\\s*)+", PCRE2_ZERO_TERMINATED, 0,
&errorcode, &erroroffset, nullptr);
if (!re)
return result;
pcre2_match_data *match_data =
pcre2_match_data_create_from_pattern(re, nullptr);
PCRE2_SIZE offset = 0;
std::string clean;
while (offset < result.size()) {
int rc = pcre2_match(re, (PCRE2_SPTR)result.c_str(), result.size(), offset,
0, match_data, nullptr);
if (rc < 0) {
clean += result.substr(offset);
break;
}
PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
clean += result.substr(offset, ovector[0] - offset) + "\n";
offset = ovector[1];
}
pcre2_match_data_free(match_data);
pcre2_code_free(re);
std::string final_str;
size_t start = 0;
while (start < clean.size()) {
size_t end = clean.find('\n', start);
if (end == std::string::npos)
end = clean.size();
std::string line = clean.substr(start, end - start);
size_t first = line.find_first_not_of(" \t\r");
size_t last = line.find_last_not_of(" \t\r");
if (first != std::string::npos)
final_str += line.substr(first, last - first + 1) + "\n";
start = end + 1;
}
if (!final_str.empty() && final_str.back() == '\n')
final_str.pop_back();
return final_str;
}

109
src/utils/unicode.cc Normal file
View File

@@ -0,0 +1,109 @@
#include "utils/utils.h"
int display_width(const char *str, size_t len) {
if (!str || !*str)
return 0;
if (str[0] == '\t')
return 4;
unicode_width_state_t state;
unicode_width_init(&state);
int width = 0;
for (size_t j = 0; j < len; j++) {
unsigned char c = str[j];
if (c < 128) {
int char_width = unicode_width_process(&state, c);
if (char_width > 0)
width += char_width;
} else {
uint_least32_t cp;
size_t bytes = grapheme_decode_utf8(str + j, strlen(str) - j, &cp);
if (bytes > 1) {
int char_width = unicode_width_process(&state, cp);
if (char_width > 0)
width += char_width;
j += bytes - 1;
}
}
}
return width;
}
uint32_t get_visual_col_from_bytes(const char *line, uint32_t len,
uint32_t byte_limit) {
if (!line)
return 0;
uint32_t visual_col = 0;
uint32_t current_byte = 0;
if (len > 0 && line[len - 1] == '\n')
len--;
while (current_byte < byte_limit && current_byte < len) {
uint32_t inc = grapheme_next_character_break_utf8(line + current_byte,
len - current_byte);
if (current_byte + inc > byte_limit)
break;
int w = display_width(line + current_byte, inc);
if (w < 0)
w = 0;
visual_col += (uint32_t)w;
current_byte += inc;
}
return visual_col;
}
uint32_t get_bytes_from_visual_col(const char *line, uint32_t len,
uint32_t target_visual_col) {
if (!line)
return 0;
uint32_t current_byte = 0;
uint32_t visual_col = 0;
if (len > 0 && line[len - 1] == '\n')
len--;
while (current_byte < len && visual_col < target_visual_col) {
uint32_t inc = grapheme_next_character_break_utf8(line + current_byte,
len - current_byte);
int w = display_width(line + current_byte, inc);
if (w < 0)
w = 0;
if (visual_col + (uint32_t)w > target_visual_col)
return current_byte;
visual_col += (uint32_t)w;
current_byte += inc;
}
return current_byte;
}
uint32_t count_clusters(const char *line, size_t len, size_t from, size_t to) {
uint32_t count = 0;
size_t pos = from;
while (pos < to && pos < len) {
size_t next =
pos + grapheme_next_character_break_utf8(line + pos, len - pos);
if (next > to)
break;
pos = next;
count++;
}
return count;
}
int utf8_byte_offset_to_utf16(const char *s, size_t byte_pos) {
int utf16_units = 0;
size_t i = 0;
while (i < byte_pos) {
unsigned char c = s[i];
if ((c & 0x80) == 0x00) {
i += 1;
utf16_units += 1;
} else if ((c & 0xE0) == 0xC0) {
i += 2;
utf16_units += 1;
} else if ((c & 0xF0) == 0xE0) {
i += 3;
utf16_units += 1;
} else {
i += 4;
utf16_units += 2;
}
}
return utf16_units;
}