diff options
Diffstat (limited to 'src/main.c')
| -rw-r--r-- | src/main.c | 364 |
1 files changed, 0 insertions, 364 deletions
diff --git a/src/main.c b/src/main.c deleted file mode 100644 index c0b6b0c..0000000 --- a/src/main.c +++ /dev/null @@ -1,364 +0,0 @@ -#include <getopt.h> -#include <locale.h> -#include <signal.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - -#include "allocator.h" -#include "binding.h" -#include "bits/getopt_core.h" -#include "bits/getopt_ext.h" -#include "buffer.h" -#include "buffers.h" -#include "display.h" -#include "lang.h" -#include "minibuffer.h" -#include "reactor.h" -#include "settings.h" - -struct frame_allocator frame_allocator; - -void *frame_alloc(size_t sz) { - return frame_allocator_alloc(&frame_allocator, sz); -} - -bool running = true; - -void terminate() { running = false; } - -static struct display *display = NULL; -static bool display_resized = false; -void resized() { - if (display != NULL) { - display_resize(display); - } - display_resized = true; - - signal(SIGWINCH, resized); -} - -int32_t _abort(struct command_ctx ctx, int argc, const char *argv[]) { - minibuffer_abort_prompt(); - minibuffer_echo_timeout(4, "💣 aborted"); - return 0; -} - -int32_t unimplemented_command(struct command_ctx ctx, int argc, - const char *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[]) { - terminate(); - return 0; -} - -static struct command GLOBAL_COMMANDS[] = { - {.name = "find-file", .fn = find_file}, - {.name = "write-file", .fn = write_file}, - {.name = "run-command-interactive", .fn = run_interactive}, - {.name = "switch-buffer", .fn = switch_buffer}, - {.name = "abort", .fn = _abort}, - {.name = "exit", .fn = exit_editor}}; - -uint64_t calc_frame_time_ns(struct timespec *timers, uint32_t num_timer_pairs) { - uint64_t total = 0; - for (uint32_t ti = 0; ti < num_timer_pairs * 2; ti += 2) { - struct timespec *start_timer = &timers[ti]; - struct timespec *end_timer = &timers[ti + 1]; - - total += - ((uint64_t)end_timer->tv_sec * 1e9 + (uint64_t)end_timer->tv_nsec) - - ((uint64_t)start_timer->tv_sec * 1e9 + (uint64_t)start_timer->tv_nsec); - } - - return total; -} - -void usage() { printf("TODO: print usage\n"); } - -int main(int argc, char *argv[]) { - - static struct option longopts[] = {{"line", required_argument, NULL, 'l'}, - {"end", no_argument, NULL, 'e'}, - {NULL, 0, NULL, 0}}; - - char *filename = NULL; - uint32_t jumpline = 1; - bool goto_end = false; - char ch; - while ((ch = getopt_long(argc, argv, "el:", longopts, NULL)) != -1) { - switch (ch) { - case 'l': - jumpline = atoi(optarg); - break; - case 'e': - goto_end = true; - break; - default: - usage(); - return 1; - } - } - argc -= optind; - argv += optind; - - if (argc > 1) { - fprintf(stderr, "More than one file to open is not supported\n"); - return 2; - } else if (argc == 1) { - filename = strdup(argv[0]); - } - - setlocale(LC_ALL, ""); - - signal(SIGTERM, terminate); - - struct commands commands = command_registry_create(32); - settings_init(64, &commands); - languages_init(true); - buffer_static_init(&commands); - - frame_allocator = frame_allocator_create(16 * 1024 * 1024); - - // create reactor - struct reactor *reactor = reactor_create(); - - // initialize display - display = display_create(); - display_clear(display); - signal(SIGWINCH, resized); - - // init keyboard - struct keyboard kbd = keyboard_create(reactor); - - // global commands, TODO: move these, they should exist even if main does not - register_commands(&commands, GLOBAL_COMMANDS, - sizeof(GLOBAL_COMMANDS) / sizeof(GLOBAL_COMMANDS[0])); - - // keymaps - struct keymap *current_keymap = NULL; - struct keymap global_keymap = keymap_create("global", 32); - struct keymap ctrlx_map = keymap_create("c-x", 32); - struct binding global_binds[] = { - PREFIX(Ctrl, 'X', &ctrlx_map), - BINDING(Ctrl, 'G', "abort"), - BINDING(Meta, 'x', "run-command-interactive"), - }; - struct binding ctrlx_bindings[] = { - BINDING(Ctrl, 'C', "exit"), - BINDING(Ctrl, 'S', "buffer-write-to-file"), - BINDING(Ctrl, 'F', "find-file"), - BINDING(Ctrl, 'W', "write-file"), - BINDING(None, 'b', "switch-buffer"), - }; - keymap_bind_keys(&global_keymap, global_binds, - sizeof(global_binds) / sizeof(global_binds[0])); - keymap_bind_keys(&ctrlx_map, ctrlx_bindings, - sizeof(ctrlx_bindings) / sizeof(ctrlx_bindings[0])); - - struct buffers buflist = {0}; - buffers_init(&buflist, 32); - struct buffer initial_buffer = buffer_create("welcome", true); - if (filename != NULL) { - buffer_destroy(&initial_buffer); - initial_buffer = buffer_from_file(filename); - if (goto_end) { - buffer_goto_end(&initial_buffer); - } else - buffer_goto(&initial_buffer, jumpline > 0 ? jumpline - 1 : 0, 0); - } else { - const char *welcome_txt = "Welcome to the editor for datagubbar 👴\n"; - buffer_add_text(&initial_buffer, (uint8_t *)welcome_txt, - strlen(welcome_txt)); - } - - // one main window - struct window main_window = (struct window){ - .buffer = buffers_add(&buflist, initial_buffer), - .prev_buffer = NULL, - .height = display_height(display) - 1, - .width = display_width(display), - .x = 0, - .y = 0, - }; - - // and one for the minibuffer - struct buffer minibuffer = buffer_create("minibuffer", false); - - minibuffer_init(&minibuffer); - struct window minibuffer_window = (struct window){ - .buffer = &minibuffer, - .prev_buffer = NULL, - .x = 0, - .y = display_height(display) - 1, - .height = 1, - .width = display_width(display), - }; - - struct timespec buffer_begin, buffer_end, display_begin, display_end, - keyboard_begin, keyboard_end; - - uint64_t frame_time = 0; - - struct window *windows[2] = { - &minibuffer_window, - &main_window, - }; - - struct command_list *command_lists[2] = {0}; - - // TODO: not always - struct window *active_window = &main_window; - - while (running) { - - clock_gettime(CLOCK_MONOTONIC, &buffer_begin); - - if (display_resized) { - minibuffer_window.width = display_width(display); - minibuffer_window.y = display_height(display) - 1; - - main_window.height = display_height(display) - 1; - main_window.width = display_width(display); - - display_resized = false; - } - - // update windows - uint32_t dot_line = 0, dot_col = 0; - for (uint32_t windowi = 0; windowi < sizeof(windows) / sizeof(windows[0]); - ++windowi) { - struct window *win = windows[windowi]; - // TODO: better capacity - command_lists[windowi] = - command_list_create(win->height * win->width, frame_alloc, win->x, - win->y, win->buffer->name); - - uint32_t relline, relcol; - window_update_buffer(win, command_lists[windowi], frame_time, &relline, - &relcol); - - if (win == active_window) { - dot_line = relline; - dot_col = relcol; - } - } - - clock_gettime(CLOCK_MONOTONIC, &buffer_end); - - // update screen - clock_gettime(CLOCK_MONOTONIC, &display_begin); - uint32_t relline, relcol; - - display_begin_render(display); - for (uint32_t windowi = 0; windowi < sizeof(windows) / sizeof(windows[0]); - ++windowi) { - display_render(display, command_lists[windowi]); - } - display_move_cursor(display, dot_line + active_window->y, - dot_col + active_window->x); - display_end_render(display); - clock_gettime(CLOCK_MONOTONIC, &display_end); - - // this blocks for events, so if nothing has happened we block here. - reactor_update(reactor); - - clock_gettime(CLOCK_MONOTONIC, &keyboard_begin); - struct keymap *local_keymaps = NULL; - uint32_t nbuffer_keymaps = - buffer_keymaps(active_window->buffer, &local_keymaps); - 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]; - - struct lookup_result res = {.found = false}; - if (current_keymap != NULL) { - res = lookup_key(current_keymap, 1, k, &commands); - } else { - // check first the global keymap, then the buffer ones - res = lookup_key(&global_keymap, 1, k, &commands); - if (!res.found) { - res = lookup_key(local_keymaps, nbuffer_keymaps, k, &commands); - } - } - - if (res.found) { - switch (res.type) { - case BindingType_Command: { - if (res.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); - if (ec != 0 && !minibuffer_displaying()) { - minibuffer_echo_timeout(4, "command %s failed with exit code %d", - res.command->name, ec); - } - } - current_keymap = NULL; - break; - } - case BindingType_Keymap: { - char keyname[16]; - key_name(k, keyname, 16); - 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); - 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; - } - } - clock_gettime(CLOCK_MONOTONIC, &keyboard_end); - - // calculate frame time - struct timespec timers[] = {buffer_begin, buffer_end, display_begin, - display_end, keyboard_begin, keyboard_end}; - frame_time = calc_frame_time_ns(timers, 3); - - if (minibuffer_focused()) { - active_window = &minibuffer_window; - } else { - // TODO: not this - active_window = &main_window; - } - - frame_allocator_clear(&frame_allocator); - } - - minibuffer_destroy(); - buffer_destroy(&minibuffer); - buffers_destroy(&buflist); - display_clear(display); - display_destroy(display); - keymap_destroy(&global_keymap); - keymap_destroy(&ctrlx_map); - command_registry_destroy(&commands); - reactor_destroy(reactor); - frame_allocator_destroy(&frame_allocator); - buffer_static_teardown(); - settings_destroy(); - - return 0; -} |
