summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/binding.c19
-rw-r--r--src/binding.h21
-rw-r--r--src/buffer.c37
-rw-r--r--src/buffer.h13
-rw-r--r--src/buffers.c42
-rw-r--r--src/buffers.h17
-rw-r--r--src/command.c68
-rw-r--r--src/command.h15
-rw-r--r--src/keyboard.c18
-rw-r--r--src/keyboard.h11
-rw-r--r--src/main.c109
-rw-r--r--src/minibuffer.c100
-rw-r--r--src/minibuffer.h7
-rw-r--r--src/window.c9
-rw-r--r--src/window.h15
15 files changed, 388 insertions, 113 deletions
diff --git a/src/binding.c b/src/binding.c
index 5147c97..a0946ee 100644
--- a/src/binding.c
+++ b/src/binding.c
@@ -36,26 +36,37 @@ void keymap_destroy(struct keymap *keymap) {
struct lookup_result lookup_key(struct keymap *keymaps, uint32_t nkeymaps,
struct key *key, struct commands *commands) {
- // lookup in order in the keymaps
- for (uint32_t kmi = 0; kmi < nkeymaps; ++kmi) {
+ // lookup in reverse order in the keymaps
+ uint32_t kmi = nkeymaps;
+ while (kmi > 0) {
+ --kmi;
struct keymap *keymap = &keymaps[kmi];
for (uint32_t bi = 0; bi < keymap->nbindings; ++bi) {
struct binding *binding = &keymap->bindings[bi];
if (key_equal(key, &binding->key)) {
- if (binding->type == BindingType_Command) {
+ switch (binding->type) {
+ case BindingType_Command: {
return (struct lookup_result){
.found = true,
.type = BindingType_Command,
.command = lookup_command_by_hash(commands, binding->command),
};
- } else if (binding->type == BindingType_Keymap) {
+ }
+ case BindingType_Keymap: {
return (struct lookup_result){
.found = true,
.type = BindingType_Keymap,
.keymap = binding->keymap,
};
}
+ case BindingType_DirectCommand:
+ return (struct lookup_result){
+ .found = true,
+ .type = BindingType_Command,
+ .command = binding->direct_command,
+ };
+ }
}
}
}
diff --git a/src/binding.h b/src/binding.h
index bfde9fc..18a7278 100644
--- a/src/binding.h
+++ b/src/binding.h
@@ -7,20 +7,34 @@ struct keymap {
uint32_t capacity;
};
-enum binding_type { BindingType_Command, BindingType_Keymap };
+enum binding_type {
+ BindingType_Command,
+ BindingType_Keymap,
+ BindingType_DirectCommand
+};
-#define BINDING(mod_, c_, command_) \
+#define BINDING_INNER(mod_, c_, command_) \
(struct binding) { \
.key = {.mod = mod_, .key = c_}, .type = BindingType_Command, \
.command = hash_command_name(command_) \
}
-#define PREFIX(mod_, c_, keymap_) \
+#define ANONYMOUS_BINDING_INNER(mod_, c_, command_) \
+ (struct binding) { \
+ .key = {.mod = mod_, .key = c_}, .type = BindingType_DirectCommand, \
+ .direct_command = command_ \
+ }
+
+#define PREFIX_INNER(mod_, c_, keymap_) \
(struct binding) { \
.key = {.mod = mod_, .key = c_}, .type = BindingType_Keymap, \
.keymap = keymap_ \
}
+#define BINDING(...) BINDING_INNER(__VA_ARGS__)
+#define PREFIX(...) PREFIX_INNER(__VA_ARGS__)
+#define ANONYMOUS_BINDING(...) ANONYMOUS_BINDING_INNER(__VA_ARGS__)
+
struct binding {
struct key key;
@@ -28,6 +42,7 @@ struct binding {
union {
uint32_t command;
+ struct command *direct_command;
struct keymap *keymap;
};
};
diff --git a/src/buffer.c b/src/buffer.c
index 5cf1cb8..c3d2925 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -6,6 +6,7 @@
#include "utf8.h"
#include <fcntl.h>
+#include <libgen.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -26,10 +27,10 @@ struct update_hook_result buffer_modeline_hook(struct buffer *buffer,
uint64_t frame_time,
void *userdata);
-struct buffer buffer_create(const char *name, bool modeline) {
+struct buffer buffer_create(char *name, bool modeline) {
struct buffer b =
(struct buffer){.filename = NULL,
- .name = name,
+ .name = strdup(name),
.text = text_create(10),
.dot_col = 0,
.dot_line = 0,
@@ -43,14 +44,14 @@ struct buffer buffer_create(const char *name, bool modeline) {
b.keymaps[0] = keymap_create("buffer-default", 128);
struct binding bindings[] = {
BINDING(Ctrl, 'B', "backward-char"),
- BINDING(Spec, 'D', "backward-char"),
+ BINDING(LEFT, "backward-char"),
BINDING(Ctrl, 'F', "forward-char"),
- BINDING(Spec, 'C', "forward-char"),
+ BINDING(RIGHT, "forward-char"),
BINDING(Ctrl, 'P', "backward-line"),
- BINDING(Spec, 'A', "backward-line"),
+ BINDING(UP, "backward-line"),
BINDING(Ctrl, 'N', "forward-line"),
- BINDING(Spec, 'B', "forward-line"),
+ BINDING(DOWN, "forward-line"),
BINDING(Ctrl, 'A', "beginning-of-line"),
BINDING(Ctrl, 'E', "end-of-line"),
@@ -59,8 +60,9 @@ struct buffer buffer_create(const char *name, bool modeline) {
BINDING(Ctrl, 'I', "indent"),
BINDING(Ctrl, 'K', "kill-line"),
- BINDING(Spec, '3', "delete-char"),
- BINDING(Ctrl, '?', "backward-delete-char"),
+ BINDING(DELETE, "delete-char"),
+ BINDING(Ctrl, 'D', "delete-char"),
+ BINDING(BACKSPACE, "backward-delete-char"),
};
keymap_bind_keys(&b.keymaps[0], bindings,
sizeof(bindings) / sizeof(bindings[0]));
@@ -81,6 +83,8 @@ struct buffer buffer_create(const char *name, bool modeline) {
void buffer_destroy(struct buffer *buffer) {
text_destroy(buffer->text);
free(buffer->text);
+ free(buffer->name);
+ free(buffer->filename);
}
void buffer_clear(struct buffer *buffer) {
@@ -100,8 +104,9 @@ uint32_t buffer_keymaps(struct buffer *buffer, struct keymap **keymaps_out) {
void buffer_add_keymap(struct buffer *buffer, struct keymap *keymap) {
if (buffer->nkeymaps == buffer->nkeymaps_max) {
- // TODO: better
- return;
+ buffer->nkeymaps_max *= 2;
+ buffer->keymaps =
+ realloc(buffer->keymaps, sizeof(struct keymap) * buffer->nkeymaps_max);
}
buffer->keymaps[buffer->nkeymaps] = *keymap;
++buffer->nkeymaps;
@@ -174,9 +179,9 @@ void buffer_end_of_line(struct buffer *buffer) {
void buffer_beginning_of_line(struct buffer *buffer) { buffer->dot_col = 0; }
-struct buffer buffer_from_file(const char *filename, struct reactor *reactor) {
- struct buffer b = buffer_create(filename, true);
- b.filename = filename;
+struct buffer buffer_from_file(char *filename) {
+ struct buffer b = buffer_create(basename((char *)filename), true);
+ b.filename = strdup(filename);
if (access(b.filename, F_OK) == 0) {
FILE *file = fopen(filename, "r");
@@ -297,7 +302,7 @@ void render_line(struct text_chunk *line, void *userdata) {
if (cmdbuf->width > line->nchars) {
command_list_draw_repeated(cmdbuf->cmds, col, visual_line, ' ',
- cmdbuf->width - line->nchars);
+ cmdbuf->width - col + cmdbuf->col_offset);
}
}
@@ -520,3 +525,7 @@ void buffer_update(struct buffer *buffer, uint32_t width, uint32_t height,
*relline = rel_line < 0 ? 0 : (uint32_t)rel_line + total_margins.top;
*relcol = rel_col < 0 ? 0 : (uint32_t)rel_col + total_margins.left;
}
+
+struct text_chunk buffer_get_line(struct buffer *buffer, uint32_t line) {
+ return text_get_line(buffer->text, line);
+}
diff --git a/src/buffer.h b/src/buffer.h
index cf9c269..dcc4a8c 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -4,6 +4,7 @@
#include "command.h"
#include "text.h"
+#include "window.h"
struct keymap;
struct reactor;
@@ -48,8 +49,8 @@ struct modeline {
};
struct buffer {
- const char *name;
- const char *filename;
+ char *name;
+ char *filename;
struct text *text;
@@ -67,7 +68,7 @@ struct buffer {
struct update_hooks update_hooks;
};
-struct buffer buffer_create(const char *name, bool modeline);
+struct buffer buffer_create(char *name, bool modeline);
void buffer_destroy(struct buffer *buffer);
uint32_t buffer_keymaps(struct buffer *buffer, struct keymap **keymaps_out);
@@ -89,10 +90,12 @@ void buffer_beginning_of_line(struct buffer *buffer);
void buffer_newline(struct buffer *buffer);
void buffer_indent(struct buffer *buffer);
+struct text_chunk buffer_get_line(struct buffer *buffer, uint32_t line);
+
uint32_t buffer_add_update_hook(struct buffer *buffer, update_hook_cb hook,
void *userdata);
-struct buffer buffer_from_file(const char *filename, struct reactor *reactor);
+struct buffer buffer_from_file(char *filename);
void buffer_to_file(struct buffer *buffer);
void buffer_update(struct buffer *buffer, uint32_t width, uint32_t height,
@@ -103,7 +106,7 @@ void buffer_update(struct buffer *buffer, uint32_t width, uint32_t height,
#define BUFFER_WRAPCMD(fn) \
static int32_t fn##_cmd(struct command_ctx ctx, int argc, \
const char *argv[]) { \
- fn(ctx.current_buffer); \
+ fn(ctx.active_window->buffer); \
return 0; \
}
diff --git a/src/buffers.c b/src/buffers.c
new file mode 100644
index 0000000..479caa5
--- /dev/null
+++ b/src/buffers.c
@@ -0,0 +1,42 @@
+#include "buffers.h"
+#include "buffer.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+void buffers_init(struct buffers *buffers, uint32_t initial_capacity) {
+ buffers->buffers = calloc(initial_capacity, sizeof(struct buffer));
+ buffers->nbuffers = 0;
+ buffers->capacity = initial_capacity;
+}
+
+struct buffer *buffers_add(struct buffers *buffers, struct buffer buffer) {
+ if (buffers->nbuffers == buffers->capacity) {
+ buffers->capacity *= 2;
+ buffers->buffers =
+ realloc(buffers->buffers, sizeof(struct buffer) * buffers->capacity);
+ }
+
+ buffers->buffers[buffers->nbuffers] = buffer;
+ ++buffers->nbuffers;
+
+ return &buffers->buffers[buffers->nbuffers - 1];
+}
+
+struct buffer *buffers_find(struct buffers *buffers, const char *name) {
+ for (uint32_t bufi = 0; bufi < buffers->nbuffers; ++bufi) {
+ if (strcmp(name, buffers->buffers[bufi].name) == 0) {
+ return &buffers->buffers[bufi];
+ }
+ }
+
+ return NULL;
+}
+
+void buffers_destroy(struct buffers *buffers) {
+ for (uint32_t bufi = 0; bufi < buffers->nbuffers; ++bufi) {
+ buffer_destroy(&buffers->buffers[bufi]);
+ }
+
+ buffers->nbuffers = 0;
+}
diff --git a/src/buffers.h b/src/buffers.h
new file mode 100644
index 0000000..edf772c
--- /dev/null
+++ b/src/buffers.h
@@ -0,0 +1,17 @@
+#include <stdint.h>
+
+struct buffer;
+
+struct buffers {
+ // TODO: more buffers
+ struct buffer *buffers;
+ uint32_t nbuffers;
+ uint32_t capacity;
+};
+
+void buffers_init(struct buffers *buffers, uint32_t initial_capacity);
+
+struct buffer *buffers_add(struct buffers *buffers, struct buffer buffer);
+struct buffer *buffers_find(struct buffers *buffers, const char *name);
+
+void buffers_destroy(struct buffers *buffers);
diff --git a/src/command.c b/src/command.c
index a667750..93ede01 100644
--- a/src/command.c
+++ b/src/command.c
@@ -1,4 +1,6 @@
-#include "command.h"
+#include "buffer.h"
+#include "buffers.h"
+#include "minibuffer.h"
#include <stdlib.h>
@@ -65,10 +67,66 @@ struct command *lookup_command_by_hash(struct commands *commands,
return NULL;
}
-int32_t execute_command(struct command *command, struct buffer *current_buffer,
+int32_t execute_command(struct command *command, struct commands *commands,
+ struct window *active_window, struct buffers *buffers,
int argc, const char *argv[]) {
- return command->fn((struct command_ctx){.current_buffer = current_buffer,
- .userdata = command->userdata},
- argc, argv);
+ return command->fn(
+ (struct command_ctx){
+ .buffers = buffers,
+ .active_window = active_window,
+ .userdata = command->userdata,
+ .commands = commands,
+ .self = command,
+ },
+ argc, argv);
+}
+
+int32_t find_file(struct command_ctx ctx, int argc, const char *argv[]) {
+ const char *pth = NULL;
+ if (argc == 1) {
+ pth = argv[0];
+ ctx.active_window->buffer =
+ buffers_add(ctx.buffers, buffer_from_file((char *)pth));
+ minibuffer_echo_timeout(4, "buffer %s loaded",
+ ctx.active_window->buffer->name);
+ } else {
+ minibuffer_prompt(ctx, "find file: ");
+ }
+
+ return 0;
+}
+
+int32_t run_interactive(struct command_ctx ctx, int argc, const char *argv[]) {
+ if (argc == 0) {
+ minibuffer_prompt(ctx, "execute: ");
+ return 0;
+ }
+
+ struct command *cmd = lookup_command(ctx.commands, argv[0]);
+ if (cmd != NULL) {
+ return execute_command(cmd, ctx.commands, ctx.active_window, ctx.buffers,
+ argc - 1, argv + 1);
+ } else {
+ minibuffer_echo_timeout(4, "command %s not found", argv[0]);
+ return 11;
+ }
+}
+
+int32_t switch_buffer(struct command_ctx ctx, int argc, const char *argv[]) {
+ if (argc == 0) {
+ minibuffer_prompt(ctx, "buffer: ");
+ return 0;
+ }
+
+ const char *bufname = argv[0];
+ struct buffer *buf = buffers_find(ctx.buffers, bufname);
+
+ if (buf == NULL) {
+ minibuffer_echo_timeout(4, "buffer %s not found", bufname);
+ return 1;
+ } else {
+ ctx.active_window->buffer = buf;
+ return 0;
+ }
}
diff --git a/src/command.h b/src/command.h
index fe998ae..719422e 100644
--- a/src/command.h
+++ b/src/command.h
@@ -1,9 +1,14 @@
#include <stdint.h>
struct buffer;
+struct buffers;
+struct window;
struct command_ctx {
- struct buffer *current_buffer;
+ struct buffers *buffers;
+ struct window *active_window;
+ struct commands *commands;
+ struct command *self;
void *userdata;
};
@@ -34,7 +39,8 @@ uint32_t register_command(struct commands *commands, struct command *command);
void register_commands(struct commands *command_list, struct command *commands,
uint32_t ncommands);
-int32_t execute_command(struct command *command, struct buffer *current_buffer,
+int32_t execute_command(struct command *command, struct commands *commands,
+ struct window *active_window, struct buffers *buffers,
int argc, const char *argv[]);
uint32_t hash_command_name(const char *name);
@@ -42,3 +48,8 @@ uint32_t hash_command_name(const char *name);
struct command *lookup_command(struct commands *commands, const char *name);
struct command *lookup_command_by_hash(struct commands *commands,
uint32_t hash);
+
+// Common commands
+int32_t find_file(struct command_ctx ctx, int argc, const char *argv[]);
+int32_t run_interactive(struct command_ctx ctx, int argc, const char *argv[]);
+int32_t switch_buffer(struct command_ctx ctx, int argc, const char *argv[]);
diff --git a/src/keyboard.c b/src/keyboard.c
index 03d0bd4..e76630e 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -72,6 +72,18 @@ void parse_keys(uint8_t *bytes, uint32_t nbytes, struct key *out_keys,
(kp->mod & Spec && !(has_more && bytes[bytei + 1] == '~'))) {
++nkps;
}
+ } else if (utf8_byte_is_unicode_start(b)) {
+ kp->mod = None;
+ kp->key = 0;
+ kp->start = bytei;
+ kp->end = bytei + utf8_nbytes(bytes + bytei, nbytes - bytei, 1);
+ ++nkps;
+ } else {
+ kp->mod = None;
+ kp->key = b;
+ kp->start = bytei;
+ kp->end = bytei + 1;
+ ++nkps;
}
}
}
@@ -97,13 +109,13 @@ struct keyboard_update keyboard_update(struct keyboard *kbd,
}
}
- int nbytes = read(STDIN_FILENO, upd.raw, 32);
+ int nbytes = read(STDIN_FILENO, upd.raw, 64);
if (nbytes > 0) {
upd.nbytes = nbytes;
parse_keys(upd.raw, upd.nbytes, upd.keys, &upd.nkeys);
- if (nbytes < 32) {
+ if (nbytes < 64) {
kbd->has_data = false;
}
} else if (nbytes == EAGAIN) {
@@ -118,7 +130,7 @@ bool key_equal_char(struct key *key, uint8_t mod, uint8_t c) {
}
bool key_equal(struct key *key1, struct key *key2) {
- return key1->key == key2->key && key1->mod == key2->mod;
+ return key_equal_char(key1, key2->mod, key2->key);
}
void key_name(struct key *key, char *buf, size_t capacity) {
diff --git a/src/keyboard.h b/src/keyboard.h
index 72c61d5..9bf36de 100644
--- a/src/keyboard.h
+++ b/src/keyboard.h
@@ -3,11 +3,20 @@
#include <stdint.h>
enum modifiers {
+ None = 0,
Ctrl = 1 << 0,
Meta = 1 << 1,
Spec = 1 << 2,
};
+#define BACKSPACE Ctrl, '?'
+#define DELETE Spec, '3'
+
+#define UP Spec, 'A'
+#define DOWN Spec, 'B'
+#define RIGHT Spec, 'C'
+#define LEFT Spec, 'D'
+
struct key {
uint8_t key;
uint8_t mod;
@@ -24,7 +33,7 @@ struct keyboard_update {
struct key keys[32];
uint32_t nkeys;
- uint8_t raw[32];
+ uint8_t raw[64];
uint32_t nbytes;
};
diff --git a/src/main.c b/src/main.c
index 028f926..4048aba 100644
--- a/src/main.c
+++ b/src/main.c
@@ -8,6 +8,7 @@
#include "binding.h"
#include "buffer.h"
+#include "buffers.h"
#include "display.h"
#include "minibuffer.h"
#include "reactor.h"
@@ -56,6 +57,7 @@ void resized() {
}
int32_t _abort(struct command_ctx ctx, int argc, const char *argv[]) {
+ minibuffer_abort_prompt();
minibuffer_echo_timeout(4, "💣 aborted");
return 0;
}
@@ -72,16 +74,9 @@ int32_t exit_editor(struct command_ctx ctx, int argc, const char *argv[]) {
}
static struct command GLOBAL_COMMANDS[] = {
- {
- .name = "find-file",
- .fn = unimplemented_command,
- .userdata = (void *)"find-file",
- },
- {
- .name = "run-command-interactive",
- .fn = unimplemented_command,
- .userdata = (void *)"run-command-interactive",
- },
+ {.name = "find-file", .fn = find_file},
+ {.name = "run-command-interactive", .fn = run_interactive},
+ {.name = "switch-buffer", .fn = switch_buffer},
{.name = "abort", .fn = _abort},
{.name = "exit", .fn = exit_editor}};
@@ -99,44 +94,8 @@ uint64_t calc_frame_time_ns(struct timespec *timers, uint32_t num_timer_pairs) {
return total;
}
-struct buffers {
- // TODO: more buffers
- struct buffer buffers[32];
- uint32_t nbuffers;
-};
-
-struct window {
- uint32_t x;
- uint32_t y;
- uint32_t width;
- uint32_t height;
- struct buffer *buffer;
-};
-
-void window_update_buffer(struct window *window, struct command_list *commands,
- uint64_t frame_time, uint32_t *relline,
- uint32_t *relcol) {
- buffer_update(window->buffer, window->width, window->height, commands,
- frame_time, relline, relcol);
-}
-
-void buffers_init(struct buffers *buffers) { buffers->nbuffers = 0; }
-
-void buffers_add(struct buffers *buffers, struct buffer buffer) {
- buffers->buffers[buffers->nbuffers] = buffer;
- ++buffers->nbuffers;
-}
-
-void buffers_destroy(struct buffers *buffers) {
- for (uint32_t bufi = 0; bufi < buffers->nbuffers; ++bufi) {
- buffer_destroy(&buffers->buffers[bufi]);
- }
-
- buffers->nbuffers = 0;
-}
-
int main(int argc, char *argv[]) {
- const char *filename = NULL;
+ char *filename = NULL;
if (argc >= 1) {
filename = argv[1];
}
@@ -178,6 +137,7 @@ int main(int argc, char *argv[]) {
BINDING(Ctrl, 'C', "exit"),
BINDING(Ctrl, 'S', "buffer-write-to-file"),
BINDING(Ctrl, 'F', "find-file"),
+ BINDING(None, 'b', "switch-buffer"),
};
keymap_bind_keys(&global_keymap, global_binds,
sizeof(global_binds) / sizeof(global_binds[0]));
@@ -185,21 +145,19 @@ int main(int argc, char *argv[]) {
sizeof(ctrlx_bindings) / sizeof(ctrlx_bindings[0]));
struct buffers buflist = {0};
- buffers_init(&buflist);
+ buffers_init(&buflist, 32);
struct buffer initial_buffer = buffer_create("welcome", true);
if (filename != NULL) {
- initial_buffer = buffer_from_file(filename, &reactor);
+ initial_buffer = buffer_from_file(filename);
} else {
const char *welcome_txt = "Welcome to the editor for datagubbar 👴\n";
buffer_add_text(&initial_buffer, (uint8_t *)welcome_txt,
strlen(welcome_txt));
}
- buffers_add(&buflist, initial_buffer);
-
// one main window
struct window main_window = (struct window){
- .buffer = &initial_buffer,
+ .buffer = buffers_add(&buflist, initial_buffer),
.height = display.height - 1,
.width = display.width,
.x = 0,
@@ -207,12 +165,12 @@ int main(int argc, char *argv[]) {
};
// and one for the minibuffer
- struct buffer minibuffer = buffer_create("minibuffer", false);
- buffers_add(&buflist, minibuffer);
+ struct buffer *minibuffer =
+ buffers_add(&buflist, buffer_create("minibuffer", false));
- minibuffer_init(&minibuffer);
+ minibuffer_init(minibuffer);
struct window minibuffer_window = (struct window){
- .buffer = &minibuffer,
+ .buffer = minibuffer,
.x = 0,
.y = display.height - 1,
.height = 1,
@@ -289,20 +247,14 @@ int main(int argc, char *argv[]) {
clock_gettime(CLOCK_MONOTONIC, &keyboard_begin);
struct keymap *local_keymaps = NULL;
- uint32_t nbuffer_keymaps = buffer_keymaps(&initial_buffer, &local_keymaps);
+ uint32_t nbuffer_keymaps =
+ buffer_keymaps(active_window->buffer, &local_keymaps);
struct keyboard_update kbd_upd = keyboard_update(&kbd, &reactor);
uint32_t input_data_idx = 0;
for (uint32_t ki = 0; ki < kbd_upd.nkeys; ++ki) {
struct key *k = &kbd_upd.keys[ki];
- // insert any data from last key
- if (k->start > input_data_idx) {
- buffer_add_text(active_window->buffer, &kbd_upd.raw[input_data_idx],
- k->start - input_data_idx);
- }
- input_data_idx = k->end;
-
struct lookup_result res = {.found = false};
if (current_keymap != NULL) {
res = lookup_key(current_keymap, 1, k, &commands);
@@ -321,9 +273,9 @@ int main(int argc, char *argv[]) {
minibuffer_echo_timeout(
4, "binding found for key %s but not command", k);
} else {
- int32_t ec =
- execute_command(res.command, active_window->buffer, 0, NULL);
- if (ec != 0) {
+ int32_t ec = execute_command(res.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);
}
@@ -334,22 +286,26 @@ int main(int argc, char *argv[]) {
case BindingType_Keymap: {
char keyname[16];
key_name(k, keyname, 16);
- minibuffer_echo("%s", keyname);
current_keymap = res.keymap;
+ minibuffer_echo("%s", current_keymap->name);
break;
}
}
+ } else if (k->mod == 0) {
+ buffer_add_text(active_window->buffer, &kbd_upd.raw[k->start],
+ k->end - k->start);
} else {
char keyname[16];
key_name(k, keyname, 16);
- minibuffer_echo_timeout(4, "key \"%s\" is not bound!", keyname);
+ if (current_keymap == NULL) {
+ minibuffer_echo_timeout(4, "key \"%s\" is not bound!", keyname);
+ } else {
+ minibuffer_echo_timeout(4, "key \"%s %s\" is not bound!",
+ current_keymap->name, keyname);
+ }
current_keymap = NULL;
}
}
- if (input_data_idx < kbd_upd.nbytes) {
- buffer_add_text(active_window->buffer, &kbd_upd.raw[input_data_idx],
- kbd_upd.nbytes - input_data_idx);
- }
clock_gettime(CLOCK_MONOTONIC, &keyboard_end);
// calculate frame time
@@ -357,6 +313,13 @@ int main(int argc, char *argv[]) {
display_end, keyboard_begin, keyboard_end};
frame_time = calc_frame_time_ns(timers, 3);
+ if (minibuffer_focused()) {
+ active_window = &minibuffer_window;
+ } else {
+ // TODO: no
+ active_window = &main_window;
+ }
+
frame_allocator_clear(&frame_allocator);
}
diff --git a/src/minibuffer.c b/src/minibuffer.c
index b622ab0..a424af8 100644
--- a/src/minibuffer.c
+++ b/src/minibuffer.c
@@ -1,16 +1,77 @@
#include "minibuffer.h"
+#include "binding.h"
#include "buffer.h"
#include "display.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
static struct minibuffer {
struct buffer *buffer;
struct timespec expires;
+ char prompt[128];
+ struct command_ctx prompt_command_ctx;
+ bool prompt_active;
+ struct keymap keymap;
} g_minibuffer = {0};
+void draw_prompt(struct text_chunk *line_data, uint32_t line,
+ struct command_list *commands, void *userdata) {
+ uint32_t len = strlen(g_minibuffer.prompt);
+ command_list_set_index_color_fg(commands, 4);
+ command_list_draw_text(commands, 0, line, (uint8_t *)g_minibuffer.prompt,
+ len);
+ command_list_reset_color(commands);
+}
+
+int32_t execute(struct command_ctx ctx, int argc, const char *argv[]) {
+ if (g_minibuffer.prompt_active) {
+ struct text_chunk line = buffer_get_line(g_minibuffer.buffer, 0);
+ char *l = (char *)malloc(line.nbytes + 1);
+ memcpy(l, line.text, line.nbytes);
+
+ // split on ' '
+ const char *argv[128] = {l};
+ argc = 1;
+ for (uint32_t bytei = 0; bytei < line.nbytes; ++bytei) {
+ uint8_t byte = line.text[bytei];
+ if (byte == ' ') {
+ l[bytei] = '\0';
+ argv[argc] = l + bytei;
+ ++argc;
+ }
+ }
+
+ minibuffer_abort_prompt();
+ struct command_ctx *ctx = &g_minibuffer.prompt_command_ctx;
+ uint32_t res = execute_command(ctx->self, ctx->commands, ctx->active_window,
+ ctx->buffers, argc, argv);
+
+ free(l);
+ return res;
+ } else {
+ return 0;
+ }
+}
+
+struct command execute_minibuffer_command = {
+ .fn = execute,
+ .name = "minibuffer-execute",
+ .userdata = NULL,
+};
+
+int32_t complete(struct command_ctx ctx, int argc, const char *argv[]) {
+ return 0;
+}
+
+struct command complete_minibuffer_command = {
+ .fn = complete,
+ .name = "minibuffer-complete",
+ .userdata = NULL,
+};
+
struct update_hook_result update(struct buffer *buffer,
struct command_list *commands, uint32_t width,
uint32_t height, uint64_t frame_time,
@@ -18,19 +79,36 @@ struct update_hook_result update(struct buffer *buffer,
struct timespec current;
struct minibuffer *mb = (struct minibuffer *)userdata;
clock_gettime(CLOCK_MONOTONIC, &current);
- if (current.tv_sec >= mb->expires.tv_sec) {
+ if (!mb->prompt_active && current.tv_sec >= mb->expires.tv_sec) {
buffer_clear(buffer);
}
- return (struct update_hook_result){0};
+ struct update_hook_result res = {0};
+ if (g_minibuffer.prompt_active) {
+ res.margins.left = strlen(g_minibuffer.prompt);
+ res.line_render_hook.callback = draw_prompt;
+ }
+
+ return res;
}
void minibuffer_init(struct buffer *buffer) {
g_minibuffer.buffer = buffer;
+ struct binding bindings[] = {
+ ANONYMOUS_BINDING(Ctrl, 'M', &execute_minibuffer_command),
+ ANONYMOUS_BINDING(Ctrl, 'I', &complete_minibuffer_command),
+ };
+ keymap_bind_keys(&g_minibuffer.keymap, bindings,
+ sizeof(bindings) / sizeof(bindings[0]));
+ buffer_add_keymap(g_minibuffer.buffer, &g_minibuffer.keymap);
buffer_add_update_hook(g_minibuffer.buffer, update, &g_minibuffer);
}
void echo(uint32_t timeout, const char *fmt, va_list args) {
+ if (g_minibuffer.prompt_active) {
+ return;
+ }
+
char buff[2048];
size_t nbytes = vsnprintf(buff, 2048, fmt, args);
@@ -58,5 +136,21 @@ void minibuffer_echo_timeout(uint32_t timeout, const char *fmt, ...) {
va_end(args);
}
+void minibuffer_prompt(struct command_ctx command_ctx, const char *fmt, ...) {
+ minibuffer_clear();
+ g_minibuffer.prompt_active = true;
+ g_minibuffer.prompt_command_ctx = command_ctx;
+ va_list args;
+ va_start(args, fmt);
+ vsnprintf(g_minibuffer.prompt, sizeof(g_minibuffer.prompt), fmt, args);
+ va_end(args);
+}
+
+void minibuffer_abort_prompt() {
+ minibuffer_clear();
+ g_minibuffer.prompt_active = false;
+}
+
bool minibuffer_displaying() { return !buffer_is_empty(g_minibuffer.buffer); }
-void minibuffer_clear() { g_minibuffer.expires.tv_nsec = 0; }
+void minibuffer_clear() { buffer_clear(g_minibuffer.buffer); }
+bool minibuffer_focused() { return g_minibuffer.prompt_active; }
diff --git a/src/minibuffer.h b/src/minibuffer.h
index 9bdde8f..ec24f49 100644
--- a/src/minibuffer.h
+++ b/src/minibuffer.h
@@ -4,9 +4,16 @@
#include <time.h>
struct buffer;
+struct command_ctx;
+
void minibuffer_init(struct buffer *buffer);
void minibuffer_echo(const char *fmt, ...);
void minibuffer_echo_timeout(uint32_t timeout, const char *fmt, ...);
+
+void minibuffer_prompt(struct command_ctx command_ctx, const char *fmt, ...);
+void minibuffer_abort_prompt();
+
void minibuffer_clear();
bool minibuffer_displaying();
+bool minibuffer_focused();
diff --git a/src/window.c b/src/window.c
new file mode 100644
index 0000000..5f1911a
--- /dev/null
+++ b/src/window.c
@@ -0,0 +1,9 @@
+#include "buffer.h"
+#include "display.h"
+
+void window_update_buffer(struct window *window, struct command_list *commands,
+ uint64_t frame_time, uint32_t *relline,
+ uint32_t *relcol) {
+ buffer_update(window->buffer, window->width, window->height, commands,
+ frame_time, relline, relcol);
+}
diff --git a/src/window.h b/src/window.h
new file mode 100644
index 0000000..81535a0
--- /dev/null
+++ b/src/window.h
@@ -0,0 +1,15 @@
+#include <stdint.h>
+
+struct command_list;
+
+struct window {
+ uint32_t x;
+ uint32_t y;
+ uint32_t width;
+ uint32_t height;
+ struct buffer *buffer;
+};
+
+void window_update_buffer(struct window *window, struct command_list *commands,
+ uint64_t frame_time, uint32_t *relline,
+ uint32_t *relcol);