Lsp completion logic
This commit is contained in:
44
include/editor/completions.h
Normal file
44
include/editor/completions.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#ifndef EDITOR_COMPLETIONS_H
|
||||
#define EDITOR_COMPLETIONS_H
|
||||
|
||||
#include "editor/decl.h"
|
||||
#include "pch.h"
|
||||
#include "ui/completionbox.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
struct CompletionItem {
|
||||
std::string label; // Shown in the autocomplete box
|
||||
uint8_t kind; // Function, variable, class, etc.
|
||||
std::optional<std::string> detail; // Shown greyed in autocomplete box
|
||||
std::optional<std::string> documentation; // Hover box (can be lazy-loaded)
|
||||
bool is_markup = false;
|
||||
bool deprecated = false; // Shown with strikethrough, may push down in list
|
||||
std::string sort; // Used for sorting
|
||||
std::string filter; // Used for filtering (default: label)
|
||||
bool snippet = false;
|
||||
std::vector<TextEdit> edits;
|
||||
json original;
|
||||
std::vector<char> end_chars; // Ends completion session if typed
|
||||
};
|
||||
|
||||
struct CompletionSession {
|
||||
std::shared_mutex mtx;
|
||||
|
||||
bool active = false;
|
||||
Coord hook; // set to start of word
|
||||
std::optional<std::string> prefix; // text between hook and cursor
|
||||
uint8_t select = 0; // index of selected item (defualts to preselcted one
|
||||
// when data requested)
|
||||
std::vector<CompletionItem> items;
|
||||
std::vector<uint8_t> visible;
|
||||
bool complete = true; // If false, client may request more items on filter
|
||||
// (but doesnt try filtering on its own)
|
||||
std::optional<char> trigger_char; // Character that triggered completion sent
|
||||
// to lsp for isIncomplete resolving
|
||||
uint8_t trigger = 0; // Type of trigger (1: manual, 2: trigger char, 3: auto)
|
||||
CompletionBox box;
|
||||
|
||||
CompletionSession() : box(this) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -3,6 +3,14 @@
|
||||
|
||||
#include "utils/utils.h"
|
||||
|
||||
struct TextEdit {
|
||||
// NOTE: start.col is in utf16 index and not clusters or utf8
|
||||
Coord start;
|
||||
// NOTE: end.col is in utf16 index and not clusters or utf8
|
||||
Coord end;
|
||||
std::string text;
|
||||
};
|
||||
|
||||
struct Fold {
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#ifndef EDITOR_H
|
||||
#define EDITOR_H
|
||||
|
||||
#include "editor/completions.h"
|
||||
#include "editor/spans.h"
|
||||
#include "io/knot.h"
|
||||
#include "io/sysio.h"
|
||||
#include "ts/decl.h"
|
||||
#include "ui/completionbox.h"
|
||||
#include "ui/diagnostics.h"
|
||||
#include "ui/hover.h"
|
||||
#include "utils/utils.h"
|
||||
@@ -49,6 +51,7 @@ struct Editor {
|
||||
bool diagnostics_active;
|
||||
DiagnosticBox diagnostics;
|
||||
int lsp_version = 1;
|
||||
CompletionSession completion;
|
||||
};
|
||||
|
||||
Editor *new_editor(const char *filename_arg, Coord position, Coord size);
|
||||
@@ -73,6 +76,8 @@ 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);
|
||||
void edit_replace(Editor *editor, Coord start, Coord end, const char *text,
|
||||
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);
|
||||
@@ -90,6 +95,13 @@ 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);
|
||||
void apply_lsp_edits(Editor *editor, std::vector<TextEdit> edits);
|
||||
void completion_resolve_doc(Editor *editor);
|
||||
void complete_accept(Editor *editor);
|
||||
void complete_next(Editor *editor);
|
||||
void complete_prev(Editor *editor);
|
||||
void complete_select(Editor *editor, uint8_t index);
|
||||
void handle_completion(Editor *editor, KeyEvent event);
|
||||
|
||||
inline void apply_hook_insertion(Editor *editor, uint32_t line, uint32_t rows) {
|
||||
for (auto &hook : editor->hooks)
|
||||
|
||||
@@ -62,19 +62,33 @@ struct ScreenCell {
|
||||
};
|
||||
|
||||
struct KeyEvent {
|
||||
/* KEY_CHAR, KEY_SPECIAL, KEY_MOUSE, KEY_PASTE, KEY_NONE */
|
||||
uint8_t key_type;
|
||||
|
||||
/* the character / string if key_type == KEY_CHAR or KEY_PASTE */
|
||||
char *c;
|
||||
/* length of c */
|
||||
uint32_t len;
|
||||
|
||||
/* KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_DELETE if key_type ==
|
||||
* KEY_SPECIAL */
|
||||
uint8_t special_key;
|
||||
/* ALT, CNTRL, CNTRL_ALT, SHIFT if key_type == KEY_SPECIAL */
|
||||
uint8_t special_modifier;
|
||||
|
||||
/* column of mouse click */
|
||||
uint8_t mouse_x;
|
||||
/* row of mouse click */
|
||||
uint8_t mouse_y;
|
||||
/* LEFT_BTN, MIDDLE_BTN, RIGHT_BTN, SCROLL_BTN, NONE_BTN if key_type ==
|
||||
* KEY_MOUSE */
|
||||
uint8_t mouse_button;
|
||||
/* PRESS, RELEASE, DRAG, SCROLL if key_type == KEY_MOUSE */
|
||||
uint8_t mouse_state;
|
||||
/* SCROLL_UP, SCROLL_DOWN, SCROLL_LEFT, SCROLL_RIGHT if key_type ==
|
||||
* KEY_MOUSE and mouse_state == SCROLL */
|
||||
uint8_t mouse_direction;
|
||||
/* ALT, CNTRL, CNTRL_ALT, SHIFT if key_type == KEY_MOUSE */
|
||||
uint8_t mouse_modifier;
|
||||
};
|
||||
|
||||
@@ -97,7 +111,8 @@ 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(uint32_t row, uint32_t col, uint32_t type,
|
||||
bool show_cursor_param);
|
||||
void render();
|
||||
Coord get_size();
|
||||
|
||||
|
||||
@@ -34,7 +34,9 @@ struct LSPInstance {
|
||||
bool incremental_sync = false;
|
||||
bool allow_hover = false;
|
||||
bool allow_completion = false;
|
||||
std::string trigger_chars;
|
||||
bool allow_resolve = false;
|
||||
std::vector<char> trigger_chars;
|
||||
std::vector<char> end_chars;
|
||||
uint32_t last_id = 0;
|
||||
Queue<json> inbox;
|
||||
Queue<json> outbox;
|
||||
@@ -53,12 +55,15 @@ static json client_capabilities = {
|
||||
{"hover", {{"contentFormat", {"markdown", "plaintext"}}}},
|
||||
{"completion",
|
||||
{{"completionItem",
|
||||
{{"snippetSupport", true},
|
||||
{{"commitCharactersSupport", true},
|
||||
{"dynamicRegistration", false},
|
||||
{"snippetSupport", true},
|
||||
{"documentationFormat", {"markdown", "plaintext"}},
|
||||
{"resolveSupport", {{"properties", {"documentation", "detail"}}}},
|
||||
{"resolveSupport", {{"properties", {"documentation"}}}},
|
||||
{"insertReplaceSupport", true},
|
||||
{"labelDetailsSupport", true},
|
||||
{"insertTextModeSupport", {{"valueSet", {1}}}}}},
|
||||
{"insertTextModeSupport", {{"valueSet", {1}}}},
|
||||
{"deprecatedSupport", true}}},
|
||||
{"completionItemKind", {{"valueSet", {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}}},
|
||||
{"contextSupport", true},
|
||||
{"insertTextMode", 1}}}}}};
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
#define PCRE2_CODE_UNIT_WIDTH 8
|
||||
#define PCRE_WORKSPACE_SIZE 512
|
||||
|
||||
#include <magic.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <pcre2.h>
|
||||
extern "C" {
|
||||
#include "libgrapheme/grapheme.h"
|
||||
#include "unicode_width/unicode_width.h"
|
||||
@@ -25,12 +28,9 @@ extern "C" {
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <limits.h>
|
||||
#include <magic.h>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <optional>
|
||||
#include <pcre2.h>
|
||||
#include <queue>
|
||||
#include <shared_mutex>
|
||||
#include <signal.h>
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
#define TS_DEF(name) extern "C" const TSLanguage *LANG(name)()
|
||||
|
||||
struct Language {
|
||||
std::string name;
|
||||
const TSLanguage *(*fn)();
|
||||
uint8_t lsp_id;
|
||||
std::string name = "unknown";
|
||||
const TSLanguage *(*fn)() = nullptr;
|
||||
uint8_t lsp_id = 0;
|
||||
uint32_t color = 0xFFFFFF;
|
||||
const char *symbol = " ";
|
||||
};
|
||||
|
||||
20
include/ui/completionbox.h
Normal file
20
include/ui/completionbox.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef UI_COMPLETIONBOX_H
|
||||
#define UI_COMPLETIONBOX_H
|
||||
|
||||
#include "io/sysio.h"
|
||||
#include "pch.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
struct CompletionBox {
|
||||
struct CompletionSession *session;
|
||||
bool hidden = true;
|
||||
std::vector<ScreenCell> cells;
|
||||
Coord size;
|
||||
Coord position;
|
||||
|
||||
CompletionBox(CompletionSession *s) : session(s) {}
|
||||
void render_update();
|
||||
void render(Coord pos);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -9,8 +9,7 @@
|
||||
struct DiagnosticBox {
|
||||
std::vector<VWarn> warnings;
|
||||
std::vector<ScreenCell> cells;
|
||||
uint32_t box_width;
|
||||
uint32_t box_height;
|
||||
Coord size;
|
||||
|
||||
void clear();
|
||||
void render_first();
|
||||
|
||||
@@ -12,8 +12,7 @@ struct HoverBox {
|
||||
std::atomic<bool> is_markup;
|
||||
uint32_t scroll_;
|
||||
std::vector<ScreenCell> cells;
|
||||
uint32_t box_width;
|
||||
uint32_t box_height;
|
||||
Coord size;
|
||||
std::vector<Highlight> highlights;
|
||||
std::vector<Span> hover_spans;
|
||||
|
||||
|
||||
@@ -61,6 +61,8 @@ struct Match {
|
||||
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define UNUSED(x) (void)(x)
|
||||
#define USING(x) UNUSED(sizeof(x))
|
||||
|
||||
std::string clean_text(const std::string &input);
|
||||
std::string percent_encode(const std::string &s);
|
||||
@@ -74,6 +76,7 @@ uint32_t get_visual_col_from_bytes(const char *line, uint32_t len,
|
||||
uint32_t get_bytes_from_visual_col(const char *line, uint32_t len,
|
||||
uint32_t target_visual_col);
|
||||
int utf8_byte_offset_to_utf16(const char *s, size_t byte_pos);
|
||||
size_t utf16_offset_to_utf8(const char *s, int utf16_pos);
|
||||
|
||||
void log(const char *fmt, ...);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user