summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buffer.c8
-rw-r--r--command.c3
-rw-r--r--command.h2
-rw-r--r--config.c148
-rw-r--r--node.c7
-rw-r--r--ted.cfg15
-rw-r--r--ted.h1
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;