Fix parsing bugs and add better indentation support

This commit is contained in:
2026-02-01 20:40:52 +00:00
parent f77caf604f
commit 8b93b955e8
17 changed files with 304 additions and 103 deletions

View File

@@ -4,8 +4,14 @@
#include "lsp/lsp.h"
#include "main.h"
#include "utils/utils.h"
#include <sys/types.h>
void cut(Editor *editor) {
if (ABS((int64_t)editor->cursor.row - (int64_t)editor->selection.row) >
1500) {
bar.log("Selection too large!");
return;
}
if (mode != SELECT)
return;
Coord start;
@@ -19,6 +25,11 @@ void cut(Editor *editor) {
}
void copy(Editor *editor) {
if (ABS((int64_t)editor->cursor.row - (int64_t)editor->selection.row) >
1500) {
bar.log("Selection too large!");
return;
}
if (mode != SELECT)
return;
uint32_t len;
@@ -72,6 +83,53 @@ void dedent_current_line(Editor *editor) {
editor->cursor.row = start.row;
}
static void move_coord_by_delta(Coord &c, uint32_t row, int64_t delta) {
if (c.row == row) {
int64_t new_col = (int64_t)c.col + delta;
c.col = (uint32_t)MAX(new_col, 0);
}
}
void indent_selection(Editor *editor) {
uint32_t top = MIN(editor->cursor.row, editor->selection.row);
uint32_t bot = MAX(editor->cursor.row, editor->selection.row);
if (bot - top > 1500) {
bar.log("Can't indent more than 1500 lines at once!");
return;
}
if (bot - top >= 2)
editor->indents.indent_block(top + 1, bot - 1);
uint32_t delta_top = editor->indents.indent_line(top);
uint32_t delta_bot =
(bot == top) ? delta_top : editor->indents.indent_line(bot);
move_coord_by_delta(editor->cursor, top, delta_top);
move_coord_by_delta(editor->selection, top, delta_top);
if (bot != top) {
move_coord_by_delta(editor->cursor, bot, delta_bot);
move_coord_by_delta(editor->selection, bot, delta_bot);
}
}
void dedent_selection(Editor *editor) {
uint32_t top = MIN(editor->cursor.row, editor->selection.row);
uint32_t bot = MAX(editor->cursor.row, editor->selection.row);
if (bot - top > 1500) {
bar.log("Can't dedent more than 1500 lines at once!");
return;
}
if (bot - top >= 2)
editor->indents.dedent_block(top + 1, bot - 1);
uint32_t delta_top = editor->indents.dedent_line(top);
uint32_t delta_bot =
(bot == top) ? delta_top : editor->indents.dedent_line(bot);
move_coord_by_delta(editor->cursor, top, -(int64_t)delta_top);
move_coord_by_delta(editor->selection, top, -(int64_t)delta_top);
if (bot != top) {
move_coord_by_delta(editor->cursor, bot, -(int64_t)delta_bot);
move_coord_by_delta(editor->selection, bot, -(int64_t)delta_bot);
}
}
void insert_char(Editor *editor, char c) {
uint32_t col = editor->cursor.col;
LineIterator *it = begin_l_iter(editor->root, editor->cursor.row);
@@ -155,9 +213,7 @@ void insert_char(Editor *editor, char c) {
{"trimFinalNewlines", true}}}}}};
LSPPending *pending = new LSPPending();
pending->editor = editor;
pending->method = "textDocument/onTypeFormatting";
pending->callback = [version](Editor *editor, std::string,
json message) {
pending->callback = [version](Editor *editor, const json &message) {
if (version != editor->lsp_version)
return;
auto &edits = message["result"];
@@ -201,11 +257,32 @@ void backspace_edit(Editor *editor) {
LineIterator *it = begin_l_iter(editor->root, editor->cursor.row);
if (!it)
return;
char *line = next_line(it, nullptr);
char prev_char = line[prev_pos.col];
char next_char = line[editor->cursor.col];
uint32_t len;
char *line = next_line(it, &len);
if (!line) {
free(it->buffer);
free(it);
return;
}
if (len > 0 && line[len - 1] == '\n')
--len;
char prev_char = (prev_pos.col < len) ? line[prev_pos.col] : 0;
char next_char = (editor->cursor.col < len) ? line[editor->cursor.col] : 0;
bool before_content = false;
if (editor->cursor.col > 0) {
before_content = true;
for (uint32_t i = 0; i < editor->cursor.col; i++)
if (line[i] != ' ' && line[i] != '\t') {
before_content = false;
break;
}
}
free(it->buffer);
free(it);
if (before_content) {
dedent_current_line(editor);
return;
}
bool is_pair = (prev_char == '{' && next_char == '}') ||
(prev_char == '(' && next_char == ')') ||
(prev_char == '[' && next_char == ']') ||
@@ -312,8 +389,7 @@ void fetch_lsp_hover(Editor *editor) {
{"position", {{"line", editor->cursor.row}, {"character", col}}}}}};
LSPPending *pending = new LSPPending();
pending->editor = editor;
pending->method = "textDocument/hover";
pending->callback = [](Editor *editor, std::string, json hover) {
pending->callback = [](Editor *editor, const json &hover) {
if (hover.contains("result") && !hover["result"].is_null()) {
auto &contents = hover["result"]["contents"];
std::string hover_text = "";