From 65b6850a7dc3211566993f8a2cfacf61f5b4d6a2 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Tue, 26 Jan 2021 15:42:34 -0500 Subject: auto-indent --- buffer.c | 25 +++++++++++++++++++++++++ command.c | 32 +++++++++++++++++++------------- command.h | 11 +++++++---- config.c | 18 ++++++++++++++++++ main.c | 16 +--------------- ted.cfg | 6 +++++- ted.h | 1 + 7 files changed, 76 insertions(+), 33 deletions(-) diff --git a/buffer.c b/buffer.c index 41ad74c..5f6faec 100644 --- a/buffer.c +++ b/buffer.c @@ -1603,6 +1603,31 @@ void buffer_insert_utf8_at_cursor(TextBuffer *buffer, char const *utf8) { } } +// insert newline at cursor and auto-indent +void buffer_newline(TextBuffer *buffer) { + Settings const *settings = buffer_settings(buffer); + BufferPos cursor_pos = buffer->cursor_pos; + String32 line = buffer_get_line(buffer, cursor_pos.line); + u32 whitespace_len; + for (whitespace_len = 0; whitespace_len < line.len; ++whitespace_len) { + if (line.str[whitespace_len] != ' ' && line.str[whitespace_len] != '\t') + break; // found end of indentation + } + if (settings->auto_indent) { + // newline + auto-indent + char32_t *text = buffer_calloc(buffer, whitespace_len + 1, sizeof *text); // @OPTIMIZE: don't allocate on heap if whitespace_len is small + if (text) { + text[0] = '\n'; + memcpy(&text[1], line.str, whitespace_len * sizeof *text); + buffer_insert_text_at_cursor(buffer, str32(text, whitespace_len + 1)); + free(text); + } + } else { + // just newline + buffer_insert_char_at_cursor(buffer, '\n'); + } +} + void buffer_delete_chars_at_cursor(TextBuffer *buffer, i64 nchars) { if (buffer->selection) buffer_delete_selection(buffer); diff --git a/command.c b/command.c index a2c424d..0ec5059 100644 --- a/command.c +++ b/command.c @@ -97,6 +97,25 @@ void command_execute(Ted *ted, Command c, i64 argument) { if (buffer) buffer_select_all(buffer); break; + case CMD_TAB: + buffer_insert_char_at_cursor(buffer, '\t'); + break; + case CMD_NEWLINE: + if (buffer->is_line_buffer) { + switch (ted->menu) { + case MENU_NONE: + assert(0); + break; + case MENU_OPEN: + case MENU_SAVE_AS: { + ted->file_selector.submitted = true; + } break; + } + } else { + buffer_newline(buffer); + } + break; + case CMD_BACKSPACE: if (buffer) buffer_backspace_at_cursor(buffer, argument); break; @@ -172,19 +191,6 @@ void command_execute(Ted *ted, Command c, i64 argument) { buffer_disable_selection(buffer); } break; - case CMD_SUBMIT_LINE_BUFFER: - if (buffer->is_line_buffer) { - switch (ted->menu) { - case MENU_NONE: - assert(0); - break; - case MENU_OPEN: - case MENU_SAVE_AS: { - ted->file_selector.submitted = true; - } break; - } - } - break; } if (buffer && buffer_haserr(buffer)) { diff --git a/command.h b/command.h index 79d8a1d..9793d2a 100644 --- a/command.h +++ b/command.h @@ -24,6 +24,10 @@ ENUM_U16 { CMD_SELECT_END_OF_FILE, CMD_SELECT_ALL, // select entire buffer + // insertion + CMD_TAB, // insert '\t' + CMD_NEWLINE, // insert '\n' + autoindent -- also used to submit line buffers + // scrolling CMD_PAGE_UP, // move cursor up one page up (where one page is however tall the buffer is) CMD_PAGE_DOWN, @@ -48,8 +52,6 @@ ENUM_U16 { CMD_ESCAPE, // by default this is the escape key. closes menus, etc. - CMD_SUBMIT_LINE_BUFFER, // submit "line buffer" value -- the line buffer is where you type file names when opening files, etc. - CMD_COUNT } ENUM_U16_END(Command); @@ -83,6 +85,8 @@ static CommandName const command_names[CMD_COUNT] = { {"select-all", CMD_SELECT_ALL}, {"page-up", CMD_PAGE_UP}, {"page-down", CMD_PAGE_DOWN}, + {"tab", CMD_TAB}, + {"newline", CMD_NEWLINE}, {"backspace", CMD_BACKSPACE}, {"delete", CMD_DELETE}, {"backspace-word", CMD_BACKSPACE_WORD}, @@ -97,7 +101,6 @@ static CommandName const command_names[CMD_COUNT] = { {"paste", CMD_PASTE}, {"increase-text-size", CMD_TEXT_SIZE_INCREASE}, {"decrease-text-size", CMD_TEXT_SIZE_DECREASE}, - {"escape", CMD_ESCAPE}, - {"submit-line-buffer", CMD_SUBMIT_LINE_BUFFER} + {"escape", CMD_ESCAPE} }; diff --git a/config.c b/config.c index 868122d..3baa943 100644 --- a/config.c +++ b/config.c @@ -257,6 +257,16 @@ void config_read(Ted *ted, char const *filename) { bool const is_integer = *endptr == '\0'; double const floating = strtod(value, (char **)&endptr); bool const is_floating = *endptr == '\0'; + bool is_bool = false; + bool boolean = false; + #define BOOL_HELP "(should be yes/no/on/off)" + if (streq(value, "yes") || streq(value, "on")) { + is_bool = true; + boolean = true; + } else if (streq(value, "no") || streq(value, "off")) { + is_bool = true; + boolean = false; + } if (streq(key, "tab-width")) { if (is_integer && integer > 0 && integer < 100) { @@ -324,9 +334,17 @@ void config_read(Ted *ted, char const *filename) { } else { config_err(cfg, "Invalid error display time: %s.", value); } + } else if (streq(key, "auto-indent")) { + if (is_bool) { + settings->auto_indent = boolean; + } else { + config_err(cfg, "Invalid auto indent: %s " BOOL_HELP ".", value); + } } else { config_err(cfg, "Unrecognized core setting: %s.", key); } + + #undef BOOL_HELP } break; } } diff --git a/main.c b/main.c index 747c95f..81490b6 100644 --- a/main.c +++ b/main.c @@ -1,9 +1,8 @@ // @TODO: -// - save as // - warn on: // - overwrite (from save as menu) // - unsaved changes -// - auto-indent +// - tabs, split // - Windows installation #include "base.h" no_warn_start @@ -362,22 +361,9 @@ int main(int argc, char **argv) { (u32)((modifier & (KMOD_LALT|KMOD_RALT)) != 0) << KEY_MODIFIER_ALT_BIT; if (key_combo < KEY_COMBO_COUNT) { KeyAction *action = &ted->key_actions[key_combo]; - bool was_in_line_buffer = buffer && buffer->is_line_buffer; if (action->command) { command_execute(ted, action->command, action->argument); } - - if (buffer) { - switch (key_combo) { - case SDL_SCANCODE_RETURN << 3: - if (!was_in_line_buffer) // make sure return to submit line buffer doesn't get added to newly-active buffer - buffer_insert_char_at_cursor(buffer, '\n'); - break; - case SDL_SCANCODE_TAB << 3: - buffer_insert_char_at_cursor(buffer, '\t'); - break; - } - } } } break; case SDL_TEXTINPUT: { diff --git a/ted.cfg b/ted.cfg index 1705862..0d9089e 100644 --- a/ted.cfg +++ b/ted.cfg @@ -16,6 +16,7 @@ border-thickness = 1 max-menu-width = 600 padding = 6 error-display-time = 10 +auto-indent = on [keyboard] # motion and selection @@ -45,6 +46,10 @@ Ctrl+End = :end-of-file Ctrl+Shift+End = :select-end-of-file Ctrl+a = :select-all +# insertion +Tab = :tab +Return = :newline + # deletion Delete = :delete Ctrl+Delete = :delete-word @@ -70,7 +75,6 @@ Ctrl++ = 3 :increase-text-size Ctrl+- = 3 :decrease-text-size Escape = :escape -Return = :submit-line-buffer [colors] border = #a77 diff --git a/ted.h b/ted.h index e1f6498..18892ec 100644 --- a/ted.h +++ b/ted.h @@ -9,6 +9,7 @@ typedef struct { u16 text_size; u16 max_menu_width; u16 error_display_time; + bool auto_indent; u8 tab_width; u8 cursor_width; u8 undo_save_time; -- cgit v1.2.3