summaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/bindings.c8
-rw-r--r--src/main/bindings.h4
-rw-r--r--src/main/cmds.c182
-rw-r--r--src/main/cmds.h2
-rw-r--r--src/main/completion.c52
-rw-r--r--src/main/completion.h18
-rw-r--r--src/main/lsp.c108
-rw-r--r--src/main/lsp.h11
-rw-r--r--src/main/main.c55
-rw-r--r--src/main/search-replace.c209
-rw-r--r--src/main/search-replace.h2
11 files changed, 450 insertions, 201 deletions
diff --git a/src/main/bindings.c b/src/main/bindings.c
index 7b25c7b..889c32b 100644
--- a/src/main/bindings.c
+++ b/src/main/bindings.c
@@ -72,6 +72,10 @@ void set_default_buffer_bindings(struct keymap *keymap) {
}
int32_t execute(struct command_ctx ctx, int argc, const char *argv[]) {
+ (void)ctx;
+ (void)argc;
+ (void)argv;
+
// TODO: this should be more lib-like
return minibuffer_execute();
}
@@ -82,7 +86,7 @@ static struct command execute_minibuffer_command = {
.userdata = NULL,
};
-void init_bindings() {
+void init_bindings(void) {
g_global_keymap = keymap_create("global", 32);
g_ctrlx_map = keymap_create("c-x", 32);
g_windows_keymap = keymap_create("c-x w", 32);
@@ -203,7 +207,7 @@ uint32_t buffer_keymaps(struct buffer *buffer, struct keymap *keymaps[],
return nkeymaps;
}
-void destroy_bindings() {
+void destroy_bindings(void) {
keymap_destroy(&g_windows_keymap);
keymap_destroy(&g_global_keymap);
keymap_destroy(&g_ctrlx_map);
diff --git a/src/main/bindings.h b/src/main/bindings.h
index 4fd760a..96f20fd 100644
--- a/src/main/bindings.h
+++ b/src/main/bindings.h
@@ -4,7 +4,7 @@ struct keymap;
struct buffer;
struct binding;
-void init_bindings();
+void init_bindings(void);
typedef uint64_t buffer_keymap_id;
buffer_keymap_id buffer_add_keymap(struct buffer *buffer, struct keymap keymap);
@@ -12,4 +12,4 @@ void buffer_remove_keymap(buffer_keymap_id id);
uint32_t buffer_keymaps(struct buffer *buffer, struct keymap *keymaps[],
uint32_t max_nkeymaps);
-void destroy_bindings();
+void destroy_bindings(void);
diff --git a/src/main/cmds.c b/src/main/cmds.c
index 18f333d..40983a2 100644
--- a/src/main/cmds.c
+++ b/src/main/cmds.c
@@ -20,7 +20,12 @@
#include "completion.h"
#include "search-replace.h"
-int32_t _abort(struct command_ctx ctx, int argc, const char *argv[]) {
+static void (*g_terminate_cb)(void) = NULL;
+
+static int32_t _abort(struct command_ctx ctx, int argc, const char *argv[]) {
+ (void)argc;
+ (void)argv;
+
abort_replace();
abort_search();
abort_completion();
@@ -33,16 +38,27 @@ int32_t _abort(struct command_ctx ctx, int argc, const char *argv[]) {
int32_t unimplemented_command(struct command_ctx ctx, int argc,
const char *argv[]) {
+ (void)argc;
+ (void)argv;
minibuffer_echo("TODO: %s is not implemented", (const char *)ctx.userdata);
return 0;
}
-int32_t exit_editor(struct command_ctx ctx, int argc, const char *argv[]) {
- ((void (*)())ctx.userdata)();
+static int32_t exit_editor(struct command_ctx ctx, int argc,
+ const char *argv[]) {
+ (void)ctx;
+ (void)argc;
+ (void)argv;
+
+ if (g_terminate_cb != NULL) {
+ g_terminate_cb();
+ }
+
return 0;
}
-int32_t write_file(struct command_ctx ctx, int argc, const char *argv[]) {
+static int32_t write_file(struct command_ctx ctx, int argc,
+ const char *argv[]) {
const char *pth = NULL;
if (argc == 0) {
return minibuffer_prompt(ctx, "write to file: ");
@@ -55,7 +71,7 @@ int32_t write_file(struct command_ctx ctx, int argc, const char *argv[]) {
return 0;
}
-static void run_interactive_comp_inserted() { minibuffer_execute(); }
+static void run_interactive_comp_inserted(void) { minibuffer_execute(); }
int32_t run_interactive(struct command_ctx ctx, int argc, const char *argv[]) {
if (argc == 0) {
@@ -63,7 +79,7 @@ int32_t run_interactive(struct command_ctx ctx, int argc, const char *argv[]) {
enable_completion(minibuffer_buffer(),
((struct completion_trigger){
.kind = CompletionTrigger_Input,
- .input =
+ .data.input =
(struct completion_trigger_input){
.nchars = 0, .trigger_initially = false}}),
providers, 1, run_interactive_comp_inserted);
@@ -106,9 +122,9 @@ int32_t do_switch_buffer(struct command_ctx ctx, int argc, const char *argv[]) {
}
}
-COMMAND_FN("do-switch-buffer", do_switch_buffer, do_switch_buffer, NULL);
+COMMAND_FN("do-switch-buffer", do_switch_buffer, do_switch_buffer, NULL)
-static void switch_buffer_comp_inserted() { minibuffer_execute(); }
+static void switch_buffer_comp_inserted(void) { minibuffer_execute(); }
int32_t switch_buffer(struct command_ctx ctx, int argc, const char *argv[]) {
if (argc == 0) {
@@ -117,7 +133,7 @@ int32_t switch_buffer(struct command_ctx ctx, int argc, const char *argv[]) {
enable_completion(minibuffer_buffer(),
((struct completion_trigger){
.kind = CompletionTrigger_Input,
- .input =
+ .data.input =
(struct completion_trigger_input){
.nchars = 0, .trigger_initially = false}}),
providers, 1, switch_buffer_comp_inserted);
@@ -156,9 +172,9 @@ int32_t do_kill_buffer(struct command_ctx ctx, int argc, const char *argv[]) {
}
}
-COMMAND_FN("do-kill-buffer", do_kill_buffer, do_kill_buffer, NULL);
+COMMAND_FN("do-kill-buffer", do_kill_buffer, do_kill_buffer, NULL)
-static void kill_buffer_comp_inserted() { minibuffer_execute(); }
+static void kill_buffer_comp_inserted(void) { minibuffer_execute(); }
int32_t kill_buffer(struct command_ctx ctx, int argc, const char *argv[]) {
if (argc == 0) {
@@ -167,7 +183,7 @@ int32_t kill_buffer(struct command_ctx ctx, int argc, const char *argv[]) {
enable_completion(minibuffer_buffer(),
((struct completion_trigger){
.kind = CompletionTrigger_Input,
- .input =
+ .data.input =
(struct completion_trigger_input){
.nchars = 0, .trigger_initially = false}}),
providers, 1, kill_buffer_comp_inserted);
@@ -188,7 +204,6 @@ void timer_to_list_line(const struct timer *timer, void *userdata) {
static char buf[128];
const char *name = timer_name(timer);
- size_t namelen = strlen(name);
size_t len =
snprintf(buf, 128, "%s - %.2f ms (min: %.2f, max: %.2f)", name,
(timer_average(timer) / 1e6), timer_min(timer) / (float)1e6,
@@ -197,6 +212,8 @@ void timer_to_list_line(const struct timer *timer, void *userdata) {
}
void timers_refresh(struct buffer *buffer, void *userdata) {
+ (void)userdata;
+
buffer_set_readonly(buffer, false);
buffer_clear(buffer);
timers_for_each(timer_to_list_line, buffer);
@@ -208,6 +225,9 @@ void timers_refresh(struct buffer *buffer, void *userdata) {
}
int32_t timers(struct command_ctx ctx, int argc, const char *argv[]) {
+ (void)argc;
+ (void)argv;
+
struct buffer *b = buffers_find(ctx.buffers, "*timers*");
if (b == NULL) {
b = buffers_add(ctx.buffers, buffer_create("*timers*"));
@@ -236,7 +256,7 @@ void buffer_to_list_line(struct buffer *buffer, void *userdata) {
listbuf, begin,
(struct location){.line = begin.line, .col = begin.col + nchars},
(struct text_property){.type = TextProperty_Colors,
- .colors = (struct text_property_colors){
+ .data.colors = (struct text_property_colors){
.set_bg = false,
.set_fg = true,
.fg = Color_Green,
@@ -249,7 +269,7 @@ void buffer_to_list_line(struct buffer *buffer, void *userdata) {
(struct location){.line = begin.line,
.col = begin.col + 24 + nchars_path},
(struct text_property){.type = TextProperty_Colors,
- .colors = (struct text_property_colors){
+ .data.colors = (struct text_property_colors){
.set_bg = false,
.set_fg = true,
.fg = Color_Blue,
@@ -259,12 +279,16 @@ void buffer_to_list_line(struct buffer *buffer, void *userdata) {
listbuf, (struct location){.line = begin.line, .col = 0},
(struct location){.line = begin.line,
.col = buffer_line_length(listbuf, begin.line)},
- (struct text_property){.type = TextProperty_Data, .userdata = buffer});
+ (struct text_property){.type = TextProperty_Data,
+ .data.userdata = buffer});
}
}
int32_t buflist_visit_cmd(struct command_ctx ctx, int argc,
const char *argv[]) {
+ (void)argc;
+ (void)argv;
+
struct window *w = ctx.active_window;
struct buffer_view *bv = window_buffer_view(w);
@@ -275,7 +299,7 @@ int32_t buflist_visit_cmd(struct command_ctx ctx, int argc,
for (uint32_t propi = 0; propi < nprops; ++propi) {
struct text_property *p = props[propi];
if (p->type == TextProperty_Data) {
- window_set_buffer(w, p->userdata);
+ window_set_buffer(w, p->data.userdata);
return 0;
}
}
@@ -300,6 +324,8 @@ void buflist_refresh(struct buffer *buffer, void *userdata) {
int32_t buflist_refresh_cmd(struct command_ctx ctx, int argc,
const char *argv[]) {
+ (void)argc;
+ (void)argv;
buflist_refresh(window_buffer(ctx.active_window), ctx.buffers);
return 0;
}
@@ -310,6 +336,9 @@ static struct command buflist_refresh_command = {
};
int32_t buflist_kill_cmd(struct command_ctx ctx, int argc, const char *argv[]) {
+ (void)argc;
+ (void)argv;
+
struct window *w = ctx.active_window;
struct buffer_view *bv = window_buffer_view(w);
@@ -333,6 +362,9 @@ int32_t buflist_kill_cmd(struct command_ctx ctx, int argc, const char *argv[]) {
}
int32_t buffer_list(struct command_ctx ctx, int argc, const char *argv[]) {
+ (void)argc;
+ (void)argv;
+
struct buffer *b = buffers_find(ctx.buffers, "*buffers*");
if (b == NULL) {
b = buffers_add(ctx.buffers, buffer_create("*buffers*"));
@@ -373,7 +405,7 @@ int32_t buffer_list(struct command_ctx ctx, int argc, const char *argv[]) {
return 0;
}
-static void find_file_comp_inserted() { minibuffer_execute(); }
+static void find_file_comp_inserted(void) { minibuffer_execute(); }
static int32_t open_file(struct buffers *buffers, struct window *active_window,
const char *pth) {
@@ -412,14 +444,13 @@ static int32_t open_file(struct buffers *buffers, struct window *active_window,
}
int32_t find_file(struct command_ctx ctx, int argc, const char *argv[]) {
- const char *pth = NULL;
if (argc == 0) {
minibuffer_clear();
struct completion_provider providers[] = {path_provider()};
enable_completion(minibuffer_buffer(),
((struct completion_trigger){
.kind = CompletionTrigger_Input,
- .input =
+ .data.input =
(struct completion_trigger_input){
.nchars = 0, .trigger_initially = true}}),
providers, 1, find_file_comp_inserted);
@@ -432,7 +463,7 @@ int32_t find_file(struct command_ctx ctx, int argc, const char *argv[]) {
return 0;
}
-COMMAND_FN("find-file-internal", find_file, find_file, NULL);
+COMMAND_FN("find-file-internal", find_file, find_file, NULL)
int32_t find_file_relative(struct command_ctx ctx, int argc,
const char *argv[]) {
struct buffer *b = window_buffer(ctx.active_window);
@@ -450,7 +481,7 @@ int32_t find_file_relative(struct command_ctx ctx, int argc,
enable_completion(minibuffer_buffer(),
((struct completion_trigger){
.kind = CompletionTrigger_Input,
- .input =
+ .data.input =
(struct completion_trigger_input){
.nchars = 0, .trigger_initially = true}}),
providers, 1, find_file_comp_inserted);
@@ -481,7 +512,8 @@ int32_t find_file_relative(struct command_ctx ctx, int argc,
}
void register_global_commands(struct commands *commands,
- void (*terminate_cb)()) {
+ void (*terminate_cb)(void)) {
+ g_terminate_cb = terminate_cb;
struct command global_commands[] = {
{.name = "find-file", .fn = find_file},
{.name = "find-file-relative", .fn = find_file_relative},
@@ -492,7 +524,7 @@ void register_global_commands(struct commands *commands,
{.name = "abort", .fn = _abort},
{.name = "timers", .fn = timers},
{.name = "buffer-list", .fn = buffer_list},
- {.name = "exit", .fn = exit_editor, .userdata = terminate_cb}};
+ {.name = "exit", .fn = exit_editor}};
register_commands(commands, global_commands,
sizeof(global_commands) / sizeof(global_commands[0]));
@@ -505,6 +537,8 @@ void teardown_global_commands(void) { cleanup_search_replace(); }
#define BUFFER_VIEW_WRAPCMD(fn) \
static int32_t fn##_cmd(struct command_ctx ctx, int argc, \
const char *argv[]) { \
+ (void)argc; \
+ (void)argv; \
buffer_view_##fn(window_buffer_view(ctx.active_window)); \
return 0; \
}
@@ -512,51 +546,59 @@ void teardown_global_commands(void) { cleanup_search_replace(); }
#define BUFFER_WRAPCMD(fn) \
static int32_t fn##_cmd(struct command_ctx ctx, int argc, \
const char *argv[]) { \
+ (void)argc; \
+ (void)argv; \
buffer_##fn(window_buffer(ctx.active_window)); \
return 0; \
}
-BUFFER_WRAPCMD(to_file);
-BUFFER_WRAPCMD(reload);
-BUFFER_VIEW_WRAPCMD(kill_line);
-BUFFER_VIEW_WRAPCMD(forward_delete_char);
-BUFFER_VIEW_WRAPCMD(backward_delete_char);
-BUFFER_VIEW_WRAPCMD(delete_word);
-BUFFER_VIEW_WRAPCMD(backward_char);
-BUFFER_VIEW_WRAPCMD(backward_word);
-BUFFER_VIEW_WRAPCMD(forward_char);
-BUFFER_VIEW_WRAPCMD(forward_word);
-BUFFER_VIEW_WRAPCMD(backward_line);
-BUFFER_VIEW_WRAPCMD(forward_line);
-BUFFER_VIEW_WRAPCMD(goto_end_of_line);
-BUFFER_VIEW_WRAPCMD(goto_beginning_of_line);
-BUFFER_VIEW_WRAPCMD(newline);
-BUFFER_VIEW_WRAPCMD(indent);
-BUFFER_VIEW_WRAPCMD(indent_alt);
-BUFFER_VIEW_WRAPCMD(set_mark);
-BUFFER_VIEW_WRAPCMD(clear_mark);
-BUFFER_VIEW_WRAPCMD(copy);
-BUFFER_VIEW_WRAPCMD(cut);
-BUFFER_VIEW_WRAPCMD(paste);
-BUFFER_VIEW_WRAPCMD(paste_older);
-BUFFER_VIEW_WRAPCMD(goto_beginning);
-BUFFER_VIEW_WRAPCMD(goto_end);
-BUFFER_VIEW_WRAPCMD(undo);
-BUFFER_VIEW_WRAPCMD(sort_lines);
+BUFFER_WRAPCMD(to_file)
+BUFFER_WRAPCMD(reload)
+BUFFER_VIEW_WRAPCMD(kill_line)
+BUFFER_VIEW_WRAPCMD(forward_delete_char)
+BUFFER_VIEW_WRAPCMD(backward_delete_char)
+BUFFER_VIEW_WRAPCMD(delete_word)
+BUFFER_VIEW_WRAPCMD(backward_char)
+BUFFER_VIEW_WRAPCMD(backward_word)
+BUFFER_VIEW_WRAPCMD(forward_char)
+BUFFER_VIEW_WRAPCMD(forward_word)
+BUFFER_VIEW_WRAPCMD(backward_line)
+BUFFER_VIEW_WRAPCMD(forward_line)
+BUFFER_VIEW_WRAPCMD(goto_end_of_line)
+BUFFER_VIEW_WRAPCMD(goto_beginning_of_line)
+BUFFER_VIEW_WRAPCMD(newline)
+BUFFER_VIEW_WRAPCMD(indent)
+BUFFER_VIEW_WRAPCMD(indent_alt)
+BUFFER_VIEW_WRAPCMD(set_mark)
+BUFFER_VIEW_WRAPCMD(clear_mark)
+BUFFER_VIEW_WRAPCMD(copy)
+BUFFER_VIEW_WRAPCMD(cut)
+BUFFER_VIEW_WRAPCMD(paste)
+BUFFER_VIEW_WRAPCMD(paste_older)
+BUFFER_VIEW_WRAPCMD(goto_beginning)
+BUFFER_VIEW_WRAPCMD(goto_end)
+BUFFER_VIEW_WRAPCMD(undo)
+BUFFER_VIEW_WRAPCMD(sort_lines)
static int32_t scroll_up_cmd(struct command_ctx ctx, int argc,
const char *argv[]) {
+ (void)argc;
+ (void)argv;
+
buffer_view_backward_nlines(window_buffer_view(ctx.active_window),
window_height(ctx.active_window) - 1);
return 0;
-};
+}
static int32_t scroll_down_cmd(struct command_ctx ctx, int argc,
const char *argv[]) {
+ (void)argc;
+ (void)argv;
+
buffer_view_forward_nlines(window_buffer_view(ctx.active_window),
window_height(ctx.active_window) - 1);
return 0;
-};
+}
static int32_t goto_line(struct command_ctx ctx, int argc, const char *argv[]) {
// don't want to goto line in minibuffer
@@ -574,7 +616,7 @@ static int32_t goto_line(struct command_ctx ctx, int argc, const char *argv[]) {
if (line < 0) {
uint32_t nlines = buffer_num_lines(v->buffer);
line = -line;
- line = line >= nlines ? 0 : nlines - line;
+ line = (uint32_t)line >= nlines ? 0 : nlines - line;
} else if (line > 0) {
line = line - 1;
}
@@ -623,12 +665,18 @@ void register_buffer_commands(struct commands *commands) {
static int32_t window_close_cmd(struct command_ctx ctx, int argc,
const char *argv[]) {
+ (void)argc;
+ (void)argv;
+
window_close(ctx.active_window);
return 0;
}
static int32_t window_split_cmd(struct command_ctx ctx, int argc,
const char *argv[]) {
+ (void)argc;
+ (void)argv;
+
struct window *resa, *resb;
window_split(ctx.active_window, &resa, &resb);
return 0;
@@ -636,6 +684,9 @@ static int32_t window_split_cmd(struct command_ctx ctx, int argc,
static int32_t window_hsplit_cmd(struct command_ctx ctx, int argc,
const char *argv[]) {
+ (void)argc;
+ (void)argv;
+
struct window *resa, *resb;
window_hsplit(ctx.active_window, &resa, &resb);
return 0;
@@ -643,6 +694,9 @@ static int32_t window_hsplit_cmd(struct command_ctx ctx, int argc,
static int32_t window_vsplit_cmd(struct command_ctx ctx, int argc,
const char *argv[]) {
+ (void)argc;
+ (void)argv;
+
struct window *resa, *resb;
window_vsplit(ctx.active_window, &resa, &resb);
return 0;
@@ -650,12 +704,19 @@ static int32_t window_vsplit_cmd(struct command_ctx ctx, int argc,
static int32_t window_close_others_cmd(struct command_ctx ctx, int argc,
const char *argv[]) {
+ (void)argc;
+ (void)argv;
+
window_close_others(ctx.active_window);
return 0;
}
static int32_t window_focus_next_cmd(struct command_ctx ctx, int argc,
const char *argv[]) {
+ (void)ctx;
+ (void)argc;
+ (void)argv;
+
windows_focus_next();
return 0;
}
@@ -676,6 +737,9 @@ static int32_t window_focus_cmd(struct command_ctx ctx, int argc,
static int32_t window_focus_n_cmd(struct command_ctx ctx, int argc,
const char *argv[]) {
+ (void)argc;
+ (void)argv;
+
char *window_id = (char *)ctx.userdata;
const char *argv_[] = {window_id};
return window_focus_cmd(ctx, 1, argv_);
@@ -730,15 +794,15 @@ int32_t settings_set_cmd(struct command_ctx ctx, int argc, const char *argv[]) {
struct setting_value new_value = {.type = setting->value.type};
switch (setting->value.type) {
case Setting_Bool:
- new_value.bool_value = strncmp("true", value, 4) == 0 ||
- strncmp("yes", value, 3) == 0 ||
- strncmp("on", value, 2) == 0;
+ new_value.data.bool_value = strncmp("true", value, 4) == 0 ||
+ strncmp("yes", value, 3) == 0 ||
+ strncmp("on", value, 2) == 0;
break;
case Setting_Number:
- new_value.number_value = atol(value);
+ new_value.data.number_value = atol(value);
break;
case Setting_String:
- new_value.string_value = (char *)value;
+ new_value.data.string_value = (char *)value;
break;
}
diff --git a/src/main/cmds.h b/src/main/cmds.h
index a258ce5..324842d 100644
--- a/src/main/cmds.h
+++ b/src/main/cmds.h
@@ -1,7 +1,7 @@
struct commands;
void register_global_commands(struct commands *commands,
- void (*terminate_cb)());
+ void (*terminate_cb)(void));
void teardown_global_commands(void);
void register_buffer_commands(struct commands *commands);
diff --git a/src/main/completion.c b/src/main/completion.c
index 4ffbc46..7a002ac 100644
--- a/src/main/completion.c
+++ b/src/main/completion.c
@@ -38,7 +38,7 @@ struct completion_state {
static struct buffer *g_target_buffer = NULL;
-static void hide_completion();
+static void hide_completion(void);
static bool is_space(const struct codepoint *c) {
// TODO: utf8 whitespace and other whitespace
@@ -67,15 +67,15 @@ static struct completion_provider g_commands_provider = {
.userdata = NULL,
};
-struct completion_provider path_provider() {
+struct completion_provider path_provider(void) {
return g_path_provider;
}
-struct completion_provider buffer_provider() {
+struct completion_provider buffer_provider(void) {
return g_buffer_provider;
}
-struct completion_provider commands_provider() {
+struct completion_provider commands_provider(void) {
return g_commands_provider;
}
@@ -89,6 +89,10 @@ VEC(struct active_completion) g_active_completions;
static int32_t goto_next_completion(struct command_ctx ctx, int argc,
const char *argv[]) {
+ (void)ctx;
+ (void)argc;
+ (void)argv;
+
if (g_state.current_completion < g_state.ncompletions - 1) {
++g_state.current_completion;
}
@@ -104,6 +108,10 @@ static int32_t goto_next_completion(struct command_ctx ctx, int argc,
static int32_t goto_prev_completion(struct command_ctx ctx, int argc,
const char *argv[]) {
+ (void)ctx;
+ (void)argc;
+ (void)argv;
+
if (g_state.current_completion > 0) {
--g_state.current_completion;
}
@@ -119,6 +127,10 @@ static int32_t goto_prev_completion(struct command_ctx ctx, int argc,
static int32_t insert_completion(struct command_ctx ctx, int argc,
const char *argv[]) {
+ (void)ctx;
+ (void)argc;
+ (void)argv;
+
// is it in the popup?
struct completion *comp = &g_state.completions[g_state.current_completion];
bool done = comp->complete;
@@ -135,7 +147,7 @@ static int32_t insert_completion(struct command_ctx ctx, int argc,
return 0;
}
-static void clear_completions() {
+static void clear_completions(void) {
for (uint32_t ci = 0; ci < g_state.ncompletions; ++ci) {
free((void *)g_state.completions[ci].display);
free((void *)g_state.completions[ci].insert);
@@ -146,9 +158,9 @@ static void clear_completions() {
g_state.ncompletions = 0;
}
-COMMAND_FN("next-completion", next_completion, goto_next_completion, NULL);
-COMMAND_FN("prev-completion", prev_completion, goto_prev_completion, NULL);
-COMMAND_FN("insert-completion", insert_completion, insert_completion, NULL);
+COMMAND_FN("next-completion", next_completion, goto_next_completion, NULL)
+COMMAND_FN("prev-completion", prev_completion, goto_prev_completion, NULL)
+COMMAND_FN("insert-completion", insert_completion, insert_completion, NULL)
static void update_completions(struct buffer *buffer,
struct active_completion_ctx *ctx,
@@ -246,7 +258,7 @@ static void on_buffer_insert(struct buffer *buffer,
ctx->trigger_current_nchars += nchars;
- if (ctx->trigger_current_nchars < ctx->trigger.input.nchars) {
+ if (ctx->trigger_current_nchars < ctx->trigger.data.input.nchars) {
return;
}
@@ -267,6 +279,9 @@ static void on_buffer_insert(struct buffer *buffer,
}
static void update_completion_buffer(struct buffer *buffer, void *userdata) {
+ (void)buffer;
+ (void)userdata;
+
buffer_add_text_property(
g_target_buffer,
(struct location){.line = g_state.current_completion, .col = 0},
@@ -274,7 +289,7 @@ static void update_completion_buffer(struct buffer *buffer, void *userdata) {
.col = buffer_line_length(g_target_buffer,
g_state.current_completion)},
(struct text_property){.type = TextProperty_Colors,
- .colors = (struct text_property_colors){
+ .data.colors = (struct text_property_colors){
.set_bg = false,
.bg = 0,
.set_fg = true,
@@ -352,7 +367,7 @@ void enable_completion(struct buffer *source, struct completion_trigger trigger,
// do we want to trigger initially?
if (ctx->trigger.kind == CompletionTrigger_Input &&
- ctx->trigger.input.trigger_initially) {
+ ctx->trigger.data.input.trigger_initially) {
struct oneshot_completion *comp =
calloc(1, sizeof(struct oneshot_completion));
comp->ctx = ctx;
@@ -361,7 +376,7 @@ void enable_completion(struct buffer *source, struct completion_trigger trigger,
}
}
-static void hide_completion() {
+static void hide_completion(void) {
windows_close_popup();
if (g_state.active) {
buffer_remove_keymap(g_state.keymap_id);
@@ -369,13 +384,13 @@ static void hide_completion() {
}
}
-void abort_completion() {
+void abort_completion(void) {
hide_completion();
g_state.active = false;
clear_completions();
}
-bool completion_active() {
+bool completion_active(void) {
return popup_window_visible() &&
window_buffer(popup_window()) == g_target_buffer && g_state.active;
}
@@ -391,7 +406,7 @@ static void cleanup_active_comp_ctx(void *userdata) {
free(ctx);
}
-static void do_nothing(void *userdata) {}
+static void do_nothing(void *userdata) { (void)userdata; }
static void cleanup_active_completion(struct active_completion *comp) {
buffer_remove_delete_hook(comp->buffer, comp->remove_hook_id, do_nothing);
@@ -410,7 +425,7 @@ void disable_completion(struct buffer *buffer) {
}
}
-void destroy_completion() {
+void destroy_completion(void) {
// clean up any active completions we might have
VEC_FOR_EACH(&g_active_completions, struct active_completion * comp) {
cleanup_active_completion(comp);
@@ -429,10 +444,10 @@ static int cmp_completions(const void *comp_a, const void *comp_b) {
}
static uint32_t complete_path(struct completion_context ctx, void *userdata) {
+ (void)userdata;
// obtain path from the buffer
struct text_chunk txt = {0};
- uint32_t start_idx = 0;
if (ctx.buffer == minibuffer_buffer()) {
txt = minibuffer_content();
} else {
@@ -455,7 +470,6 @@ static uint32_t complete_path(struct completion_context ctx, void *userdata) {
uint32_t n = 0;
char *p1 = to_abspath(path);
- size_t len = strlen(p1);
char *p2 = strdup(p1);
size_t inlen = strlen(path);
@@ -553,7 +567,6 @@ static uint32_t complete_buffers(struct completion_context ctx,
}
struct text_chunk txt = {0};
- uint32_t start_idx = 0;
if (ctx.buffer == minibuffer_buffer()) {
txt = minibuffer_content();
} else {
@@ -608,7 +621,6 @@ static uint32_t complete_commands(struct completion_context ctx,
return 0;
}
struct text_chunk txt = {0};
- uint32_t start_idx = 0;
if (ctx.buffer == minibuffer_buffer()) {
txt = minibuffer_content();
} else {
diff --git a/src/main/completion.h b/src/main/completion.h
index 28871b9..f2ce186 100644
--- a/src/main/completion.h
+++ b/src/main/completion.h
@@ -97,10 +97,10 @@ struct completion_trigger_input {
struct completion_trigger {
/** Type of trigger. */
enum completion_trigger_kind kind;
- union {
+ union completion_trigger_data {
uint32_t c;
struct completion_trigger_input input;
- };
+ } data;
};
/**
@@ -114,12 +114,12 @@ void init_completion(struct buffers *buffers, struct commands *commands);
/**
* Tear down the completion system.
*/
-void destroy_completion();
+void destroy_completion(void);
/**
* Callback for completion inserted.
*/
-typedef void (*insert_cb)();
+typedef void (*insert_cb)(void);
/**
* Enable completions in the buffer @p source.
@@ -141,7 +141,7 @@ void enable_completion(struct buffer *source, struct completion_trigger trigger,
* This provider completes filesystem paths.
* @returns A filesystem path @ref completion_provider.
*/
-struct completion_provider path_provider();
+struct completion_provider path_provider(void);
/**
* Create a new buffer completion provider.
@@ -150,7 +150,7 @@ struct completion_provider path_provider();
* buffer list.
* @returns A buffer name @ref completion_provider.
*/
-struct completion_provider buffer_provider();
+struct completion_provider buffer_provider(void);
/**
* Create a new command completion provider.
@@ -158,19 +158,19 @@ struct completion_provider buffer_provider();
* This provider completes registered command names.
* @returns A command name @ref completion_provider.
*/
-struct completion_provider commands_provider();
+struct completion_provider commands_provider(void);
/**
* Abort any active completion.
*/
-void abort_completion();
+void abort_completion(void);
/**
* Is a completion currently showing?
*
* @returns True if the completion window is showing completions.
*/
-bool completion_active();
+bool completion_active(void);
/**
* Disable completion for @ref buffer.
diff --git a/src/main/lsp.c b/src/main/lsp.c
new file mode 100644
index 0000000..d56ca07
--- /dev/null
+++ b/src/main/lsp.c
@@ -0,0 +1,108 @@
+#include "lsp.h"
+
+#include "dged/buffer.h"
+#include "dged/buffers.h"
+#include "dged/hash.h"
+#include "dged/hashmap.h"
+#include "dged/lsp.h"
+#include "dged/minibuffer.h"
+#include "dged/reactor.h"
+#include "dged/settings.h"
+
+HASHMAP_ENTRY_TYPE(lsp_entry, struct lsp *);
+
+HASHMAP(struct lsp_entry) g_lsp_clients;
+
+static struct create_data {
+ struct reactor *reactor;
+ struct buffers *buffers;
+} g_create_data;
+
+static void log_message(int type, struct s8 msg) {
+ (void)type;
+ message("%s", msg);
+}
+
+static void create_lsp_client(struct buffer *buffer, void *userdata) {
+ (void)userdata;
+
+ struct create_data *data = &g_create_data;
+ const char *id = buffer->lang.id;
+ HASHMAP_GET(&g_lsp_clients, struct lsp_entry, id, struct lsp * *lsp);
+ if (lsp == NULL) {
+ // we need to start a new server
+ struct setting *s = lang_setting(&buffer->lang, "language-server");
+ if (!s) { // no language server set
+ return;
+ }
+
+ char *const command[] = {s->value.data.string_value, NULL};
+
+ char bufname[1024] = {0};
+ snprintf(bufname, 1024, "*%s-lsp-stderr*", command[0]);
+ struct buffer *stderr_buf = buffers_find(data->buffers, bufname);
+ if (stderr_buf == NULL) {
+ struct buffer buf = buffer_create(bufname);
+ buf.lazy_row_add = false;
+ stderr_buf = buffers_add(data->buffers, buf);
+ buffer_set_readonly(stderr_buf, true);
+ }
+
+ struct lsp_client client_impl = {
+ .log_message = log_message,
+ };
+ struct lsp *new_lsp =
+ lsp_create(command, data->reactor, stderr_buf, client_impl, NULL);
+
+ if (new_lsp == NULL) {
+ minibuffer_echo("failed to create language server %s", command[0]);
+ buffers_remove(data->buffers, bufname);
+ return;
+ }
+
+ HASHMAP_APPEND(&g_lsp_clients, struct lsp_entry, id,
+ struct lsp_entry * new);
+ new->value = new_lsp;
+
+ if (lsp_start_server(new_lsp) < 0) {
+ minibuffer_echo("failed to start language server %s process.",
+ lsp_server_name(new_lsp));
+ return;
+ }
+ }
+}
+
+static void set_default_lsp(const char *lang_id, const char *server) {
+ struct language l = lang_from_id(lang_id);
+ if (!lang_is_fundamental(&l)) {
+ lang_setting_set_default(
+ &l, "language-server",
+ (struct setting_value){.type = Setting_String,
+ .data.string_value = (char *)server});
+ lang_destroy(&l);
+ }
+}
+
+void lang_servers_init(struct reactor *reactor, struct buffers *buffers) {
+ HASHMAP_INIT(&g_lsp_clients, 32, hash_name);
+
+ set_default_lsp("c", "clangd");
+ set_default_lsp("rs", "rust-analyzer");
+ set_default_lsp("python", "pylsp");
+
+ g_create_data.reactor = reactor;
+ g_create_data.buffers = buffers;
+ buffer_add_create_hook(create_lsp_client, NULL);
+}
+
+void lang_servers_update(void) {
+ HASHMAP_FOR_EACH(&g_lsp_clients, struct lsp_entry * e) {
+ lsp_update(e->value, NULL, 0);
+ }
+}
+
+void lang_servers_teardown(void) {
+ HASHMAP_FOR_EACH(&g_lsp_clients, struct lsp_entry * e) {
+ lsp_stop_server(e->value);
+ }
+}
diff --git a/src/main/lsp.h b/src/main/lsp.h
new file mode 100644
index 0000000..736282d
--- /dev/null
+++ b/src/main/lsp.h
@@ -0,0 +1,11 @@
+#ifndef _MAIN_LSP_H
+#define _MAIN_LSP_H
+
+struct reactor;
+struct buffers;
+
+void lang_servers_init(struct reactor *reactor, struct buffers *buffers);
+void lang_servers_update(void);
+void lang_servers_teardown(void);
+
+#endif
diff --git a/src/main/main.c b/src/main/main.c
index 45f72cb..fa740e8 100644
--- a/src/main/main.c
+++ b/src/main/main.c
@@ -9,6 +9,8 @@
#include <time.h>
#include <unistd.h>
+#include "config.h"
+
#include "dged/allocator.h"
#include "dged/binding.h"
#include "dged/buffer.h"
@@ -29,6 +31,10 @@
#define str(s) #s
#endif
+#ifdef LSP_ENABLE
+#include "lsp.h"
+#endif
+
#include "bindings.h"
#include "cmds.h"
#include "completion.h"
@@ -48,11 +54,16 @@ void *frame_alloc(size_t sz) {
static bool running = true;
-void terminate() { running = false; }
+void terminate(void) { running = false; }
+void terminate2(int sig) {
+ (void)sig;
+ running = false;
+}
static struct display *display = NULL;
static bool display_resized = false;
-void resized() {
+void resized(int sig) {
+ (void)sig;
if (display != NULL) {
display_resize(display);
}
@@ -61,7 +72,9 @@ void resized() {
signal(SIGWINCH, resized);
}
-void segfault() {
+void segfault(int sig) {
+ (void)sig;
+
// make an effort to restore the
// terminal to its former glory
if (display != NULL) {
@@ -73,7 +86,7 @@ void segfault() {
abort();
}
-#define INVALID_WATCH -1
+#define INVALID_WATCH (uint32_t) - 1
static void clear_buffer_props(struct buffer *buffer, void *userdata) {
(void)userdata;
@@ -139,13 +152,13 @@ void update_file_watches(struct reactor *reactor) {
}
}
-static void usage() {
+static void usage(void) {
printf("dged - a text editor for datagubbar/datagummor!\n");
printf("usage: dged [-l/--line line_number] [-e/--end] [-h/--help] "
"[filename]\n");
}
-static void version() {
+static void version(void) {
printf("dged - %s\n© Albert Cervin 2024\n", DGED_VERSION);
}
@@ -194,7 +207,7 @@ int main(int argc, char *argv[]) {
setlocale(LC_ALL, "");
- signal(SIGTERM, terminate);
+ signal(SIGTERM, terminate2);
signal(SIGSEGV, segfault);
struct commands commands = command_registry_create(32);
@@ -212,7 +225,8 @@ int main(int argc, char *argv[]) {
int32_t ret = settings_from_file(settings_file_abs, &errmsgs);
if (ret > 0) {
fprintf(stderr, "Error reading settings from %s:\n", settings_file_abs);
- for (uint32_t erri = 0; erri < ret; ++erri) {
+ uint32_t nerrors = (uint32_t)ret;
+ for (uint32_t erri = 0; erri < nerrors; ++erri) {
fprintf(stderr, " - %s", errmsgs[erri]);
free(errmsgs[erri]);
}
@@ -266,7 +280,7 @@ int main(int argc, char *argv[]) {
struct setting *path_setting = settings_get("editor.grammars-path");
char *settings_path = NULL;
if (path_setting != NULL && path_setting->value.type == Setting_String) {
- settings_path = path_setting->value.string_value;
+ settings_path = path_setting->value.data.string_value;
}
const char *builtin_path = join_path(xstr(DATADIR), "grammars");
@@ -309,6 +323,10 @@ int main(int argc, char *argv[]) {
free((void *)builtin_path);
#endif
+#ifdef LSP_ENABLE
+ lang_servers_init(reactor, &buflist);
+#endif
+
struct buffer initial_buffer = buffer_create("welcome");
if (filename != NULL) {
buffer_destroy(&initial_buffer);
@@ -394,7 +412,6 @@ int main(int argc, char *argv[]) {
struct keyboard_update kbd_upd =
keyboard_update(&kbd, reactor, frame_alloc);
- uint32_t input_data_idx = 0;
for (uint32_t ki = 0; ki < kbd_upd.nkeys; ++ki) {
struct key *k = &kbd_upd.keys[ki];
@@ -416,15 +433,15 @@ int main(int argc, char *argv[]) {
if (res.found) {
switch (res.type) {
case BindingType_Command: {
- if (res.command == NULL) {
+ if (res.data.command == NULL) {
minibuffer_echo_timeout(
4, "binding found for key %s but not command", k);
} else {
- int32_t ec = execute_command(res.command, &commands, active_window,
- &buflist, 0, NULL);
+ int32_t ec = execute_command(res.data.command, &commands,
+ active_window, &buflist, 0, NULL);
if (ec != 0 && !minibuffer_displaying()) {
minibuffer_echo_timeout(4, "command %s failed with exit code %d",
- res.command->name, ec);
+ res.data.command->name, ec);
}
}
current_keymap = NULL;
@@ -443,7 +460,7 @@ int main(int argc, char *argv[]) {
minibuffer_echo("%s", keyname);
}
- current_keymap = res.keymap;
+ current_keymap = res.data.keymap;
break;
}
}
@@ -469,6 +486,10 @@ int main(int argc, char *argv[]) {
update_file_watches(reactor);
+#if defined(LSP_ENABLE)
+ lang_servers_update();
+#endif
+
// calculate frame time
frame_time = timer_average(update_windows) +
timer_average(update_keyboard) + timer_average(update_display);
@@ -489,6 +510,10 @@ int main(int argc, char *argv[]) {
syntax_teardown();
#endif
+#ifdef LSP_ENABLE
+ lang_servers_teardown();
+#endif
+
display_clear(display);
display_destroy(display);
destroy_bindings();
diff --git a/src/main/search-replace.c b/src/main/search-replace.c
index 50beb1e..32c514c 100644
--- a/src/main/search-replace.c
+++ b/src/main/search-replace.c
@@ -45,6 +45,55 @@ static struct search {
buffer_keymap_id keymap_id;
} g_current_search = {0};
+static void highlight_match(struct buffer *buffer, struct region match,
+ bool current) {
+ if (current) {
+ buffer_add_text_property(
+ buffer, match.begin, match.end,
+ (struct text_property){.type = TextProperty_Colors,
+ .data.colors = (struct text_property_colors){
+ .set_bg = true,
+ .bg = 3,
+ .set_fg = true,
+ .fg = 0,
+ }});
+
+ } else {
+ buffer_add_text_property(
+ buffer, match.begin, match.end,
+ (struct text_property){.type = TextProperty_Colors,
+ .data.colors = (struct text_property_colors){
+ .set_bg = true,
+ .bg = 6,
+ .set_fg = true,
+ .fg = 0,
+ }});
+ }
+}
+
+static void search_highlight_hook(struct buffer *buffer, void *userdata) {
+ (void)userdata;
+
+ for (uint32_t matchi = 0; matchi < g_current_search.nmatches; ++matchi) {
+ highlight_match(buffer, g_current_search.matches[matchi],
+ matchi == g_current_search.current_match);
+ }
+}
+
+static void replace_highlight_hook(struct buffer *buffer, void *userdata) {
+ (void)userdata;
+
+ for (uint32_t matchi = 0; matchi < g_current_replace.nmatches; ++matchi) {
+ struct match *m = &g_current_replace.matches[matchi];
+ if (m->state != Todo) {
+ continue;
+ }
+
+ highlight_match(buffer, m->region,
+ matchi == g_current_replace.current_match);
+ }
+}
+
static void clear_replace(void) {
buffer_remove_keymap(g_current_replace.keymap_id);
free(g_current_replace.matches);
@@ -89,6 +138,36 @@ void abort_search(void) {
minibuffer_abort_prompt();
}
+static void start_search(struct buffer *buffer, const char *pattern) {
+ if (buffer != g_current_search.buffer) {
+ clear_search();
+ }
+
+ g_current_search.buffer = buffer;
+ g_current_search.active = true;
+
+ // if we are in a new buffer, add the update hook for it.
+ if (g_current_search.highlight_hook == (uint32_t)-1) {
+ g_current_search.highlight_hook =
+ buffer_add_update_hook(buffer, search_highlight_hook, NULL);
+ }
+
+ // replace the pattern if needed
+ if (g_current_search.pattern == NULL ||
+ !s8eq(s8(g_current_search.pattern), s8(pattern))) {
+ char *new_pattern = strdup(pattern);
+ free(g_current_search.pattern);
+ g_current_search.pattern = new_pattern;
+ }
+
+ // clear out any old search results
+ if (g_current_search.matches != NULL) {
+ free(g_current_search.matches);
+ g_current_search.matches = NULL;
+ g_current_search.nmatches = 0;
+ }
+}
+
uint64_t matchdist(struct region *match, struct location loc) {
struct location begin = match->begin;
@@ -98,64 +177,21 @@ uint64_t matchdist(struct region *match, struct location loc) {
// into the line it is, otherwise check the distance from location
int64_t coldist = begin.col;
if (linedist == 0) {
- int64_t coldist = (int64_t)begin.col - (int64_t)loc.col;
+ coldist = (int64_t)begin.col - (int64_t)loc.col;
}
// arbitrary row scaling, best effort to avoid counting line length
+ // this is not technically correct if you have lines longer than
+ // 1e6 but otoh, that seems excessive
return (linedist * linedist) * 1e6 + coldist * coldist;
}
-static void highlight_match(struct buffer *buffer, struct region match,
- bool current) {
- if (current) {
- buffer_add_text_property(
- buffer, match.begin, match.end,
- (struct text_property){.type = TextProperty_Colors,
- .colors = (struct text_property_colors){
- .set_bg = true,
- .bg = 3,
- .set_fg = true,
- .fg = 0,
- }});
-
- } else {
- buffer_add_text_property(
- buffer, match.begin, match.end,
- (struct text_property){.type = TextProperty_Colors,
- .colors = (struct text_property_colors){
- .set_bg = true,
- .bg = 6,
- .set_fg = true,
- .fg = 0,
- }});
- }
-}
-
-static void search_highlight_hook(struct buffer *buffer, void *userdata) {
- (void)userdata;
-
- for (uint32_t matchi = 0; matchi < g_current_search.nmatches; ++matchi) {
- highlight_match(buffer, g_current_search.matches[matchi],
- matchi == g_current_search.current_match);
- }
-}
-
-static void replace_highlight_hook(struct buffer *buffer, void *userdata) {
- (void)userdata;
-
- for (uint32_t matchi = 0; matchi < g_current_replace.nmatches; ++matchi) {
- struct match *m = &g_current_replace.matches[matchi];
- if (m->state != Todo) {
- continue;
- }
-
- highlight_match(buffer, m->region,
- matchi == g_current_replace.current_match);
- }
-}
-
static int32_t replace_next(struct command_ctx ctx, int argc,
const char *argv[]) {
+ (void)ctx;
+ (void)argc;
+ (void)argv;
+
struct replace *state = &g_current_replace;
struct buffer_view *buffer_view = window_buffer_view(state->window);
struct buffer *buffer = buffer_view->buffer;
@@ -207,6 +243,10 @@ static int32_t replace_next(struct command_ctx ctx, int argc,
}
static int32_t skip_next(struct command_ctx ctx, int argc, const char *argv[]) {
+ (void)ctx;
+ (void)argc;
+ (void)argv;
+
struct replace *state = &g_current_replace;
struct buffer_view *buffer_view = window_buffer_view(state->window);
@@ -230,8 +270,8 @@ static int32_t skip_next(struct command_ctx ctx, int argc, const char *argv[]) {
return 0;
}
-COMMAND_FN("replace-next", replace_next, replace_next, NULL);
-COMMAND_FN("skip-next", skip_next, skip_next, NULL);
+COMMAND_FN("replace-next", replace_next, replace_next, NULL)
+COMMAND_FN("skip-next", skip_next, skip_next, NULL)
static int cmp_matches(const void *m1, const void *m2) {
struct region *match1 = (struct region *)m1;
@@ -350,35 +390,9 @@ static struct region *find_closest(struct region *matches, uint32_t nmatches,
return closest;
}
-static void do_search(struct buffer_view *view, const char *pattern,
+static bool do_search(struct buffer_view *view, const char *pattern,
bool reverse) {
- if (view->buffer != g_current_search.buffer) {
- clear_search();
- }
-
- g_current_search.buffer = view->buffer;
- g_current_search.active = true;
-
- // if we are in a new buffer, add the update hook for it.
- if (g_current_search.highlight_hook == (uint32_t)-1) {
- g_current_search.highlight_hook =
- buffer_add_update_hook(view->buffer, search_highlight_hook, NULL);
- }
-
- // replace the pattern if needed
- if (g_current_search.pattern == NULL ||
- !s8eq(s8(g_current_search.pattern), s8(pattern))) {
- char *new_pattern = strdup(pattern);
- free(g_current_search.pattern);
- g_current_search.pattern = new_pattern;
- }
-
- // clear out any old search results first
- if (g_current_search.matches != NULL) {
- free(g_current_search.matches);
- g_current_search.matches = NULL;
- g_current_search.nmatches = 0;
- }
+ start_search(view->buffer, pattern);
buffer_find(view->buffer, g_current_search.pattern, &g_current_search.matches,
&g_current_search.nmatches);
@@ -391,10 +405,10 @@ static void do_search(struct buffer_view *view, const char *pattern,
view->dot, reverse, &closest_idx);
buffer_view_goto(view, closest->begin);
g_current_search.current_match = closest_idx;
- } else {
- abort_search();
- minibuffer_echo_timeout(4, "%s not found", pattern);
+ return true;
}
+
+ return false;
}
static const char *get_pattern() {
@@ -424,12 +438,18 @@ int32_t search_interactive(struct command_ctx ctx, int argc,
}
minibuffer_set_prompt(search_prompt(*(bool *)ctx.userdata));
+ buffer_view_goto_end(window_buffer_view(minibuffer_window()));
if (pattern != NULL) {
- do_search(window_buffer_view(minibuffer_target_window()), pattern,
- *(bool *)ctx.userdata);
+ if (!do_search(window_buffer_view(minibuffer_target_window()), pattern,
+ *(bool *)ctx.userdata)) {
+ abort_search();
+ minibuffer_echo_timeout(4, "%s not found", pattern);
+ }
+
free((char *)pattern);
}
+
return 0;
}
@@ -437,11 +457,13 @@ static bool search_dir_backward = true;
static bool search_dir_forward = false;
COMMAND_FN("search-forward", search_forward, search_interactive,
- &search_dir_forward);
+ &search_dir_forward)
COMMAND_FN("search-backward", search_backward, search_interactive,
- &search_dir_backward);
+ &search_dir_backward)
int32_t find(struct command_ctx ctx, int argc, const char *argv[]) {
+ (void)argv;
+
bool reverse = *(bool *)ctx.userdata;
if (argc == 0) {
struct binding bindings[] = {
@@ -454,17 +476,21 @@ int32_t find(struct command_ctx ctx, int argc, const char *argv[]) {
return minibuffer_prompt(ctx, search_prompt(reverse));
}
+ // allow enter to end the interactive search
if (g_current_search.active) {
abort_search();
return 0;
}
buffer_remove_keymap(g_current_search.keymap_id);
- do_search(window_buffer_view(ctx.active_window), argv[0], reverse);
+ bool found =
+ do_search(window_buffer_view(ctx.active_window), argv[0], reverse);
- if (g_current_search.active) {
- abort_search();
+ abort_search();
+ if (!found) {
+ minibuffer_echo_timeout(4, "%s not found", argv[0]);
}
+
return 0;
}
@@ -481,11 +507,10 @@ void register_search_replace_commands(struct commands *commands) {
}
void cleanup_search_replace(void) {
+ clear_replace();
clear_search();
if (g_current_search.pattern != NULL) {
free(g_current_search.pattern);
g_current_search.pattern = NULL;
}
-
- clear_replace();
}
diff --git a/src/main/search-replace.h b/src/main/search-replace.h
index 16869fc..ef5e0dc 100644
--- a/src/main/search-replace.h
+++ b/src/main/search-replace.h
@@ -3,7 +3,7 @@ struct commands;
/**
* Abort a replace currently in progress.
*/
-void abort_replace();
+void abort_replace(void);
/**
* Abort a search currently in progress.