From d7e2d3d4f13c5f6e52ad36aa890eb09a650d1238 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Sun, 31 Jan 2021 15:33:21 -0500 Subject: fixed Ctrl+Left/Right being double-set, cleaned up core options code, auto-add-newline --- buffer.c | 8 ++++ command.c | 3 ++ command.h | 2 + config.c | 148 ++++++++++++++++++++++++++++++++------------------------------ node.c | 7 +++ ted.cfg | 15 ++++++- ted.h | 1 + 7 files changed, 111 insertions(+), 73 deletions(-) diff --git a/buffer.c b/buffer.c index 3649a68..41c5d09 100644 --- a/buffer.c +++ b/buffer.c @@ -643,6 +643,7 @@ void buffer_new_file(TextBuffer *buffer, char const *filename) { // Save the buffer to its current filename. This will rewrite the entire file, regardless of // whether there are any unsaved changes. bool buffer_save(TextBuffer *buffer) { + Settings const *settings = buffer_settings(buffer); if (!buffer->is_line_buffer && buffer->filename) { FILE *out = fopen(buffer->filename, "wb"); if (out) { @@ -659,6 +660,13 @@ bool buffer_save(TextBuffer *buffer) { if (line != end-1) { putc('\n', out); + } else { + if (settings->auto_add_newline) { + if (line->len) { + // if the last line isn't empty, add a newline. + putc('\n', out); + } + } } } if (ferror(out)) { diff --git a/command.c b/command.c index 5ff7444..da1701a 100644 --- a/command.c +++ b/command.c @@ -247,6 +247,9 @@ void command_execute(Ted *ted, Command c, i64 argument) { case CMD_TAB_PREV: if (ted->active_node) node_tab_prev(ted, ted->active_node, argument); break; + case CMD_TAB_SWITCH: + if (ted->active_node) node_tab_switch(ted, ted->active_node, argument); + break; case CMD_ESCAPE: if (*ted->error_shown) { diff --git a/command.h b/command.h index 63afdb2..906bf08 100644 --- a/command.h +++ b/command.h @@ -51,6 +51,7 @@ ENUM_U16 { CMD_QUIT, CMD_TAB_CLOSE, + CMD_TAB_SWITCH, // argument = index of tab (starting at 0) CMD_TAB_NEXT, CMD_TAB_PREV, @@ -110,6 +111,7 @@ static CommandName const command_names[CMD_COUNT] = { {"cut", CMD_CUT}, {"paste", CMD_PASTE}, {"tab-close", CMD_TAB_CLOSE}, + {"tab-switch", CMD_TAB_SWITCH}, {"tab-next", CMD_TAB_NEXT}, {"tab-prev", CMD_TAB_PREV}, {"increase-text-size", CMD_TEXT_SIZE_INCREASE}, diff --git a/config.c b/config.c index bdec0d9..2ebc094 100644 --- a/config.c +++ b/config.c @@ -151,6 +151,47 @@ void config_read(Ted *ted, char const *filename) { }; ConfigReader *cfg = &cfg_reader; Settings *settings = &ted->settings; + + typedef struct { + char const *name; + bool *control; + } OptionBool; + typedef struct { + char const *name; + u8 *control, min, max; + } OptionU8; + typedef struct { + char const *name; + float *control, min, max; + } OptionFloat; + typedef struct { + char const *name; + u16 *control, min, max; + } OptionU16; + // core options + // (these go at the start so they don't need to be re-computed each time) + OptionBool const options_bool[] = { + {"auto-indent", &settings->auto_indent}, + {"auto-add-newline", &settings->auto_add_newline}, + }; + OptionU8 const options_u8[] = { + {"tab-width", &settings->tab_width, 1, 100}, + {"cursor-width", &settings->cursor_width, 1, 100}, + {"undo-save-time", &settings->undo_save_time, 1, 200}, + {"border-thickness", &settings->border_thickness, 1, 30}, + {"padding", &settings->padding, 0, 100}, + {"scrolloff", &settings->scrolloff, 1, 100}, + }; + OptionFloat const options_float[] = { + {"cursor-blink-time-on", &settings->cursor_blink_time_on, 0, 1000}, + {"cursor-blink-time-off", &settings->cursor_blink_time_off, 0, 1000}, + }; + OptionU16 const options_u16[] = { + {"text-size", &settings->text_size, TEXT_SIZE_MIN, TEXT_SIZE_MAX}, + {"max-menu-width", &settings->max_menu_width, 10, U16_MAX}, + {"error-display-time", &settings->error_display_time, 0, U16_MAX}, + }; + FILE *fp = fopen(filename, "rb"); if (fp) { int line_cap = 4096; @@ -270,83 +311,48 @@ void config_read(Ted *ted, char const *filename) { boolean = false; } - if (streq(key, "tab-width")) { - if (is_integer && integer > 0 && integer < 100) { - settings->tab_width = (u8)integer; - } else { - config_err(cfg, "Invalid tab width: %s.", value); - } - } else if (streq(key, "cursor-width")) { - if (is_integer && integer > 0 && integer < 100) { - settings->cursor_width = (u8)integer; - } else { - config_err(cfg, "Invalid cursor width: %s.", value); + // go through all types of options + for (size_t i = 0; i < arr_count(options_bool); ++i) { + OptionBool const *option = &options_bool[i]; + if (streq(key, option->name)) { + if (is_bool) + *option->control = boolean; + else + config_err(cfg, "Invalid %s: %s. This should be yes, no, on, or off.", option->name, value); } - } else if (streq(key, "undo-save-time")) { - if (is_integer && integer > 0 && integer < 200) { - settings->undo_save_time = (u8)integer; - } else { - config_err(cfg, "Invalid undo save time: %s.", value); - } - } else if (streq(key, "cursor-blink-time-on")) { - if (is_floating && floating >= 0 && floating < 1000) { - settings->cursor_blink_time_on = (float)floating; - } else { - config_err(cfg, "Invalid cursor blink time: %s.", value); - } - } else if (streq(key, "cursor-blink-time-off")) { - if (is_floating && floating >= 0 && floating < 1000) { - settings->cursor_blink_time_off = (float)floating; - } else { - config_err(cfg, "Invalid cursor blink time: %s.", value); - } - } else if (streq(key, "text-size")) { - if (is_integer && integer >= TEXT_SIZE_MIN && integer <= TEXT_SIZE_MAX) { - settings->text_size = (u16)integer; - } else { - config_err(cfg, "Invalid text size: %s.", value); - } - } else if (streq(key, "border-thickness")) { - if (is_integer && integer > 0 && integer < 30) { - settings->border_thickness = (u8)integer; - } else { - config_err(cfg, "Invalid border thickness: %s.", value); - } - } else if (streq(key, "max-menu-width")) { - if (is_integer && integer >= 10 && integer < U16_MAX) { - settings->max_menu_width = (u16)integer; - } else { - config_err(cfg, "Invalid max menu width: %s.", value); - } - } else if (streq(key, "padding")) { - if (is_integer && integer >= 0 && integer < 100) { - settings->padding = (u8)integer; - } else { - config_err(cfg, "Invalid padding: %s.", value); - } - } else if (streq(key, "scrolloff")) { - if (is_integer && integer >= 1 && integer < 100) { - settings->scrolloff = (u8)integer; - } else { - config_err(cfg, "Invalid scrolloff: %s.", value); + } + + for (size_t i = 0; i < arr_count(options_u8); ++i) { + OptionU8 const *option = &options_u8[i]; + if (streq(key, option->name)) { + if (is_integer && integer >= option->min && integer <= option->max) + *option->control = (u8)integer; + else + config_err(cfg, "Invalid %s: %s. This should be an integer from %u to %u.", option->name, value, option->min, option->max); } - } else if (streq(key, "error-display-time")) { - if (is_integer && integer >= 0 && integer < U16_MAX) { - settings->error_display_time = (u16)integer; - } else { - config_err(cfg, "Invalid error display time: %s.", value); + } + + for (size_t i = 0; i < arr_count(options_u16); ++i) { + OptionU16 const *option = &options_u16[i]; + if (streq(key, option->name)) { + if (is_integer && integer >= option->min && integer <= option->max) + *option->control = (u16)integer; + else + config_err(cfg, "Invalid %s: %s. This should be an integer from %u to %u.", option->name, value, option->min, option->max); } - } else if (streq(key, "auto-indent")) { - if (is_bool) { - settings->auto_indent = boolean; - } else { - config_err(cfg, "Invalid auto indent: %s " BOOL_HELP ".", value); + } + + + for (size_t i = 0; i < arr_count(options_float); ++i) { + OptionFloat const *option = &options_float[i]; + if (streq(key, option->name)) { + if (is_floating && floating >= option->min && floating <= option->max) + *option->control = (float)floating; + else + config_err(cfg, "Invalid %s: %s. This should be a number from %g to %g.", option->name, value, option->min, option->max); } - } else { - config_err(cfg, "Unrecognized core setting: %s.", key); } - #undef BOOL_HELP } break; } } diff --git a/node.c b/node.c index f0e85e0..9a37d4a 100644 --- a/node.c +++ b/node.c @@ -20,6 +20,13 @@ static void node_tab_prev(Ted *ted, Node *node, i64 n) { node_tab_next(ted, node, -n); } +static void node_tab_switch(Ted *ted, Node *node, i64 tab) { + assert(node->tabs); + if (tab < arr_len(node->tabs)) { + node_switch_to_tab(ted, node, (u16)tab); + } +} + static void node_free(Node *node) { arr_free(node->tabs); memset(node, 0, sizeof *node); diff --git a/ted.cfg b/ted.cfg index 8b576f4..a639917 100644 --- a/ted.cfg +++ b/ted.cfg @@ -17,6 +17,8 @@ max-menu-width = 600 padding = 6 error-display-time = 10 auto-indent = on +# automatically add a newline at the end of the file on save +auto-add-newline = on [keyboard] # motion and selection @@ -75,11 +77,20 @@ Ctrl+c = :copy Ctrl+x = :cut Ctrl+v = :paste +# tabs Ctrl+w = :tab-close Ctrl+PageUp = :tab-prev -Ctrl+Left = :tab-prev Ctrl+PageDown = :tab-next -Ctrl+Right = :tab-next +Alt+1 = 0 :tab-switch +Alt+2 = 1 :tab-switch +Alt+3 = 2 :tab-switch +Alt+4 = 3 :tab-switch +Alt+5 = 4 :tab-switch +Alt+6 = 5 :tab-switch +Alt+7 = 6 :tab-switch +Alt+8 = 7 :tab-switch +Alt+9 = 8 :tab-switch +Alt+0 = 9 :tab-switch Ctrl++ = 3 :increase-text-size Ctrl+- = 3 :decrease-text-size diff --git a/ted.h b/ted.h index 7c546ae..9df0208 100644 --- a/ted.h +++ b/ted.h @@ -11,6 +11,7 @@ typedef struct { u16 max_menu_width; u16 error_display_time; bool auto_indent; + bool auto_add_newline; u8 tab_width; u8 cursor_width; u8 undo_save_time; -- cgit v1.2.3