popup and diagnose ui
This commit is contained in:
+67
-56
@@ -2,32 +2,27 @@
|
||||
#include "../include/define.h"
|
||||
#include "../include/editor_op.h"
|
||||
#include "../include/output.h"
|
||||
#include "include/data.h"
|
||||
#include "include/buffer.h"
|
||||
#include "include/builtins.h"
|
||||
#include "../include/completion.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>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "include/terminal.h"
|
||||
#include "include/utf8.h"
|
||||
#include "include/utils.h"
|
||||
|
||||
extern struct editorConfig E;
|
||||
|
||||
/**
|
||||
* @file input.c
|
||||
* @brief Input handling module for the Beluga text editor
|
||||
* @details Manages user input processing, key bindings, cursor movement, and file path completion
|
||||
* @details Manages user input processing, key bindings, cursor movement, and
|
||||
* file path completion
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -36,7 +31,8 @@ extern struct editorConfig E;
|
||||
* the first file or directory entry that matches the filename prefix.
|
||||
* Appends a trailing slash for directory entries.
|
||||
* @param path The file path to complete (can be relative or absolute)
|
||||
* @return Pointer to the completed file path (dynamically allocated), or NULL if:
|
||||
* @return Pointer to the completed file path (dynamically allocated), or NULL
|
||||
* if:
|
||||
* - path ends with '/' (already a directory)
|
||||
* - no matching entries found
|
||||
* - directory cannot be opened
|
||||
@@ -63,7 +59,7 @@ const char *fileCompletion(const char *path) {
|
||||
if (last_slash) {
|
||||
dir_len = last_slash - path + 1; // length of dir_path
|
||||
strncpy(directory, path, dir_len);
|
||||
predict_len = strlen(path) - dir_len;
|
||||
predict_len = (int)(strlen(path) - dir_len);
|
||||
strncpy(predict, last_slash + 1, predict_len);
|
||||
directory[dir_len] = '\0';
|
||||
predict[predict_len] = '\0';
|
||||
@@ -102,9 +98,9 @@ const char *fileCompletion(const char *path) {
|
||||
|
||||
/**
|
||||
* @brief Displays an interactive prompt and returns user input
|
||||
* @details Allows the user to enter text in a prompt with optional path completion
|
||||
* via Tab key. Supports backspace, delete, and escape key handling. Dynamically
|
||||
* allocates memory for the input buffer.
|
||||
* @details Allows the user to enter text in a prompt with optional path
|
||||
* completion via Tab key. Supports backspace, delete, and escape key handling.
|
||||
* Dynamically allocates memory for the input buffer.
|
||||
* @param prompt The prompt message format string (printf-style)
|
||||
* @param placeHolder Initial text to display in the input buffer
|
||||
* @param bPathMode If non-zero, enables Tab key file path completion
|
||||
@@ -154,8 +150,7 @@ char *editorPrompt(char *prompt, char *placeHolder, char bPathMode) {
|
||||
strcpy(path, buf);
|
||||
}
|
||||
memset(buf, 0, 256);
|
||||
buf_len = 0;
|
||||
char * buf_complete = (char *) fileCompletion(path);
|
||||
char *buf_complete = (char *)fileCompletion(path);
|
||||
strcpy(buf, buf_complete);
|
||||
bFree(buf_complete);
|
||||
buf_len = strlen(buf);
|
||||
@@ -166,14 +161,12 @@ char *editorPrompt(char *prompt, char *placeHolder, char bPathMode) {
|
||||
buf_size *= 2;
|
||||
buf = bRealloc(buf, buf_size);
|
||||
}
|
||||
buf[buf_len++] = c;
|
||||
buf[buf_len++] = (char)c;
|
||||
buf[buf_len] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Executes the command bound to a key sequence
|
||||
* @details Searches the keybinding table for a matching key sequence and
|
||||
@@ -210,56 +203,62 @@ int executeKeyBind(char *key_sequence) {
|
||||
* and either executes the bound command or inserts the character. Resets
|
||||
* the quit buffer counter on successful key processing.
|
||||
* @note Updates global editor state E
|
||||
* @note Calls editorReadKey() to get input and editorInsertChar() for unbound keys
|
||||
* @note Calls editorReadKey() to get input and editorInsertChar() for unbound
|
||||
* keys
|
||||
*/
|
||||
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++;
|
||||
if (E.constantes.LSP) {
|
||||
if (c == LSP_WAKE_KEY)
|
||||
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);
|
||||
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];
|
||||
// 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--;
|
||||
// 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
|
||||
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);
|
||||
// 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;
|
||||
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))) {
|
||||
@@ -268,5 +267,17 @@ void editorProcessKeypress() {
|
||||
int seq_len = utf8Encode(c, key_sequence);
|
||||
appDebug("key seq : %s\n", key_sequence);
|
||||
bufferInsertBytes(key_sequence, seq_len);
|
||||
if (E.constantes.LSP && is_word_char(key_sequence)) {
|
||||
EditorPane *active = splitScreenGetActivePane();
|
||||
struct buffer_t *buffer = bufferFindById(active->buffer_id);
|
||||
|
||||
if (E.lsp_client && E.lsp_client->state == LSP_READY) {
|
||||
lspDidChange(E.lsp_client, buffer);
|
||||
|
||||
E.lsp_client->completion_just_arrived = 0; // consume the flag
|
||||
}
|
||||
buffer->b_has_changed = 0;
|
||||
editorAutoComplete(lisp_null(), &E.ctx_error, E.ctx);
|
||||
}
|
||||
E.quit_times_buffer = E.constantes.QUIT_TIMES;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user