Add lsp warnings and updates support (and other minor fixes)
This commit is contained in:
@@ -19,7 +19,7 @@ A TUI IDE.
|
|||||||
- `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 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)
|
||||||
|
|||||||
613
grammar/h.scm
Normal file
613
grammar/h.scm
Normal file
@@ -0,0 +1,613 @@
|
|||||||
|
;; #ffffff #000000 0 0 0 1
|
||||||
|
((identifier) @variable
|
||||||
|
(#set! priority 95))
|
||||||
|
|
||||||
|
(preproc_def
|
||||||
|
(preproc_arg) @variable)
|
||||||
|
|
||||||
|
;; #fbb152 #000000 0 0 0 1
|
||||||
|
[
|
||||||
|
"default"
|
||||||
|
"goto"
|
||||||
|
"asm"
|
||||||
|
"__asm__"
|
||||||
|
] @keyword
|
||||||
|
|
||||||
|
[
|
||||||
|
"enum"
|
||||||
|
"struct"
|
||||||
|
"union"
|
||||||
|
"typedef"
|
||||||
|
] @keyword.type
|
||||||
|
|
||||||
|
[
|
||||||
|
"sizeof"
|
||||||
|
"offsetof"
|
||||||
|
] @keyword.operator
|
||||||
|
|
||||||
|
(alignof_expression
|
||||||
|
.
|
||||||
|
_ @keyword.operator)
|
||||||
|
|
||||||
|
;; #fbb152 #000000 0 0 0 1
|
||||||
|
"return" @keyword.return
|
||||||
|
|
||||||
|
;; #fbb152 #000000 0 0 0 1
|
||||||
|
[
|
||||||
|
"while"
|
||||||
|
"for"
|
||||||
|
"do"
|
||||||
|
"continue"
|
||||||
|
"break"
|
||||||
|
] @keyword.repeat
|
||||||
|
|
||||||
|
;; #fbb152 #000000 0 0 0 1
|
||||||
|
[
|
||||||
|
"if"
|
||||||
|
"else"
|
||||||
|
"case"
|
||||||
|
"switch"
|
||||||
|
] @keyword.conditional
|
||||||
|
|
||||||
|
;; #fbb152 #000000 0 0 0 1
|
||||||
|
[
|
||||||
|
"#if"
|
||||||
|
"#ifdef"
|
||||||
|
"#ifndef"
|
||||||
|
"#else"
|
||||||
|
"#elif"
|
||||||
|
"#endif"
|
||||||
|
"#elifdef"
|
||||||
|
"#elifndef"
|
||||||
|
(preproc_directive)
|
||||||
|
] @keyword.directive
|
||||||
|
|
||||||
|
;; #fbb152 #000000 0 0 0 1
|
||||||
|
"#define" @keyword.directive.define
|
||||||
|
|
||||||
|
;; #fbb152 #000000 0 0 0 1
|
||||||
|
"#include" @keyword.import
|
||||||
|
|
||||||
|
;; #bd9ae6 #000000 0 0 0 1
|
||||||
|
[
|
||||||
|
";"
|
||||||
|
":"
|
||||||
|
","
|
||||||
|
"."
|
||||||
|
"::"
|
||||||
|
] @punctuation.delimiter
|
||||||
|
|
||||||
|
;; #e6a24c #000000 0 0 0 2
|
||||||
|
"..." @punctuation.special
|
||||||
|
|
||||||
|
;; #bd9ae6 #000000 0 0 0 1
|
||||||
|
[
|
||||||
|
"("
|
||||||
|
")"
|
||||||
|
"["
|
||||||
|
"]"
|
||||||
|
"{"
|
||||||
|
"}"
|
||||||
|
] @punctuation.bracket
|
||||||
|
|
||||||
|
;; #ffffff #000000 0 0 0 1
|
||||||
|
[
|
||||||
|
"="
|
||||||
|
"-"
|
||||||
|
"*"
|
||||||
|
"/"
|
||||||
|
"+"
|
||||||
|
"%"
|
||||||
|
"~"
|
||||||
|
"|"
|
||||||
|
"&"
|
||||||
|
"^"
|
||||||
|
"<<"
|
||||||
|
">>"
|
||||||
|
"->"
|
||||||
|
"<"
|
||||||
|
"<="
|
||||||
|
">="
|
||||||
|
">"
|
||||||
|
"=="
|
||||||
|
"!="
|
||||||
|
"!"
|
||||||
|
"&&"
|
||||||
|
"||"
|
||||||
|
"-="
|
||||||
|
"+="
|
||||||
|
"*="
|
||||||
|
"/="
|
||||||
|
"%="
|
||||||
|
"|="
|
||||||
|
"&="
|
||||||
|
"^="
|
||||||
|
">>="
|
||||||
|
"<<="
|
||||||
|
"--"
|
||||||
|
"++"
|
||||||
|
] @operator
|
||||||
|
|
||||||
|
;; #ffffff #000000 0 0 0 1
|
||||||
|
(comma_expression
|
||||||
|
"," @operator)
|
||||||
|
|
||||||
|
;; #51eeba #000000 0 0 0 1
|
||||||
|
[
|
||||||
|
(true)
|
||||||
|
(false)
|
||||||
|
] @boolean
|
||||||
|
|
||||||
|
;; #fbb152 #000000 0 0 0 1
|
||||||
|
(conditional_expression
|
||||||
|
[
|
||||||
|
"?"
|
||||||
|
":"
|
||||||
|
] @keyword.conditional.ternary)
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 1
|
||||||
|
(string_literal) @string
|
||||||
|
|
||||||
|
(system_lib_string) @string
|
||||||
|
|
||||||
|
;; #e6a24c #000000 0 0 0 2
|
||||||
|
(escape_sequence) @string.escape
|
||||||
|
|
||||||
|
;; #ebda8c #000000 0 0 0 1
|
||||||
|
(null) @constant.builtin
|
||||||
|
|
||||||
|
;; #ebda8c #000000 0 0 0 1
|
||||||
|
(number_literal) @number
|
||||||
|
|
||||||
|
;; #ebda8c #000000 0 0 0 1
|
||||||
|
(char_literal) @character
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 1
|
||||||
|
(preproc_defined) @function.macro
|
||||||
|
|
||||||
|
;; #ffffff #000000 0 0 0 1
|
||||||
|
((field_expression
|
||||||
|
(field_identifier) @property) @_parent)
|
||||||
|
|
||||||
|
(field_designator) @property
|
||||||
|
|
||||||
|
((field_identifier) @property)
|
||||||
|
|
||||||
|
;; #fbb152 #000000 0 0 0 1
|
||||||
|
(statement_identifier) @label
|
||||||
|
|
||||||
|
(declaration
|
||||||
|
type: (type_identifier) @_type
|
||||||
|
declarator: (identifier) @label
|
||||||
|
(#match? @_type "^__label__$"))
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 1
|
||||||
|
[
|
||||||
|
(type_identifier)
|
||||||
|
(type_descriptor)
|
||||||
|
] @type
|
||||||
|
|
||||||
|
;; #fbb152 #000000 0 0 0 1
|
||||||
|
(storage_class_specifier) @keyword.modifier
|
||||||
|
|
||||||
|
[
|
||||||
|
(type_qualifier)
|
||||||
|
(gnu_asm_qualifier)
|
||||||
|
"__extension__"
|
||||||
|
] @keyword.modifier
|
||||||
|
|
||||||
|
;; #fbb152 #000000 0 0 0 1
|
||||||
|
(linkage_specification
|
||||||
|
"extern" @keyword.modifier)
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 1
|
||||||
|
(type_definition
|
||||||
|
declarator: (type_identifier) @type.definition)
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 1
|
||||||
|
(primitive_type) @type.builtin
|
||||||
|
|
||||||
|
(sized_type_specifier
|
||||||
|
_ @type.builtin
|
||||||
|
type: _?)
|
||||||
|
|
||||||
|
;; #ebda8c #000000 0 0 0 1
|
||||||
|
((identifier) @constant
|
||||||
|
(#match? @constant "^[A-Z][A-Z0-9_]+$"))
|
||||||
|
|
||||||
|
(preproc_def
|
||||||
|
(preproc_arg) @constant
|
||||||
|
(#match? @constant "^[A-Z][A-Z0-9_]+$"))
|
||||||
|
|
||||||
|
(enumerator
|
||||||
|
name: (identifier) @constant)
|
||||||
|
|
||||||
|
(case_statement
|
||||||
|
value: (identifier) @constant)
|
||||||
|
|
||||||
|
;; #ebda8c #000000 0 0 0 1
|
||||||
|
((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__)$"))
|
||||||
|
|
||||||
|
(preproc_def
|
||||||
|
(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__)$"))
|
||||||
|
|
||||||
|
;; #ffffff #000000 0 0 0 1
|
||||||
|
(attribute_specifier
|
||||||
|
(argument_list
|
||||||
|
(identifier) @variable.builtin))
|
||||||
|
|
||||||
|
(attribute_specifier
|
||||||
|
(argument_list
|
||||||
|
(call_expression
|
||||||
|
function: (identifier) @variable.builtin)))
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 1
|
||||||
|
((call_expression
|
||||||
|
function: (identifier) @function.builtin)
|
||||||
|
(#match? @function.builtin "^__builtin_"))
|
||||||
|
|
||||||
|
((call_expression
|
||||||
|
function: (identifier) @function.builtin))
|
||||||
|
|
||||||
|
;; #ebda8c #000000 0 0 0 1
|
||||||
|
(preproc_def
|
||||||
|
name: (_) @constant.macro)
|
||||||
|
|
||||||
|
(preproc_call
|
||||||
|
directive: (preproc_directive) @_u
|
||||||
|
argument: (_) @constant.macro
|
||||||
|
(#match? @_u "^#undef$"))
|
||||||
|
|
||||||
|
(preproc_ifdef
|
||||||
|
name: (identifier) @constant.macro)
|
||||||
|
|
||||||
|
(preproc_elifdef
|
||||||
|
name: (identifier) @constant.macro)
|
||||||
|
|
||||||
|
(preproc_defined
|
||||||
|
(identifier) @constant.macro)
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 3
|
||||||
|
(call_expression
|
||||||
|
function: (identifier) @function.call)
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
function: (field_expression
|
||||||
|
field: (field_identifier) @function.call))
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 3
|
||||||
|
(function_declarator
|
||||||
|
declarator: (identifier) @function)
|
||||||
|
|
||||||
|
(function_declarator
|
||||||
|
declarator: (parenthesized_declarator
|
||||||
|
(pointer_declarator
|
||||||
|
declarator: (field_identifier) @function)))
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 3
|
||||||
|
(preproc_function_def
|
||||||
|
name: (identifier) @function.macro)
|
||||||
|
|
||||||
|
;; #AAAAAA #000000 0 1 0 1
|
||||||
|
(comment) @comment @spell
|
||||||
|
|
||||||
|
;; #AAAAAA #000000 0 1 0 1
|
||||||
|
((comment) @comment.documentation
|
||||||
|
(#match? @comment.documentation "^/[*][*][^*].*[*]/$"))
|
||||||
|
|
||||||
|
;; #ffffff #000000 0 0 0 1
|
||||||
|
(parameter_declaration
|
||||||
|
declarator: (identifier) @variable.parameter)
|
||||||
|
|
||||||
|
(parameter_declaration
|
||||||
|
declarator: (array_declarator) @variable.parameter)
|
||||||
|
|
||||||
|
(parameter_declaration
|
||||||
|
declarator: (pointer_declarator) @variable.parameter)
|
||||||
|
|
||||||
|
(preproc_params
|
||||||
|
(identifier) @variable.parameter)
|
||||||
|
|
||||||
|
;; #fbb152 #000000 0 0 0 1
|
||||||
|
[
|
||||||
|
"__attribute__"
|
||||||
|
"__declspec"
|
||||||
|
"__based"
|
||||||
|
"__cdecl"
|
||||||
|
"__clrcall"
|
||||||
|
"__stdcall"
|
||||||
|
"__fastcall"
|
||||||
|
"__thiscall"
|
||||||
|
"__vectorcall"
|
||||||
|
(ms_pointer_modifier)
|
||||||
|
(attribute_declaration)
|
||||||
|
] @attribute
|
||||||
|
|
||||||
|
;; #ffffff #000000 0 0 0 1
|
||||||
|
((identifier) @variable.member
|
||||||
|
(#match? @variable.member "^m_.*$"))
|
||||||
|
|
||||||
|
(parameter_declaration
|
||||||
|
declarator: (reference_declarator) @variable.parameter)
|
||||||
|
|
||||||
|
(variadic_parameter_declaration
|
||||||
|
declarator: (variadic_declarator
|
||||||
|
(_) @variable.parameter))
|
||||||
|
|
||||||
|
(optional_parameter_declaration
|
||||||
|
declarator: (_) @variable.parameter)
|
||||||
|
|
||||||
|
;; #ffffff #000000 0 0 0 1
|
||||||
|
((field_expression
|
||||||
|
(field_identifier) @function.method) @_parent)
|
||||||
|
|
||||||
|
(field_declaration
|
||||||
|
(field_identifier) @variable.member)
|
||||||
|
|
||||||
|
(field_initializer
|
||||||
|
(field_identifier) @property)
|
||||||
|
|
||||||
|
(function_declarator
|
||||||
|
declarator: (field_identifier) @function.method)
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 3
|
||||||
|
(concept_definition
|
||||||
|
name: (identifier) @type.definition)
|
||||||
|
|
||||||
|
(alias_declaration
|
||||||
|
name: (type_identifier) @type.definition)
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 1
|
||||||
|
(auto) @type.builtin
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 1
|
||||||
|
(namespace_identifier) @module
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 1
|
||||||
|
((namespace_identifier) @type
|
||||||
|
(#match? @type "^[A-Z]"))
|
||||||
|
|
||||||
|
;; #ebda8c #000000 0 0 0 1
|
||||||
|
(case_statement
|
||||||
|
value: (qualified_identifier
|
||||||
|
(identifier) @constant))
|
||||||
|
|
||||||
|
;; #fbb152 #000000 0 0 0 1
|
||||||
|
(using_declaration
|
||||||
|
.
|
||||||
|
"using"
|
||||||
|
.
|
||||||
|
"namespace"
|
||||||
|
.
|
||||||
|
[
|
||||||
|
(qualified_identifier)
|
||||||
|
(identifier)
|
||||||
|
] @module)
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 3
|
||||||
|
(destructor_name
|
||||||
|
(identifier) @function.method)
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 3
|
||||||
|
(function_declarator
|
||||||
|
(qualified_identifier
|
||||||
|
(identifier) @function))
|
||||||
|
|
||||||
|
(function_declarator
|
||||||
|
(qualified_identifier
|
||||||
|
(qualified_identifier
|
||||||
|
(identifier) @function)))
|
||||||
|
|
||||||
|
(function_declarator
|
||||||
|
(qualified_identifier
|
||||||
|
(qualified_identifier
|
||||||
|
(qualified_identifier
|
||||||
|
(identifier) @function))))
|
||||||
|
|
||||||
|
((qualified_identifier
|
||||||
|
(qualified_identifier
|
||||||
|
(qualified_identifier
|
||||||
|
(qualified_identifier
|
||||||
|
(identifier) @function)))) @_parent)
|
||||||
|
|
||||||
|
(function_declarator
|
||||||
|
(template_function
|
||||||
|
(identifier) @function))
|
||||||
|
|
||||||
|
(operator_name) @function
|
||||||
|
|
||||||
|
"operator" @function
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 3
|
||||||
|
"static_assert" @function.builtin
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 3
|
||||||
|
(call_expression
|
||||||
|
(qualified_identifier
|
||||||
|
(identifier) @function.call))
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
(qualified_identifier
|
||||||
|
(qualified_identifier
|
||||||
|
(identifier) @function.call)))
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
(qualified_identifier
|
||||||
|
(qualified_identifier
|
||||||
|
(qualified_identifier
|
||||||
|
(identifier) @function.call))))
|
||||||
|
|
||||||
|
((qualified_identifier
|
||||||
|
(qualified_identifier
|
||||||
|
(qualified_identifier
|
||||||
|
(qualified_identifier
|
||||||
|
(identifier) @function.call)))) @_parent)
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
(template_function
|
||||||
|
(identifier) @function.call))
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
(qualified_identifier
|
||||||
|
(template_function
|
||||||
|
(identifier) @function.call)))
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
(qualified_identifier
|
||||||
|
(qualified_identifier
|
||||||
|
(template_function
|
||||||
|
(identifier) @function.call))))
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
(qualified_identifier
|
||||||
|
(qualified_identifier
|
||||||
|
(qualified_identifier
|
||||||
|
(template_function
|
||||||
|
(identifier) @function.call)))))
|
||||||
|
|
||||||
|
((qualified_identifier
|
||||||
|
(qualified_identifier
|
||||||
|
(qualified_identifier
|
||||||
|
(qualified_identifier
|
||||||
|
(template_function
|
||||||
|
(identifier) @function.call))))) @_parent)
|
||||||
|
|
||||||
|
(function_declarator
|
||||||
|
(template_method
|
||||||
|
(field_identifier) @function.method))
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 3
|
||||||
|
(call_expression
|
||||||
|
(field_expression
|
||||||
|
(field_identifier) @function.method.call))
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
(field_expression
|
||||||
|
(template_method
|
||||||
|
(field_identifier) @function.method.call)))
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 3
|
||||||
|
((function_declarator
|
||||||
|
(qualified_identifier
|
||||||
|
(identifier) @constructor))
|
||||||
|
(#match? @constructor "^[A-Z]"))
|
||||||
|
|
||||||
|
((call_expression
|
||||||
|
function: (identifier) @constructor)
|
||||||
|
(#match? @constructor "^[A-Z]"))
|
||||||
|
|
||||||
|
((call_expression
|
||||||
|
function: (qualified_identifier
|
||||||
|
name: (identifier) @constructor))
|
||||||
|
(#match? @constructor "^[A-Z]"))
|
||||||
|
|
||||||
|
((call_expression
|
||||||
|
function: (field_expression
|
||||||
|
field: (field_identifier) @constructor))
|
||||||
|
(#match? @constructor "^[A-Z]"))
|
||||||
|
|
||||||
|
((field_initializer
|
||||||
|
(field_identifier) @constructor
|
||||||
|
(argument_list))
|
||||||
|
(#match? @constructor "^[A-Z]"))
|
||||||
|
|
||||||
|
;; #ffffff #000000 0 0 0 1
|
||||||
|
(this) @variable.builtin
|
||||||
|
|
||||||
|
;; #ebda8c #000000 0 0 0 1
|
||||||
|
(null
|
||||||
|
"nullptr" @constant.builtin)
|
||||||
|
|
||||||
|
;; #51eeba #000000 0 0 0 2
|
||||||
|
(true) @boolean_true
|
||||||
|
|
||||||
|
;; #ee513a #000000 0 0 0 2
|
||||||
|
(false) @boolean_false
|
||||||
|
|
||||||
|
;; #aad84c #000000 0 0 0 1
|
||||||
|
(raw_string_literal) @string
|
||||||
|
|
||||||
|
;; #fbb152 #000000 0 0 0 1
|
||||||
|
[
|
||||||
|
"try"
|
||||||
|
"catch"
|
||||||
|
"noexcept"
|
||||||
|
"throw"
|
||||||
|
] @keyword.exception
|
||||||
|
|
||||||
|
;; #fbb152 #000000 0 0 0 1
|
||||||
|
[
|
||||||
|
"decltype"
|
||||||
|
"explicit"
|
||||||
|
"friend"
|
||||||
|
"override"
|
||||||
|
"using"
|
||||||
|
"requires"
|
||||||
|
"constexpr"
|
||||||
|
] @keyword
|
||||||
|
|
||||||
|
;; #fbb152 #000000 0 0 0 1
|
||||||
|
[
|
||||||
|
"class"
|
||||||
|
"namespace"
|
||||||
|
"template"
|
||||||
|
"typename"
|
||||||
|
"concept"
|
||||||
|
] @keyword.type
|
||||||
|
|
||||||
|
;; #fbb152 #000000 0 0 0 1
|
||||||
|
[
|
||||||
|
"co_await"
|
||||||
|
"co_yield"
|
||||||
|
"co_return"
|
||||||
|
] @keyword.coroutine
|
||||||
|
|
||||||
|
;; #fbb152 #000000 0 0 0 1
|
||||||
|
[
|
||||||
|
"public"
|
||||||
|
"private"
|
||||||
|
"protected"
|
||||||
|
"final"
|
||||||
|
"virtual"
|
||||||
|
] @keyword.modifier
|
||||||
|
|
||||||
|
;; #fbb152 #000000 0 0 0 1
|
||||||
|
[
|
||||||
|
"new"
|
||||||
|
"delete"
|
||||||
|
"xor"
|
||||||
|
"bitand"
|
||||||
|
"bitor"
|
||||||
|
"compl"
|
||||||
|
"not"
|
||||||
|
"xor_eq"
|
||||||
|
"and_eq"
|
||||||
|
"or_eq"
|
||||||
|
"not_eq"
|
||||||
|
"and"
|
||||||
|
"or"
|
||||||
|
] @keyword.operator
|
||||||
|
|
||||||
|
;; #ffffff #000000 0 0 0 1
|
||||||
|
"<=>" @operator
|
||||||
|
|
||||||
|
;; #bd9ae6 #000000 0 0 0 1
|
||||||
|
"::" @punctuation.delimiter
|
||||||
|
|
||||||
|
;; #bd9ae6 #000000 0 0 0 1
|
||||||
|
(template_argument_list
|
||||||
|
[
|
||||||
|
"<"
|
||||||
|
">"
|
||||||
|
] @punctuation.bracket)
|
||||||
|
|
||||||
|
(template_parameter_list
|
||||||
|
[
|
||||||
|
"<"
|
||||||
|
">"
|
||||||
|
] @punctuation.bracket)
|
||||||
|
|
||||||
|
;; #ffffff #000000 0 0 0 1
|
||||||
|
(literal_suffix) @operator
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "./utils.h"
|
#include "./utils.h"
|
||||||
#include "ts_def.h"
|
#include "ts_def.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <shared_mutex>
|
||||||
|
|
||||||
#define CHAR 0
|
#define CHAR 0
|
||||||
#define WORD 1
|
#define WORD 1
|
||||||
@@ -95,16 +96,14 @@ struct SpanCursor {
|
|||||||
|
|
||||||
struct VHint {
|
struct VHint {
|
||||||
Coord pos;
|
Coord pos;
|
||||||
char *text; // Can only be a single line with ascii only
|
std::string hint;
|
||||||
uint32_t len;
|
|
||||||
|
|
||||||
bool operator<(const VHint &other) const { return pos < other.pos; }
|
bool operator<(const VHint &other) const { return pos < other.pos; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VWarn {
|
struct VWarn {
|
||||||
uint32_t line;
|
uint32_t line;
|
||||||
char *text; // Can only be a single line
|
std::string text;
|
||||||
uint32_t len;
|
|
||||||
int8_t type; // For hl
|
int8_t type; // For hl
|
||||||
|
|
||||||
bool operator<(const VWarn &other) const { return line < other.line; }
|
bool operator<(const VWarn &other) const { return line < other.line; }
|
||||||
@@ -158,11 +157,13 @@ struct Editor {
|
|||||||
Spans def_spans;
|
Spans def_spans;
|
||||||
uint32_t hooks[94];
|
uint32_t hooks[94];
|
||||||
bool jumper_set;
|
bool jumper_set;
|
||||||
|
std::shared_mutex v_mtx;
|
||||||
std::vector<VHint> hints;
|
std::vector<VHint> hints;
|
||||||
std::vector<VWarn> warnings;
|
std::vector<VWarn> warnings;
|
||||||
VAI ai;
|
VAI ai;
|
||||||
std::shared_mutex lsp_mtx;
|
std::shared_mutex lsp_mtx;
|
||||||
struct LSPInstance *lsp;
|
struct LSPInstance *lsp;
|
||||||
|
int lsp_version = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const Fold *fold_for_line(const std::vector<Fold> &folds,
|
inline const Fold *fold_for_line(const std::vector<Fold> &folds,
|
||||||
@@ -262,6 +263,6 @@ void apply_line_deletion(Editor *editor, uint32_t removal_start,
|
|||||||
uint32_t leading_indent(const char *line, uint32_t len);
|
uint32_t leading_indent(const char *line, uint32_t len);
|
||||||
uint32_t get_indent(Editor *editor, Coord cursor);
|
uint32_t get_indent(Editor *editor, Coord cursor);
|
||||||
bool closing_after_cursor(const char *line, uint32_t len, uint32_t col);
|
bool closing_after_cursor(const char *line, uint32_t len, uint32_t col);
|
||||||
// void editor_lsp_handle(Editor *editor, json msg);
|
void editor_lsp_handle(Editor *editor, json msg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -7,21 +7,21 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
static const std::unordered_map<std::string, Language> kLanguages = {
|
static const std::unordered_map<std::string, Language> kLanguages = {
|
||||||
{"bash", {"bash", tree_sitter_bash}},
|
{"bash", {"bash", LANG(bash)}},
|
||||||
{"c", {"c", tree_sitter_c, 1}},
|
{"c", {"c", LANG(c), 1}},
|
||||||
{"cpp", {"cpp", tree_sitter_cpp, 1}},
|
{"cpp", {"cpp", LANG(cpp), 1}},
|
||||||
{"h", {"h", tree_sitter_cpp, 1}},
|
{"h", {"h", LANG(cpp), 1}},
|
||||||
{"css", {"css", tree_sitter_css}},
|
{"css", {"css", LANG(css)}},
|
||||||
{"fish", {"fish", tree_sitter_fish}},
|
{"fish", {"fish", LANG(fish)}},
|
||||||
{"go", {"go", tree_sitter_go}},
|
{"go", {"go", LANG(go)}},
|
||||||
{"haskell", {"haskell", tree_sitter_haskell}},
|
{"haskell", {"haskell", LANG(haskell)}},
|
||||||
{"html", {"html", tree_sitter_html}},
|
{"html", {"html", LANG(html)}},
|
||||||
{"javascript", {"javascript", tree_sitter_javascript}},
|
{"javascript", {"javascript", LANG(javascript)}},
|
||||||
{"json", {"json", tree_sitter_json}},
|
{"json", {"json", LANG(json)}},
|
||||||
{"lua", {"lua", tree_sitter_lua}},
|
{"lua", {"lua", LANG(lua)}},
|
||||||
{"make", {"make", tree_sitter_make}},
|
{"make", {"make", LANG(make)}},
|
||||||
{"python", {"python", tree_sitter_python}},
|
{"python", {"python", LANG(python)}},
|
||||||
{"ruby", {"ruby", tree_sitter_ruby}},
|
{"ruby", {"ruby", LANG(ruby)}},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::unordered_map<uint8_t, LSP> kLsps = {
|
static const std::unordered_map<uint8_t, LSP> kLsps = {
|
||||||
|
|||||||
@@ -3,34 +3,36 @@
|
|||||||
|
|
||||||
#include "./pch.h"
|
#include "./pch.h"
|
||||||
|
|
||||||
|
#define LANG(name) tree_sitter_##name
|
||||||
|
#define TS_DEF(name) extern "C" const TSLanguage *LANG(name)();
|
||||||
|
|
||||||
struct Language {
|
struct Language {
|
||||||
std::string name;
|
std::string name;
|
||||||
const TSLanguage *(*fn)();
|
const TSLanguage *(*fn)();
|
||||||
uint8_t lsp_id = 0;
|
uint8_t lsp_id = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" {
|
TS_DEF(bash)
|
||||||
const TSLanguage *tree_sitter_bash();
|
TS_DEF(c)
|
||||||
const TSLanguage *tree_sitter_c();
|
TS_DEF(cpp)
|
||||||
const TSLanguage *tree_sitter_cpp();
|
TS_DEF(css)
|
||||||
const TSLanguage *tree_sitter_css();
|
TS_DEF(fish)
|
||||||
const TSLanguage *tree_sitter_fish();
|
TS_DEF(go)
|
||||||
const TSLanguage *tree_sitter_go();
|
TS_DEF(haskell)
|
||||||
const TSLanguage *tree_sitter_haskell();
|
TS_DEF(html)
|
||||||
const TSLanguage *tree_sitter_html();
|
TS_DEF(javascript)
|
||||||
const TSLanguage *tree_sitter_javascript();
|
TS_DEF(json)
|
||||||
const TSLanguage *tree_sitter_json();
|
TS_DEF(lua)
|
||||||
const TSLanguage *tree_sitter_lua();
|
TS_DEF(make)
|
||||||
const TSLanguage *tree_sitter_make();
|
TS_DEF(python)
|
||||||
const TSLanguage *tree_sitter_python();
|
TS_DEF(ruby)
|
||||||
const TSLanguage *tree_sitter_ruby();
|
TS_DEF(rust)
|
||||||
const TSLanguage *tree_sitter_rust();
|
|
||||||
// TO ADD
|
// TO ADD
|
||||||
// sql
|
// sql
|
||||||
// wasm
|
// wasm
|
||||||
// conf
|
// conf
|
||||||
// yaml, toml
|
// yaml, toml
|
||||||
// godot
|
// godot
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -82,6 +82,8 @@ extern std::mutex screen_mutex;
|
|||||||
|
|
||||||
Coord start_screen();
|
Coord start_screen();
|
||||||
void end_screen();
|
void end_screen();
|
||||||
|
void update(uint32_t row, uint32_t col, std::string utf8, uint32_t fg,
|
||||||
|
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 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);
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ void log(const char *fmt, ...);
|
|||||||
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);
|
||||||
|
|||||||
@@ -71,6 +71,10 @@ 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;
|
||||||
|
auto warn_it = editor->warnings.begin();
|
||||||
|
while (warn_it != editor->warnings.end() &&
|
||||||
|
warn_it->line < editor->scroll.row)
|
||||||
|
++warn_it;
|
||||||
std::shared_lock knot_lock(editor->knot_mtx);
|
std::shared_lock knot_lock(editor->knot_mtx);
|
||||||
if (editor->selection_active) {
|
if (editor->selection_active) {
|
||||||
Coord start, end;
|
Coord start, end;
|
||||||
@@ -131,6 +135,7 @@ void render_editor(Editor *editor) {
|
|||||||
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);
|
def_span_cursor.sync(global_byte_offset);
|
||||||
|
std::shared_lock v_lock(editor->v_mtx);
|
||||||
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) {
|
||||||
@@ -156,6 +161,8 @@ void render_editor(Editor *editor) {
|
|||||||
while (line_index <= skip_until) {
|
while (line_index <= skip_until) {
|
||||||
if (hook_it != v.end() && hook_it->first == line_index + 1)
|
if (hook_it != v.end() && hook_it->first == line_index + 1)
|
||||||
hook_it++;
|
hook_it++;
|
||||||
|
while (warn_it != editor->warnings.end() && warn_it->line == line_index)
|
||||||
|
++warn_it;
|
||||||
uint32_t line_len;
|
uint32_t line_len;
|
||||||
char *line = next_line(it, &line_len);
|
char *line = next_line(it, &line_len);
|
||||||
if (!line)
|
if (!line)
|
||||||
@@ -174,6 +181,11 @@ 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--;
|
||||||
|
std::vector<VWarn> line_warnings;
|
||||||
|
while (warn_it != editor->warnings.end() && warn_it->line == line_index) {
|
||||||
|
line_warnings.push_back(*warn_it);
|
||||||
|
++warn_it;
|
||||||
|
}
|
||||||
uint32_t current_byte_offset = 0;
|
uint32_t current_byte_offset = 0;
|
||||||
if (rendered_rows == 0)
|
if (rendered_rows == 0)
|
||||||
current_byte_offset += editor->scroll.col;
|
current_byte_offset += editor->scroll.col;
|
||||||
@@ -257,6 +269,78 @@ void render_editor(Editor *editor) {
|
|||||||
0x555555 | color, 0);
|
0x555555 | color, 0);
|
||||||
col++;
|
col++;
|
||||||
}
|
}
|
||||||
|
if (!line_warnings.empty() && line_left == 0) {
|
||||||
|
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 final;
|
||||||
|
case 2:
|
||||||
|
err_sym = "";
|
||||||
|
fg_color = 0xFFFF00;
|
||||||
|
goto final;
|
||||||
|
case 3:
|
||||||
|
err_sym = "";
|
||||||
|
fg_color = 0xFF00FF;
|
||||||
|
goto final;
|
||||||
|
case 4:
|
||||||
|
err_sym = "";
|
||||||
|
fg_color = 0xAAAAAA;
|
||||||
|
goto final;
|
||||||
|
final:
|
||||||
|
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 (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);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ extern "C" {
|
|||||||
#include "../libs/libgrapheme/grapheme.h"
|
#include "../libs/libgrapheme/grapheme.h"
|
||||||
}
|
}
|
||||||
#include "../include/editor.h"
|
#include "../include/editor.h"
|
||||||
|
#include "../include/lsp.h"
|
||||||
#include "../include/main.h"
|
#include "../include/main.h"
|
||||||
#include "../include/utils.h"
|
#include "../include/utils.h"
|
||||||
|
|
||||||
@@ -342,6 +343,26 @@ void edit_erase(Editor *editor, Coord pos, int64_t len) {
|
|||||||
TSPoint old_point = {pos.row, pos.col};
|
TSPoint old_point = {pos.row, pos.col};
|
||||||
uint32_t byte_pos = line_to_byte(editor->root, pos.row, nullptr) + pos.col;
|
uint32_t byte_pos = line_to_byte(editor->root, pos.row, nullptr) + pos.col;
|
||||||
Coord point = move_left_pure(editor, pos, -len);
|
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;
|
uint32_t start = line_to_byte(editor->root, point.row, nullptr) + point.col;
|
||||||
if (cursor_original > start && cursor_original <= byte_pos) {
|
if (cursor_original > start && cursor_original <= byte_pos) {
|
||||||
editor->cursor = point;
|
editor->cursor = point;
|
||||||
@@ -372,6 +393,17 @@ void edit_erase(Editor *editor, Coord pos, int64_t len) {
|
|||||||
};
|
};
|
||||||
editor->edit_queue.push(edit);
|
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);
|
std::unique_lock lock_3(editor->spans.mtx);
|
||||||
apply_edit(editor->spans.spans, start, start - byte_pos);
|
apply_edit(editor->spans.spans, start, start - byte_pos);
|
||||||
if (editor->spans.mid_parse)
|
if (editor->spans.mid_parse)
|
||||||
@@ -386,6 +418,26 @@ void edit_erase(Editor *editor, Coord pos, int64_t len) {
|
|||||||
TSPoint old_point = {pos.row, pos.col};
|
TSPoint old_point = {pos.row, pos.col};
|
||||||
uint32_t byte_pos = line_to_byte(editor->root, pos.row, nullptr) + pos.col;
|
uint32_t byte_pos = line_to_byte(editor->root, pos.row, nullptr) + pos.col;
|
||||||
Coord point = move_right_pure(editor, pos, len);
|
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;
|
uint32_t end = line_to_byte(editor->root, point.row, nullptr) + point.col;
|
||||||
if (cursor_original > byte_pos && cursor_original <= end) {
|
if (cursor_original > byte_pos && cursor_original <= end) {
|
||||||
editor->cursor = pos;
|
editor->cursor = pos;
|
||||||
@@ -416,6 +468,17 @@ void edit_erase(Editor *editor, Coord pos, int64_t len) {
|
|||||||
};
|
};
|
||||||
editor->edit_queue.push(edit);
|
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);
|
std::unique_lock lock_3(editor->spans.mtx);
|
||||||
apply_edit(editor->spans.spans, byte_pos, byte_pos - end);
|
apply_edit(editor->spans.spans, byte_pos, byte_pos - end);
|
||||||
if (editor->spans.mid_parse)
|
if (editor->spans.mid_parse)
|
||||||
@@ -466,6 +529,30 @@ void edit_insert(Editor *editor, Coord pos, char *data, uint32_t len) {
|
|||||||
};
|
};
|
||||||
editor->edit_queue.push(edit);
|
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);
|
std::unique_lock lock_3(editor->spans.mtx);
|
||||||
apply_edit(editor->spans.spans, byte_pos, len);
|
apply_edit(editor->spans.spans, byte_pos, len);
|
||||||
if (editor->spans.mid_parse)
|
if (editor->spans.mid_parse)
|
||||||
|
|||||||
@@ -351,25 +351,50 @@ void handle_editor_event(Editor *editor, KeyEvent event) {
|
|||||||
edit_erase(editor, editor->cursor, -(int64_t)prev_col_cluster);
|
edit_erase(editor, editor->cursor, -(int64_t)prev_col_cluster);
|
||||||
} else if (isprint((unsigned char)(event.c[0]))) {
|
} else if (isprint((unsigned char)(event.c[0]))) {
|
||||||
char c = event.c[0];
|
char c = event.c[0];
|
||||||
|
uint32_t col = editor->cursor.col;
|
||||||
|
LineIterator *it = begin_l_iter(editor->root, editor->cursor.row);
|
||||||
|
uint32_t len;
|
||||||
|
char *line = next_line(it, &len);
|
||||||
|
bool skip_insert = false;
|
||||||
|
if (line && col < len) {
|
||||||
|
char next = line[col];
|
||||||
|
if ((c == '}' && next == '}') || (c == ')' && next == ')') ||
|
||||||
|
(c == ']' && next == ']') || (c == '"' && next == '"') ||
|
||||||
|
(c == '\'' && next == '\'')) {
|
||||||
|
cursor_right(editor, 1);
|
||||||
|
skip_insert = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(it->buffer);
|
||||||
|
free(it);
|
||||||
|
if (!skip_insert) {
|
||||||
char closing = 0;
|
char closing = 0;
|
||||||
if (c == '{')
|
switch (c) {
|
||||||
|
case '{':
|
||||||
closing = '}';
|
closing = '}';
|
||||||
else if (c == '(')
|
break;
|
||||||
|
case '(':
|
||||||
closing = ')';
|
closing = ')';
|
||||||
else if (c == '[')
|
break;
|
||||||
|
case '[':
|
||||||
closing = ']';
|
closing = ']';
|
||||||
else if (c == '"')
|
break;
|
||||||
|
case '"':
|
||||||
closing = '"';
|
closing = '"';
|
||||||
else if (c == '\'')
|
break;
|
||||||
|
case '\'':
|
||||||
closing = '\'';
|
closing = '\'';
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (closing) {
|
if (closing) {
|
||||||
char pair[2] = {c, closing};
|
char pair[2] = {c, closing};
|
||||||
edit_insert(editor, editor->cursor, pair, 2);
|
edit_insert(editor, editor->cursor, pair, 2);
|
||||||
cursor_right(editor, 1);
|
cursor_right(editor, 1);
|
||||||
} else {
|
} else {
|
||||||
edit_insert(editor, editor->cursor, event.c, 1);
|
edit_insert(editor, editor->cursor, &c, 1);
|
||||||
cursor_right(editor, 1);
|
cursor_right(editor, 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if (event.c[0] == 0x7F || event.c[0] == 0x08) {
|
} else if (event.c[0] == 0x7F || event.c[0] == 0x08) {
|
||||||
Coord prev_pos = editor->cursor;
|
Coord prev_pos = editor->cursor;
|
||||||
if (prev_pos.col > 0)
|
if (prev_pos.col > 0)
|
||||||
@@ -571,3 +596,23 @@ void editor_worker(Editor *editor) {
|
|||||||
lock.unlock();
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ uint32_t get_indent(Editor *editor, Coord cursor) {
|
|||||||
if (!editor)
|
if (!editor)
|
||||||
return 0;
|
return 0;
|
||||||
LineIterator *it = begin_l_iter(editor->root, cursor.row);
|
LineIterator *it = begin_l_iter(editor->root, cursor.row);
|
||||||
|
next_line(it, nullptr);
|
||||||
uint32_t line_len;
|
uint32_t line_len;
|
||||||
char *line;
|
char *line;
|
||||||
while ((line = prev_line(it, &line_len)) != nullptr) {
|
while ((line = prev_line(it, &line_len)) != nullptr) {
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ std::unordered_map<uint8_t, LSPInstance *> active_lsps;
|
|||||||
Queue<LSPOpenRequest> lsp_open_queue;
|
Queue<LSPOpenRequest> lsp_open_queue;
|
||||||
|
|
||||||
static bool init_lsp(LSPInstance *lsp) {
|
static bool init_lsp(LSPInstance *lsp) {
|
||||||
log("starting %s\n", lsp->lsp->command);
|
|
||||||
int in_pipe[2];
|
int in_pipe[2];
|
||||||
int out_pipe[2];
|
int out_pipe[2];
|
||||||
if (pipe(in_pipe) == -1 || pipe(out_pipe) == -1) {
|
if (pipe(in_pipe) == -1 || pipe(out_pipe) == -1) {
|
||||||
@@ -240,8 +239,7 @@ void lsp_worker() {
|
|||||||
Editor *ed = editor_for_uri(lsp, uri);
|
Editor *ed = editor_for_uri(lsp, uri);
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
if (ed)
|
if (ed)
|
||||||
// editor_lsp_handle(ed, *msg)
|
editor_lsp_handle(ed, *msg);
|
||||||
;
|
|
||||||
else
|
else
|
||||||
lsp_handle(lsp, *msg);
|
lsp_handle(lsp, *msg);
|
||||||
lock.lock();
|
lock.lock();
|
||||||
|
|||||||
@@ -48,14 +48,24 @@ void end_screen() { disable_raw_mode(); }
|
|||||||
|
|
||||||
Coord get_size() { return {rows, cols}; }
|
Coord get_size() { return {rows, cols}; }
|
||||||
|
|
||||||
|
void update(uint32_t row, uint32_t col, std::string utf8, uint32_t fg,
|
||||||
|
uint32_t bg, uint8_t flags) {
|
||||||
|
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 : "";
|
||||||
|
screen[idx].fg = fg;
|
||||||
|
screen[idx].bg = bg;
|
||||||
|
screen[idx].flags = 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) {
|
||||||
if (row >= rows || col >= cols)
|
if (row >= rows || col >= cols)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
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 : "";
|
||||||
screen[idx].fg = fg;
|
screen[idx].fg = fg;
|
||||||
screen[idx].bg = bg;
|
screen[idx].bg = bg;
|
||||||
|
|||||||
@@ -304,6 +304,7 @@ void ts_collect_spans(Editor *editor) {
|
|||||||
while (editor->spans.edits.pop(span_edit))
|
while (editor->spans.edits.pop(span_edit))
|
||||||
apply_edit(new_spans, span_edit.first, span_edit.second);
|
apply_edit(new_spans, span_edit.first, span_edit.second);
|
||||||
TSTree *inj_tree = ts_parser_parse(inj.parser, nullptr, tsinput);
|
TSTree *inj_tree = ts_parser_parse(inj.parser, nullptr, tsinput);
|
||||||
|
knot_mtx.unlock();
|
||||||
TSQueryCursor *inj_cursor = ts_query_cursor_new();
|
TSQueryCursor *inj_cursor = ts_query_cursor_new();
|
||||||
ts_query_cursor_exec(inj_cursor, inj.query, ts_tree_root_node(inj_tree));
|
ts_query_cursor_exec(inj_cursor, inj.query, ts_tree_root_node(inj_tree));
|
||||||
TSQueryMatch inj_match;
|
TSQueryMatch inj_match;
|
||||||
|
|||||||
22
src/utils.cc
22
src/utils.cc
@@ -242,6 +242,28 @@ char *detect_file_type(const char *filename) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
Language language_for_file(const char *filename) {
|
Language language_for_file(const char *filename) {
|
||||||
std::string ext = file_extension(filename);
|
std::string ext = file_extension(filename);
|
||||||
std::string lang_name;
|
std::string lang_name;
|
||||||
|
|||||||
Reference in New Issue
Block a user