First completion level is working (LSP connected)

This commit is contained in:
2026-05-28 18:28:59 +02:00
parent 8eeef59a98
commit a8b2960eb4
27 changed files with 5167 additions and 335 deletions
+56 -7
View File
@@ -6,6 +6,8 @@
#include "include/buffer.h"
#include "include/data.h"
#include "include/split_screen.h"
#include "include/completion.h"
#include "include/lsp_ui.h"
#include <ctype.h>
#include <sys/stat.h>
#include <dirent.h>
@@ -18,6 +20,7 @@
#include "include/terminal.h"
#include "include/utf8.h"
#include "include/utils.h"
extern struct editorConfig E;
@@ -37,7 +40,7 @@ extern struct editorConfig E;
* - path ends with '/' (already a directory)
* - no matching entries found
* - directory cannot be opened
* @note Caller is responsible for freeing the returned string
* @note Caller is responsible for bFreeing the returned string
* @note Uses static buffer internally; may return stale pointers across calls
*/
const char *fileCompletion(const char *path) {
@@ -92,7 +95,7 @@ const char *fileCompletion(const char *path) {
// Cleanup when no more entries
closedir(dir);
dir = NULL;
free(entry);
bFree(entry);
appDebug("[FILE COMP] no entries\n");
return strdup(path);
}
@@ -108,13 +111,13 @@ const char *fileCompletion(const char *path) {
* @return Pointer to the user-entered text (dynamically allocated), or NULL if:
* - User pressed ESC to cancel
* - Input buffer is empty when Enter is pressed
* @note Caller is responsible for freeing the returned string
* @note Caller is responsible for bFreeing the returned string
* @note Uses editorReadKey() for input and editorRefreshScreen() for display
*/
char *editorPrompt(char *prompt, char *placeHolder, char bPathMode) {
size_t buf_size = 256;
appDebug("[FILE COMP] %s %d\n", placeHolder, strlen(placeHolder));
char *buf = malloc(buf_size);
char *buf = bAlloc(buf_size);
size_t buf_len = 0;
int c = 0;
buf[0] = '\0';
@@ -131,7 +134,7 @@ char *editorPrompt(char *prompt, char *placeHolder, char bPathMode) {
}
} else if (c == ESCAPE) {
editorSetStatusMessage("");
free(buf);
bFree(buf);
return NULL;
} else if (c == '\r') {
if (buf_len != 0) {
@@ -154,14 +157,14 @@ char *editorPrompt(char *prompt, char *placeHolder, char bPathMode) {
buf_len = 0;
char * buf_complete = (char *) fileCompletion(path);
strcpy(buf, buf_complete);
free(buf_complete);
bFree(buf_complete);
buf_len = strlen(buf);
buf[buf_len] = '\0';
} else if (!iscntrl(c) && c < 256) {
if (buf_len == buf_size - 1) {
buf_size *= 2;
buf = realloc(buf, buf_size);
buf = bRealloc(buf, buf_size);
}
buf[buf_len++] = c;
buf[buf_len] = '\0';
@@ -213,6 +216,52 @@ void editorProcessKeypress() {
int c = editorReadKey();
char key_sequence[8];
if (E.lsp_client && E.lsp_completion.visible) {
if (c == ARROW_UP || c == CTRL_KEY('p')) {
if (E.lsp_completion.selected > 0)
E.lsp_completion.selected--;
return; // consumed, redraw on next loop
}
if (c == ARROW_DOWN || c == CTRL_KEY('n')) {
if (E.lsp_completion.selected < E.lsp_completion.count - 1)
E.lsp_completion.selected++;
return;
}
if (c == '\r') {
CompletionItem *item = &E.lsp_completion.items[E.lsp_completion.selected];
EditorPane *active = splitScreenGetActivePane();
struct buffer_t *buf = bufferFindById(active->buffer_id);
// Find how many chars the user already typed by looking at the
// current word (chars before cursor on the same line)
int file_col = active->cursor_x + active->x_offset;
row_t *row = &buf->row[active->cursor_y + active->y_offset];
// Walk backwards from cursor to find start of current word
int word_start = file_col;
while (word_start > 0 &&
(isalnum((unsigned char)row->chars[word_start - 1]) ||
row->chars[word_start - 1] == '_'))
word_start--;
int already_typed = file_col - word_start; // chars user already typed
// Insert only the suffix — what comes after what's already typed
const char *suffix = item->label + already_typed;
for (int i = 0; suffix[i]; i++)
bufferInsertBytes(&suffix[i], 1);
E.lsp_completion.visible = 0;
return;
}
if (c == ESCAPE) {
E.lsp_completion.visible = 0;
return;
}
// Any other key: dismiss popup and fall through to normal handling
E.lsp_completion.visible = 0;
}
if (executeKeyBind(keyToString(c))) {
return;
}