Add lsp's for many different languages and minor fixes
This commit is contained in:
@@ -27,6 +27,7 @@ A TUI IDE.
|
||||
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)
|
||||
- [ ] Add codeium/copilot support for auto-completion (uses the VAI virtual text) as a test phase.
|
||||
- [ ] Redo cpp/c/h scm file . also pretty much all of them do manually
|
||||
- [ ] 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`.
|
||||
- [ ] Add snippets from wherever i get them. (like luasnip or vsnip)
|
||||
@@ -38,7 +39,7 @@ A TUI IDE.
|
||||
- [ ] Add search / replace along with search / virtual cursors are searched pos.
|
||||
- [ ] Add support for undo/redo.
|
||||
- [ ] 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 SQL support. (viewer and basic editor)
|
||||
- [ ] Add color picker/palette for hex or other css colors.
|
||||
|
||||
@@ -221,21 +221,6 @@
|
||||
_ @type.builtin
|
||||
type: _?)
|
||||
|
||||
;; #C4B5FF #000000 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
|
||||
|
||||
|
||||
@@ -221,21 +221,6 @@
|
||||
_ @type.builtin
|
||||
type: _?)
|
||||
|
||||
;; #C4B5FF #000000 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
|
||||
|
||||
|
||||
@@ -221,21 +221,6 @@
|
||||
_ @type.builtin
|
||||
type: _?)
|
||||
|
||||
;; #C4B5FF #000000 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
|
||||
|
||||
|
||||
@@ -298,18 +298,18 @@
|
||||
; JSX
|
||||
; ============================================================
|
||||
|
||||
;; #59C2FF #000000 0 0 0 2
|
||||
(jsx_opening_element (identifier) @tag (#match? @tag "^[a-z][^.]*$"))
|
||||
(jsx_closing_element (identifier) @tag (#match? @tag "^[a-z][^.]*$"))
|
||||
(jsx_self_closing_element (identifier) @tag (#match? @tag "^[a-z][^.]*$"))
|
||||
;; #59C2FF #000000 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 1
|
||||
(jsx_attribute (property_identifier) @attribute)
|
||||
;; #F07178 #000000 0 0 0 3
|
||||
(jsx_attribute (property_identifier) @attribute2)
|
||||
|
||||
;; #BFBDB6 #000000 0 0 0 1
|
||||
(jsx_opening_element (["<" ">"]) @punctuation.bracket)
|
||||
(jsx_closing_element (["</" ">"]) @punctuation.bracket)
|
||||
(jsx_self_closing_element (["<" "/>"]) @punctuation.bracket)
|
||||
;; #BFBDB6 #000000 0 0 0 3
|
||||
(jsx_opening_element (["<" ">"]) @punctuation.bracket2)
|
||||
(jsx_closing_element (["</" ">"]) @punctuation.bracket2)
|
||||
(jsx_self_closing_element (["<" "/>"]) @punctuation.bracket2)
|
||||
|
||||
; Injections
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ struct LSPInstance {
|
||||
int stdin_fd{-1};
|
||||
int stdout_fd{-1};
|
||||
bool initialized = false;
|
||||
bool incremental_sync = true;
|
||||
uint32_t last_id = 0;
|
||||
Queue<json> inbox;
|
||||
Queue<json> outbox;
|
||||
|
||||
188
include/maps.h
188
include/maps.h
@@ -19,41 +19,177 @@ static const std::unordered_map<uint8_t, LSP> kLsps = {
|
||||
"--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,
|
||||
}}},
|
||||
};
|
||||
|
||||
static const std::unordered_map<std::string, Language> kLanguages = {
|
||||
{"bash", {"bash", LANG(bash)}},
|
||||
{"bash", {"bash", LANG(bash), 4}},
|
||||
{"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)}},
|
||||
{"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}},
|
||||
{"json", {"json", 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}},
|
||||
{"make", {"make", LANG(make), 21}},
|
||||
{"gdscript", {"gdscript", LANG(gdscript)}}, // TODO: connect to godot
|
||||
{"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)}},
|
||||
{"ini", {"ini", LANG(ini)}},
|
||||
};
|
||||
|
||||
static const std::unordered_map<std::string, std::string> kExtToLang = {
|
||||
@@ -85,8 +221,7 @@ static const std::unordered_map<std::string, std::string> kExtToLang = {
|
||||
{"rs", "rust"},
|
||||
{"diff", "diff"},
|
||||
{"patch", "diff"},
|
||||
{"erb", "embedded_template"},
|
||||
{"etlua", "embedded_template"},
|
||||
{"erb", "erb"},
|
||||
{"gd", "gdscript"},
|
||||
{"gitattributes", "gitattributes"},
|
||||
{"gitignore", "gitignore"},
|
||||
@@ -120,7 +255,6 @@ static const std::unordered_map<std::string, std::string> kMimeToLang = {
|
||||
{"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"},
|
||||
|
||||
@@ -52,6 +52,7 @@ struct Coord {
|
||||
bool operator>=(const Coord &other) const { return !(*this < other); }
|
||||
};
|
||||
|
||||
std::string percent_encode(const std::string &s);
|
||||
std::string path_abs(const std::string &path_str);
|
||||
std::string path_to_file_uri(const std::string &path_str);
|
||||
int display_width(const char *str, size_t len);
|
||||
|
||||
66
samples/yaml.yaml
Normal file
66
samples/yaml.yaml
Normal 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"
|
||||
@@ -29,6 +29,8 @@ Editor *new_editor(const char *filename_arg, Coord position, Coord size) {
|
||||
editor->ts.parser = ts_parser_new();
|
||||
editor->ts.language = language.fn();
|
||||
ts_parser_set_language(editor->ts.parser, editor->ts.language);
|
||||
log("set language %s\n", language.name.c_str());
|
||||
log("lsp_id: %d\n", language.lsp_id);
|
||||
editor->ts.query_file =
|
||||
get_exe_dir() + "/../grammar/" + language.name + ".scm";
|
||||
request_add_to_lsp(language, editor);
|
||||
@@ -48,6 +50,8 @@ void free_tsset(TSSetMain *set) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +71,11 @@ void save_file(Editor *editor) {
|
||||
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);
|
||||
}
|
||||
|
||||
void render_editor(Editor *editor) {
|
||||
@@ -83,6 +92,7 @@ void render_editor(Editor *editor) {
|
||||
auto hook_it = v.begin();
|
||||
while (hook_it != v.end() && hook_it->first <= editor->scroll.row)
|
||||
++hook_it;
|
||||
std::unique_lock warn_lock(editor->v_mtx);
|
||||
auto warn_it = editor->warnings.begin();
|
||||
while (warn_it != editor->warnings.end() &&
|
||||
warn_it->line < editor->scroll.row)
|
||||
@@ -147,7 +157,6 @@ void render_editor(Editor *editor) {
|
||||
uint32_t global_byte_offset = line_to_byte(editor->root, line_index, nullptr);
|
||||
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) {
|
||||
const Fold *fold = fold_for_line(editor->folds, line_index);
|
||||
if (fold) {
|
||||
@@ -370,6 +379,9 @@ void render_editor(Editor *editor) {
|
||||
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) {
|
||||
|
||||
@@ -394,6 +394,7 @@ void edit_erase(Editor *editor, Coord pos, int64_t len) {
|
||||
editor->edit_queue.push(edit);
|
||||
}
|
||||
if (do_lsp) {
|
||||
if (editor->lsp->incremental_sync) {
|
||||
json message = {
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "textDocument/didChange"},
|
||||
@@ -403,6 +404,19 @@ void edit_erase(Editor *editor, Coord pos, int64_t len) {
|
||||
{"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);
|
||||
}
|
||||
}
|
||||
std::unique_lock lock_3(editor->spans.mtx);
|
||||
apply_edit(editor->spans.spans, start, start - byte_pos);
|
||||
@@ -469,6 +483,7 @@ void edit_erase(Editor *editor, Coord pos, int64_t len) {
|
||||
editor->edit_queue.push(edit);
|
||||
}
|
||||
if (do_lsp) {
|
||||
if (editor->lsp->incremental_sync) {
|
||||
json message = {
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "textDocument/didChange"},
|
||||
@@ -478,6 +493,19 @@ void edit_erase(Editor *editor, Coord pos, int64_t len) {
|
||||
{"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);
|
||||
}
|
||||
}
|
||||
std::unique_lock lock_3(editor->spans.mtx);
|
||||
apply_edit(editor->spans.spans, byte_pos, byte_pos - end);
|
||||
@@ -530,6 +558,7 @@ void edit_insert(Editor *editor, Coord pos, char *data, uint32_t len) {
|
||||
editor->edit_queue.push(edit);
|
||||
}
|
||||
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);
|
||||
@@ -552,6 +581,19 @@ void edit_insert(Editor *editor, Coord pos, char *data, uint32_t len) {
|
||||
{"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);
|
||||
}
|
||||
}
|
||||
std::unique_lock lock_3(editor->spans.mtx);
|
||||
apply_edit(editor->spans.spans, byte_pos, len);
|
||||
|
||||
@@ -610,6 +610,8 @@ void editor_lsp_handle(Editor *editor, json msg) {
|
||||
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 the performance hit
|
||||
w.line = d["range"]["start"]["line"];
|
||||
w.start = d["range"]["start"]["character"];
|
||||
uint32_t end = d["range"]["end"]["character"];
|
||||
|
||||
21
src/lsp.cc
21
src/lsp.cc
@@ -13,6 +13,7 @@ std::unordered_map<uint8_t, LSPInstance *> active_lsps;
|
||||
Queue<LSPOpenRequest> lsp_open_queue;
|
||||
|
||||
static bool init_lsp(LSPInstance *lsp) {
|
||||
log("initializing %s\n", lsp->lsp->command);
|
||||
int in_pipe[2];
|
||||
int out_pipe[2];
|
||||
if (pipe(in_pipe) == -1 || pipe(out_pipe) == -1) {
|
||||
@@ -59,23 +60,35 @@ LSPInstance *get_or_init_lsp(uint8_t lsp_id) {
|
||||
delete lsp;
|
||||
return nullptr;
|
||||
}
|
||||
log("starting %s\n", lsp->lsp->command);
|
||||
LSPPending *pending = new LSPPending();
|
||||
pending->method = "initialize";
|
||||
pending->editor = nullptr;
|
||||
pending->callback = [lsp](Editor *, std::string, json) {
|
||||
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") &&
|
||||
caps["textDocumentSync"].contains("change")) {
|
||||
int change_type = caps["textDocumentSync"]["change"];
|
||||
lsp->incremental_sync = (change_type == 2);
|
||||
}
|
||||
}
|
||||
lsp->initialized = true;
|
||||
json initialized = {{"jsonrpc", "2.0"},
|
||||
{"method", "initialized"},
|
||||
{"params", json::object()}};
|
||||
lsp_send(lsp, initialized, nullptr);
|
||||
log("initialized %s\n", lsp->lsp->command);
|
||||
};
|
||||
json init_message = {
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", "initialize"},
|
||||
{"params",
|
||||
{{"processId", getpid()},
|
||||
{"rootUri", "file://" + std::filesystem::current_path().string()},
|
||||
{"capabilities", json::object()}}}};
|
||||
{"rootUri", "file://" + percent_encode(path_abs("."))},
|
||||
{"capabilities",
|
||||
{{"textDocument",
|
||||
{{"publishDiagnostics", {{"relatedInformation", true}}}}}}}}}};
|
||||
lsp_send(lsp, init_message, pending);
|
||||
active_lsps[lsp_id] = lsp;
|
||||
return lsp;
|
||||
@@ -160,6 +173,7 @@ static std::optional<json> read_lsp_message(int fd) {
|
||||
return std::nullopt;
|
||||
got += n;
|
||||
}
|
||||
log("%s\n", body.c_str());
|
||||
return json::parse(body);
|
||||
}
|
||||
|
||||
@@ -249,6 +263,7 @@ void lsp_worker() {
|
||||
}
|
||||
|
||||
void request_add_to_lsp(Language language, Editor *editor) {
|
||||
log("request_add_to_lsp %d\n", language.lsp_id);
|
||||
lsp_open_queue.push({language, editor});
|
||||
}
|
||||
|
||||
|
||||
15
src/ts.cc
15
src/ts.cc
@@ -235,8 +235,12 @@ void ts_collect_spans(Editor *editor) {
|
||||
parse_counter = 0;
|
||||
editor->spans.mid_parse = true;
|
||||
std::shared_lock lock(editor->knot_mtx);
|
||||
editor->ts.tree =
|
||||
ts_parser_parse(editor->ts.parser, editor->ts.tree, tsinput);
|
||||
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);
|
||||
@@ -324,7 +328,12 @@ void ts_collect_spans(Editor *editor) {
|
||||
ts_parser_set_included_ranges(tsset->parser, tsset->ranges.data(),
|
||||
tsset->ranges.size());
|
||||
lock.lock();
|
||||
tsset->tree = ts_parser_parse(tsset->parser, tsset->tree, tsinput);
|
||||
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});
|
||||
|
||||
@@ -5,7 +5,7 @@ extern "C" {
|
||||
#include "../include/maps.h"
|
||||
#include "../include/utils.h"
|
||||
|
||||
static std::string percent_encode(const std::string &s) {
|
||||
std::string percent_encode(const std::string &s) {
|
||||
static const char *hex = "0123456789ABCDEF";
|
||||
std::string out;
|
||||
for (unsigned char c : s) {
|
||||
|
||||
Reference in New Issue
Block a user