summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md7
-rw-r--r--buffer.c11
-rw-r--r--build.c55
-rw-r--r--command.c6
-rw-r--r--command.h2
-rw-r--r--find.c4
-rw-r--r--main.c6
-rw-r--r--menu.c37
-rw-r--r--session.c2
-rw-r--r--ted.cfg1
-rw-r--r--ted.h3
-rw-r--r--util.c8
12 files changed, 100 insertions, 42 deletions
diff --git a/README.md b/README.md
index 4b0fabb..a2094f4 100644
--- a/README.md
+++ b/README.md
@@ -18,13 +18,16 @@ a simple editor that starts up practically instantaneously, and performs well on
## Supported features (more coming soon)
+All the keybindings listed below are customizable!
+
- Multiple tabs, each with a different file
- Split screen (Ctrl+/, Ctrl+Shift+/)
- Auto-indent
- Customization of (pretty much) all colours and keyboard commands.
- Syntax highlighting for C, C++, Rust, and Python.
- Find and replace (with regular expressions!)
-- Run build command (default keybinding F4), go to errors
+- Run build command (F4), go to errors
+- Run any shell command (Ctrl+!)
- Go to definition (Ctrl+click)
- Go to line (Ctrl+G)
@@ -72,7 +75,7 @@ Then run `make.bat`.
<tr><td>0.5</td> <td>Go to definition</td> <td>2021 Feb 22</td></tr>
<tr><td>0.5a</td> <td>Several bugfixes, go to line</td> <td>2021 Feb 23</td></tr>
<tr><td>0.6</td> <td>Split-screen</td> <td>2021 Feb 28</td></tr>
-<tr><td>0.7</td> <td>Restore session, command selector, big bug fixes</td> <td>2021 Mar 3</td></tr>
+<tr><td>0.7</td> <td>Restore session, command selector, :shell, big bug fixes</td> <td>2021 Mar 3</td></tr>
</table>
## License
diff --git a/buffer.c b/buffer.c
index 7489d04..21922ee 100644
--- a/buffer.c
+++ b/buffer.c
@@ -2387,6 +2387,7 @@ void buffer_render(TextBuffer *buffer, Rect r) {
rgba_u32_to_floats(colors[COLOR_TEXT], text_state.color);
buffer->first_line_on_screen = start_line;
+ buffer->last_line_on_screen = 0;
for (u32 line_idx = start_line; line_idx < nlines; ++line_idx) {
Line *line = &lines[line_idx];
if (arr_len(char_types) < line->len) {
@@ -2429,6 +2430,7 @@ void buffer_render(TextBuffer *buffer, Rect r) {
text_state.y += text_font_char_height(font);
column = 0;
}
+ if (buffer->last_line_on_screen == 0) buffer->last_line_on_screen = nlines - 1;
arr_free(char_types);
@@ -2544,3 +2546,12 @@ void buffer_dedent_selection(TextBuffer *buffer) {
buffer_dedent_lines(buffer, l1, l2);
}
+void buffer_indent_cursor_line(TextBuffer *buffer) {
+ u32 line = buffer->cursor_pos.line;
+ buffer_indent_lines(buffer, line, line);
+}
+void buffer_dedent_cursor_line(TextBuffer *buffer) {
+ u32 line = buffer->cursor_pos.line;
+ buffer_dedent_lines(buffer, line, line);
+}
+
diff --git a/build.c b/build.c
index 7554c50..4a65857 100644
--- a/build.c
+++ b/build.c
@@ -11,25 +11,41 @@ static void build_stop(Ted *ted) {
process_kill(&ted->build_process);
ted->building = false;
ted->build_shown = false;
+ *ted->build_dir = '\0';
build_clear(ted);
}
-
-static void build_start(Ted *ted) {
+// make sure you set ted->build_dir before running this!
+static void build_start_with_command(Ted *ted, char const *command) {
+ assert(*ted->build_dir);
+ change_directory(ted->build_dir);
if (ted->building) {
build_stop(ted);
}
- Settings *settings = &ted->settings;
-
ted_save_all(ted);
- // get rid of any old build errors
- build_clear(ted);
-
+ if (process_run(&ted->build_process, command)) {
+ ted->building = true;
+ ted->build_shown = true;
+ TextBuffer *build_buffer = &ted->build_buffer;
+ // new empty build output buffer
+ buffer_new_file(build_buffer, NULL);
+ build_buffer->store_undo_events = false; // don't need undo events for build output buffer
+ char32_t text[] = {'$', ' '};
+ buffer_insert_text_at_cursor(build_buffer, str32(text, 2));
+ buffer_insert_utf8_at_cursor(build_buffer, command);
+ buffer_insert_char_at_cursor(build_buffer, '\n');
+ build_buffer->view_only = true;
+ } else {
+ ted_seterr(ted, "Couldn't start build: %s", process_geterr(&ted->build_process));
+ }
+}
+
+static void build_start(Ted *ted) {
bool cargo = false, make = false;
- change_directory(ted->cwd);
- strcpy(ted->build_dir, ted->cwd);
+ strbuf_cpy(ted->build_dir, ted->cwd);
+ Settings *settings = &ted->settings;
char *command = settings->build_default_command;
@@ -42,11 +58,9 @@ static void build_start(Ted *ted) {
if (fs_file_exists("Cargo.toml")) {
cargo = true;
} else if (fs_file_exists(".." PATH_SEPARATOR_STR "Cargo.toml")) {
- change_directory("..");
ted_full_path(ted, "..", ted->build_dir, sizeof ted->build_dir);
cargo = true;
} else if (fs_file_exists(".." PATH_SEPARATOR_STR ".." PATH_SEPARATOR_STR "Cargo.toml")) {
- change_directory(".." PATH_SEPARATOR_STR "..");
ted_full_path(ted, "../..", ted->build_dir, sizeof ted->build_dir);
cargo = true;
} else
@@ -54,7 +68,6 @@ static void build_start(Ted *ted) {
if (fs_file_exists("Makefile")) {
make = true;
} else if (fs_file_exists(".." PATH_SEPARATOR_STR "Makefile")) {
- change_directory("..");
ted_full_path(ted, "..", ted->build_dir, sizeof ted->build_dir);
make = true;
}
@@ -66,22 +79,8 @@ static void build_start(Ted *ted) {
} else if (make) {
command = "make";
}
-
- if (process_run(&ted->build_process, command)) {
- ted->building = true;
- ted->build_shown = true;
- TextBuffer *build_buffer = &ted->build_buffer;
- // new empty build output buffer
- buffer_new_file(build_buffer, NULL);
- build_buffer->store_undo_events = false; // don't need undo events for build output buffer
- char32_t text[] = {'$', ' '};
- buffer_insert_text_at_cursor(build_buffer, str32(text, 2));
- buffer_insert_utf8_at_cursor(build_buffer, command);
- buffer_insert_char_at_cursor(build_buffer, '\n');
- build_buffer->view_only = true;
- } else {
- ted_seterr(ted, "Couldn't start build: %s", process_geterr(&ted->build_process));
- }
+
+ build_start_with_command(ted, command);
}
static void build_go_to_error(Ted *ted) {
diff --git a/command.c b/command.c
index c7276ac..727b2c6 100644
--- a/command.c
+++ b/command.c
@@ -115,6 +115,8 @@ void command_execute(Ted *ted, Command c, i64 argument) {
} else if (buffer) {
if (buffer->selection)
buffer_dedent_selection(buffer);
+ else
+ buffer_dedent_cursor_line(buffer);
}
break;
case CMD_NEWLINE:
@@ -319,6 +321,10 @@ void command_execute(Ted *ted, Command c, i64 argument) {
case CMD_BUILD_PREV_ERROR:
build_prev_error(ted);
break;
+ case CMD_SHELL:
+ menu_open(ted, MENU_SHELL);
+ break;
+
case CMD_GOTO_DEFINITION:
menu_open(ted, MENU_GOTO_DEFINITION);
break;
diff --git a/command.h b/command.h
index d5d8062..41bab31 100644
--- a/command.h
+++ b/command.h
@@ -72,6 +72,7 @@ ENUM_U16 {
CMD_BUILD,
CMD_BUILD_PREV_ERROR,
CMD_BUILD_NEXT_ERROR,
+ CMD_SHELL,
CMD_GOTO_DEFINITION, // "go to definition of..."
CMD_GOTO_LINE, // open "goto line..." menu
@@ -151,6 +152,7 @@ static CommandName const command_names[] = {
{"build", CMD_BUILD},
{"build-prev-error", CMD_BUILD_PREV_ERROR},
{"build-next-error", CMD_BUILD_NEXT_ERROR},
+ {"shell", CMD_SHELL},
{"goto-definition", CMD_GOTO_DEFINITION},
{"goto-line", CMD_GOTO_LINE},
{"split-horizontal", CMD_SPLIT_HORIZONTAL},
diff --git a/find.c b/find.c
index 58bff8c..1e0b409 100644
--- a/find.c
+++ b/find.c
@@ -451,9 +451,7 @@ static void find_open(Ted *ted, bool replace) {
ted->find = true;
buffer_select_all(ted->active_buffer);
}
- if (!ted->replace && replace) {
- ted->replace = true;
- }
+ ted->replace = replace;
find_update(ted, true);
}
diff --git a/main.c b/main.c
index a829736..6a9e46a 100644
--- a/main.c
+++ b/main.c
@@ -1,5 +1,4 @@
// @TODO:
-// - run shell command (i.e. not just `make`)
// - completion
// - more instructions (basic stuff + how to open config)
@@ -73,8 +72,8 @@ bool tag_goto(Ted *ted, char const *tag);
#include "find.c"
#include "node.c"
#include "tags.c"
-#include "menu.c"
#include "build.c"
+#include "menu.c"
#include "command.c"
#include "config.c"
#include "session.c"
@@ -644,6 +643,9 @@ int main(int argc, char **argv) {
}
}
}
+ if (ted->build_shown)
+ if (buffer_handle_click(ted, &ted->build_buffer, pos, times)) // handle build buffer clicks
+ add = false;
}
if (add) {
ted->mouse_clicks[button][ted->nmouse_clicks[button]] = pos;
diff --git a/menu.c b/menu.c
index 868a4a4..24a9af8 100644
--- a/menu.c
+++ b/menu.c
@@ -32,6 +32,9 @@ static void menu_close(Ted *ted) {
buffer_clear(&ted->argument_buffer);
free(selector->entries); selector->entries = NULL; selector->n_entries = 0;
} break;
+ case MENU_SHELL:
+ buffer_clear(&ted->line_buffer);
+ break;
}
ted->menu = MENU_NONE;
ted->selector_open = NULL;
@@ -79,6 +82,9 @@ static void menu_open(Ted *ted, Menu menu) {
selector->enable_cursor = true;
selector->cursor = 0;
} break;
+ case MENU_SHELL:
+ ted_switch_to_buffer(ted, &ted->line_buffer);
+ break;
}
}
@@ -288,6 +294,15 @@ static void menu_update(Ted *ted) {
}
free(search_term);
} break;
+ case MENU_SHELL:
+ if (line_buffer->line_buffer_submitted) {
+ char *command = str32_to_utf8_cstr(buffer_get_line(line_buffer, 0));
+ menu_close(ted);
+ strbuf_cpy(ted->build_dir, ted->cwd);
+ build_start_with_command(ted, command);
+ free(command);
+ }
+ break;
}
}
@@ -405,5 +420,27 @@ static void menu_render(Ted *ted) {
text_render(font_bold);
} break;
+ case MENU_SHELL: {
+ float line_buffer_height = char_height;
+
+ bounds.size.y = line_buffer_height + 2 * padding;
+ rect_coords(bounds, &x1, &y1, &x2, &y2);
+
+ gl_geometry_rect(bounds, colors[COLOR_MENU_BG]);
+ gl_geometry_rect_border(bounds, settings->border_thickness, colors[COLOR_BORDER]);
+ gl_geometry_draw();
+
+ x1 += padding;
+ y1 += padding;
+ x2 -= padding;
+ y2 -= padding;
+
+ char const *text = "Run";
+ text_utf8(font_bold, text, x1, y1, colors[COLOR_TEXT]);
+ x1 += text_get_size_v2(font_bold, text).x + padding;
+ text_render(font_bold);
+
+ buffer_render(&ted->line_buffer, rect4(x1, y1, x2, y2));
+ } break;
}
}
diff --git a/session.c b/session.c
index 4895f34..ac76511 100644
--- a/session.c
+++ b/session.c
@@ -37,6 +37,8 @@ static void session_read_node(Ted *ted, FILE *fp) {
} else {
node->active_tab = read_u16(fp);
u16 ntabs = clamp_u16(read_u16(fp), 0, TED_MAX_TABS);
+ if (node->active_tab >= ntabs)
+ node->active_tab = 0;
for (u16 i = 0; i < ntabs; ++i) {
u16 buf_idx = read_u16(fp);
if (buf_idx >= TED_MAX_BUFFERS) continue;
diff --git a/ted.cfg b/ted.cfg
index b38307e..d824b92 100644
--- a/ted.cfg
+++ b/ted.cfg
@@ -120,6 +120,7 @@ Ctrl+Alt+Shift+v = :view-only
F4 = :build
Ctrl+[ = :build-prev-error
Ctrl+] = :build-next-error
+Ctrl+! = :shell
Ctrl+d = :goto-definition
Ctrl+g = :goto-line
diff --git a/ted.h b/ted.h
index b9edc0b..ea1afdd 100644
--- a/ted.h
+++ b/ted.h
@@ -170,7 +170,8 @@ ENUM_U16 {
MENU_ASK_RELOAD, // prompt about whether to reload file which has ben changed by another program
MENU_GOTO_DEFINITION,
MENU_GOTO_LINE,
- MENU_COMMAND_SELECTOR
+ MENU_COMMAND_SELECTOR,
+ MENU_SHELL, // run a shell command
} ENUM_U16_END(Menu);
typedef struct {
diff --git a/util.c b/util.c
index f14f640..7d0064d 100644
--- a/util.c
+++ b/util.c
@@ -22,13 +22,9 @@ static u8 util_popcount(u64 x) {
static u8 util_count_leading_zeroes32(u32 x) {
if (x == 0) return 32; // GCC's __builtin_clz is undefined for x = 0
-#if __GNUC__
-#if UINT_MAX == 4294967295
+#if __GNUC__ && UINT_MAX == 4294967295
return (u8)__builtin_clz(x);
-#else
- #error "unsigned int isn't 32 bits. this function needs fixing to work on systems like yours."
-#endif
-#elif _WIN32
+#elif _WIN32 && UINT_MAX == 4294967295
return (u8)__lzcnt(x);
#else
u8 count = 0;