diff options
-rw-r--r-- | buffer.c | 27 | ||||
-rw-r--r-- | command.c | 25 | ||||
-rw-r--r-- | command.h | 7 | ||||
-rw-r--r-- | ds.h | 2 | ||||
-rw-r--r-- | menu.c | 41 | ||||
-rw-r--r-- | ted.h | 6 |
6 files changed, 85 insertions, 23 deletions
@@ -83,6 +83,8 @@ struct TextBuffer { /// /// this is either set according to the user's settings or according to the autodetected indentation bool indent_with_spaces; + /// true if user has manually specified indentation + bool manual_indentation; /// tab size /// /// this is either set according to the user's settings or according to the autodetected indentation @@ -2980,6 +2982,7 @@ void buffer_paste(TextBuffer *buffer) { } static void buffer_detect_indentation(TextBuffer *buffer) { + if (buffer->manual_indentation) return; const Settings *settings = buffer_settings(buffer); if (settings->autodetect_indentation && buffer->nlines > 1) { bool use_tabs = false; @@ -3164,6 +3167,9 @@ void buffer_reload(TextBuffer *buffer) { BufferPos cursor_pos = buffer->cursor_pos; float x1 = buffer->x1, y1 = buffer->y1, x2 = buffer->x2, y2 = buffer->y2; double scroll_x = buffer->scroll_x; double scroll_y = buffer->scroll_y; + u8 tab_width = buffer->tab_width; + bool indent_with_spaces = buffer->indent_with_spaces; + bool manual_indentation = buffer->manual_indentation; char *path = str_dup(buffer->path); if (buffer_load_file(buffer, path)) { buffer->x1 = x1; buffer->y1 = y1; buffer->x2 = x2; buffer->y2 = y2; @@ -3172,6 +3178,12 @@ void buffer_reload(TextBuffer *buffer) { buffer->scroll_y = scroll_y; buffer_validate_cursor(buffer); buffer_correct_scroll(buffer); + if (manual_indentation) { + // ensure manual indentation is preserved across reload + buffer->manual_indentation = manual_indentation; + buffer->indent_with_spaces = indent_with_spaces; + buffer->tab_width = tab_width; + } } free(path); } @@ -4126,3 +4138,18 @@ void buffer_publish_diagnostics(TextBuffer *buffer, const LSPRequest *request, L } arr_qsort(buffer->diagnostics, diagnostic_cmp); } + +void buffer_set_manual_indent_with_spaces(TextBuffer *buffer) { + buffer->indent_with_spaces = true; + buffer->manual_indentation = true; +} + +void buffer_set_manual_indent_with_tabs(TextBuffer *buffer) { + buffer->indent_with_spaces = false; + buffer->manual_indentation = true; +} + +void buffer_set_manual_tab_width(TextBuffer *buffer, u8 n) { + buffer->tab_width = n; + buffer->manual_indentation = true; +} @@ -107,6 +107,9 @@ static CommandName command_names[] = { {"rename-symbol", CMD_RENAME_SYMBOL}, {"format-file", CMD_FORMAT_FILE}, {"format-selection", CMD_FORMAT_SELECTION}, + {"indent-with-spaces", CMD_INDENT_WITH_SPACES}, + {"indent-with-tabs", CMD_INDENT_WITH_TABS}, + {"set-tab-width", CMD_SET_TAB_WIDTH}, }; static_assert_if_possible(arr_count(command_names) == CMD_COUNT) @@ -171,8 +174,8 @@ void command_execute_ex(Ted *ted, Command c, const CommandArgument *full_argumen Settings *settings = ted_active_settings(ted); if (ted->recording_macro) macro_add(ted, c, full_argument); - i64 argument = full_argument->number; const char *argument_str = full_argument->string; + i64 argument = argument_str ? 0 : full_argument->number; /* it's important that when we're playing back a macro, we only execute commands specifically from the macro. @@ -711,5 +714,25 @@ void command_execute_ex(Ted *ted, Command c, const CommandArgument *full_argumen case CMD_FORMAT_SELECTION: format_selection(ted); break; + case CMD_INDENT_WITH_SPACES: + if (buffer) { + buffer_set_manual_indent_with_spaces(buffer); + } + if (argument > 1 && argument < 256) { + buffer_set_manual_tab_width(buffer, (u8)argument); + } + break; + case CMD_INDENT_WITH_TABS: + if (buffer) { + buffer_set_manual_indent_with_tabs(buffer); + } + if (argument > 1 && argument < 256) { + buffer_set_manual_tab_width(buffer, (u8)argument); + } + break; + case CMD_SET_TAB_WIDTH: + if (argument >= 1 && argument < 256) { + buffer_set_manual_tab_width(buffer, (u8)argument); + } } } @@ -163,6 +163,13 @@ typedef enum { CMD_MACRO_STOP, CMD_MACRO_EXECUTE, + /// indent active buffer with spaces; if argument > 1, it is the # of spaces + CMD_INDENT_WITH_SPACES, + /// indent active buffer with tabs; if argument > 1, it is the tab width + CMD_INDENT_WITH_TABS, + /// set tab width/number of spaces to indent with + CMD_SET_TAB_WIDTH, + CMD_COUNT } Command; @@ -296,7 +296,7 @@ static void *arr_copy_(const void *arr, size_t member_size) { #define arr_remove_last(a) do { assert(a); if (--arr_hdr_(a)->len == 0) arr_free(a); } while (0) #define arr_remove(a, i) (void)((a) = arr_remove_((a), sizeof *(a), (i))) #define arr_remove_item(a, item) do { for (u32 _i = 0; _i < arr_len((a)); ++_i) if ((a)[_i] == item) { arr_remove((a), _i); break; } } while (0); -#define arr_index_of(a, item) (sizeof((a)[0] == (item)), arr_index_of_((a), sizeof *(a), &(item))) +#define arr_index_of(a, item) ((void)sizeof((a)[0] == (item)), arr_index_of_((a), sizeof *(a), &(item))) #define arr_remove_multiple(a, i, n) (void)((a) = arr_remove_multiple_((a), sizeof *(a), (i), (n))) #define arr_insert(a, i, x) do { u32 _index = (i); (a) = arr_cast_typeof(a) arr_grow1_((a), sizeof *(a)); \ if (a) { memmove((a) + _index + 1, (a) + _index, (arr_len(a) - _index) * sizeof *(a));\ @@ -354,31 +354,29 @@ static void command_selector_open(Ted *ted) { } static void command_selector_update(Ted *ted) { + TextBuffer *argument_buffer = ted->argument_buffer; TextBuffer *line_buffer = ted->line_buffer; Selector *selector = ted->command_selector; char *search_term = str32_to_utf8_cstr(buffer_get_line(line_buffer, 0)); - char *chosen_command = selector_update(ted, selector); - if (chosen_command) { - Command c = command_from_str(chosen_command); - if (c != CMD_UNKNOWN) { - char *argument = str32_to_utf8_cstr(buffer_get_line(ted->argument_buffer, 0)), *endp = NULL; - long long arg = 1; - bool execute = true; - if (*argument) { - strtoll(argument, &endp, 0); - if (*endp != '\0') - execute = false; + char *chosen_command_text = selector_update(ted, selector); + bool execute = chosen_command_text || line_buffer_is_submitted(argument_buffer); + free(chosen_command_text), chosen_command_text = NULL; + SelectorEntry entry = {0}; + if (execute && selector_get_cursor_entry(selector, &entry) && entry.userdata) { + line_buffer_clear_submitted(line_buffer); + Command c = (Command)entry.userdata; + char *argument = str32_to_utf8_cstr(buffer_get_line(ted->argument_buffer, 0)), *endp = NULL; + CommandArgument arg = {.number = 1}; + if (*argument) { + arg.number = strtoll(argument, &endp, 0); + if (*endp != '\0') { + arg.string = argument; } - - if (execute) { - menu_close(ted); - command_execute(ted, c, arg); - } - - free(argument); } - - free(chosen_command); + menu_close(ted); + const CommandContext ctx = {0}; + command_execute_ex(ted, c, &arg, &ctx); + free(argument); } free(search_term); } @@ -544,7 +542,8 @@ void menu_init(Ted *ted) { const char *name = command_to_str(c); if (c != CMD_UNKNOWN && *name) { SelectorEntry entry = { - .name = name + .name = name, + .userdata = c, }; selector_add_entry(ted->command_selector, &entry); } @@ -768,6 +768,12 @@ int buffer_pos_cmp(BufferPos p1, BufferPos p2); /// returns `p2 - p1`, that is, the number of characters between `p1` and `p2`, /// but negative if `p1` comes after `p2`. i64 buffer_pos_diff(TextBuffer *buffer, BufferPos p1, BufferPos p2); +/// force buffer indentation to `n` spaces +void buffer_set_manual_indent_with_spaces(TextBuffer *buffer); +/// force buffer indentation to tabs +void buffer_set_manual_indent_with_tabs(TextBuffer *buffer); +/// force buffer tab width to `n` +void buffer_set_manual_tab_width(TextBuffer *buffer, u8 n); // === build.c === /// clear build errors and stop |