summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buffer.c27
-rw-r--r--command.c25
-rw-r--r--command.h7
-rw-r--r--ds.h2
-rw-r--r--menu.c41
-rw-r--r--ted.h6
6 files changed, 85 insertions, 23 deletions
diff --git a/buffer.c b/buffer.c
index d5532d4..9591e35 100644
--- a/buffer.c
+++ b/buffer.c
@@ -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;
+}
diff --git a/command.c b/command.c
index 2407551..c1e9e3a 100644
--- a/command.c
+++ b/command.c
@@ -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);
+ }
}
}
diff --git a/command.h b/command.h
index 1beb18a..076c4ef 100644
--- a/command.h
+++ b/command.h
@@ -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;
diff --git a/ds.h b/ds.h
index 8cd30e6..32b6ad4 100644
--- a/ds.h
+++ b/ds.h
@@ -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));\
diff --git a/menu.c b/menu.c
index dce442b..8273657 100644
--- a/menu.c
+++ b/menu.c
@@ -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);
}
diff --git a/ted.h b/ted.h
index 19121a7..d95d158 100644
--- a/ted.h
+++ b/ted.h
@@ -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