From 598d72c0674bb059c0f38f03c4851bcc61e5852d Mon Sep 17 00:00:00 2001 From: pommicket Date: Sun, 13 Aug 2023 12:05:54 -0300 Subject: various little changes, remove calls to change_directory --- CMakeLists.txt | 2 +- buffer.c | 7 ++++-- build.c | 57 ++++++++++++++++++++++++++++++----------------- command.c | 2 +- control | 2 +- development.md | 6 +++++ ide-usages.c | 4 ++-- main.c | 2 ++ menu.c | 2 +- tags.c | 70 +++++++++++++++++++++++++++++++--------------------------- ted-internal.h | 2 ++ ted.h | 56 ++++++++++++++++++++++++---------------------- 12 files changed, 125 insertions(+), 87 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3641e65..652f407 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.5) project(ted) if(CMAKE_BUILD_TYPE STREQUAL "Debug") set(SOURCES buffer.c build.c colors.c command.c config.c find.c gl.c ide-autocomplete.c diff --git a/buffer.c b/buffer.c index 3f94cf1..a33cfad 100644 --- a/buffer.c +++ b/buffer.c @@ -229,6 +229,8 @@ u32 buffer_last_line_on_screen(TextBuffer *buffer) { void buffer_set_undo_enabled(TextBuffer *buffer, bool enabled) { buffer->store_undo_events = enabled; + if (!enabled) + buffer_clear_undo_redo(buffer); } Rect buffer_rect(TextBuffer *buffer) { @@ -2234,10 +2236,11 @@ bool buffer_change_number_at_pos(TextBuffer *buffer, BufferPos *ppos, i64 by) { return ret; } -void buffer_change_number_at_cursor(TextBuffer *buffer, i64 by) { +bool buffer_change_number_at_cursor(TextBuffer *buffer, i64 by) { buffer_start_edit_chain(buffer); - buffer_change_number_at_pos(buffer, &buffer->cursor_pos, by); + bool ret = buffer_change_number_at_pos(buffer, &buffer->cursor_pos, by); buffer_end_edit_chain(buffer); + return ret; } // decrease the number of lines in the buffer. diff --git a/build.c b/build.c index 771fd6d..df8f36f 100644 --- a/build.c +++ b/build.c @@ -50,11 +50,12 @@ static bool build_run_next_command_in_queue(Ted *ted) { return false; assert(!ted->build_process); assert(*ted->build_dir); - change_directory(ted->build_dir); char *command = ted->build_queue[0]; arr_remove(ted->build_queue, 0); if (ted_save_all(ted)) { - ted->build_process = process_run(command); + ProcessSettings settings = {0}; + settings.working_directory = ted->build_dir; + ted->build_process = process_run_ex(command, &settings); const char *error = process_geterr(ted->build_process); if (!error) { ted->building = true; @@ -90,6 +91,11 @@ void build_queue_finish(Ted *ted) { build_run_next_command_in_queue(ted); // run the first command } +void build_set_working_directory(Ted *ted, const char *dir) { + assert(strlen(dir) < TED_PATH_MAX - 1); + strbuf_cpy(ted->build_dir, dir); +} + void build_start_with_command(Ted *ted, const char *command) { build_queue_start(ted); build_queue_command(ted, command); @@ -98,27 +104,39 @@ void build_start_with_command(Ted *ted, const char *command) { void build_start(Ted *ted) { Settings *settings = ted_active_settings(ted); - char *command = settings->build_command; - char *root = ted_get_root_dir(ted); - strbuf_cpy(ted->build_dir, root); + const char *command = settings->build_command; + + { + char *root = ted_get_root_dir(ted); + build_set_working_directory(ted, root); + free(root); + } + if (*command == 0) { command = settings->build_default_command; - change_directory(root); - - #if _WIN32 - if (fs_file_exists("make.bat")) { - command = "make.bat"; - } else - #endif - if (fs_file_exists("Cargo.toml")) { - command = "cargo build"; - } else if (fs_file_exists("Makefile")) { - command = "make -j16"; - } else if (fs_file_exists("go.mod")) { - command = "go build"; + typedef struct { + const char *filename; + const char *command; + } Assoc; + + Assoc associations[] = { + #if _WIN32 + {"make.bat", "make.bat"}, + #endif + {"Cargo.toml", "cargo build"}, + {"Makefile", "make -j16"}, + {"go.mod", "go build"}, + }; + for (size_t i = 0; i < arr_count(associations); ++i) { + Assoc *assoc = &associations[i]; + char path[TED_PATH_MAX]; + path_full(ted->build_dir, assoc->filename, path, sizeof path); + if (fs_file_exists(path)) { + command = assoc->command; + break; + } } } - free(root); if (*command) build_start_with_command(ted, command); } @@ -209,7 +227,6 @@ static bool is_source_path(char32_t c) { || strchr(allowed_ascii_symbols_in_path, (char)c); } -// make sure you set ted->build_dir before running this! void build_check_for_errors(Ted *ted) { const Settings *settings = ted_active_settings(ted); diff --git a/command.c b/command.c index 05b36cc..b5d2f5d 100644 --- a/command.c +++ b/command.c @@ -653,7 +653,7 @@ void command_execute_ex(Ted *ted, Command c, const CommandArgument *full_argumen case CMD_SHELL: { const char *str = argument_str; if (str) { - strbuf_cpy(ted->build_dir, ted->cwd); + build_set_working_directory(ted, ted->cwd); build_start_with_command(ted, str); } else { menu_open(ted, MENU_SHELL); diff --git a/control b/control index 380315f..3d0b1ce 100644 --- a/control +++ b/control @@ -1,5 +1,5 @@ Package: ted -Version: 2.4.3 +Version: 3.0 Section: text Priority: optional Architecture: amd64 diff --git a/development.md b/development.md index c633885..086b46a 100644 --- a/development.md +++ b/development.md @@ -106,6 +106,12 @@ At the top of `syntax.c` there are a bunch of `SYNTAX_STATE_*` constants. Create a new enum for your language, and add any state that needs to be remembered across lines. Then implement the `syntax_highlight_` function similar to the other ones. +## Glossary + +- **buffer** - a text document +- **column** - one space width +- **line buffer** - a single-line buffer, e.g. the file name input in the "open file" menu + ## Releasing When releasing a new version of `ted`: diff --git a/ide-usages.c b/ide-usages.c index 4caa644..9ae31e4 100644 --- a/ide-usages.c +++ b/ide-usages.c @@ -124,10 +124,10 @@ void usages_process_lsp_response(Ted *ted, const LSPResponse *response) { fclose(last_file); buffer_set_view_only(buffer, true); - // the build_dir doesn't really matter since we're using absolute paths + // the build directory doesn't really matter since we're using absolute paths // but might as well set it to something reasonable. char *root = ted_get_root_dir(ted); - strbuf_cpy(ted->build_dir, root); + build_set_working_directory(ted, root); free(root); build_check_for_errors(ted); diff --git a/main.c b/main.c index bfaf506..6c9b88f 100644 --- a/main.c +++ b/main.c @@ -3,9 +3,11 @@ TODO: - fix find - public Node API - public Selector/FileSelector API +- public Settings API FUTURE FEATURES: - autodetect indentation (tabs vs spaces) +- custom file/build command associations - config variables - bind key to series of commands - convert macro to command list diff --git a/menu.c b/menu.c index 67b1fba..1df07ea 100644 --- a/menu.c +++ b/menu.c @@ -514,7 +514,7 @@ static void shell_menu_update(Ted *ted) { arr_add(ted->shell_history, command); } menu_close(ted); - strbuf_cpy(ted->build_dir, ted->cwd); + build_set_working_directory(ted, ted->cwd); build_start_with_command(ted, command); } } diff --git a/tags.c b/tags.c index 5ada805..2851b17 100644 --- a/tags.c +++ b/tags.c @@ -3,24 +3,23 @@ #include "ted-internal.h" #include "pcre-inc.h" -static const char *tags_filename(Ted *ted, bool error_if_does_not_exist) { - change_directory(ted->cwd); - const char *filename = "tags"; - ted_path_full(ted, ".", ted->tags_dir, sizeof ted->tags_dir); - if (!fs_file_exists(filename)) { - filename = "../tags"; - ted_path_full(ted, "..", ted->tags_dir, sizeof ted->tags_dir); - if (!fs_file_exists(filename)) { - filename = "../../tags"; - ted_path_full(ted, "../..", ted->tags_dir, sizeof ted->tags_dir); - if (!fs_file_exists(filename)) { - if (error_if_does_not_exist) - ted_error(ted, "No tags file. Try running ctags."); - filename = NULL; - } - } +static bool get_tags_dir(Ted *ted, bool error_if_does_not_exist) { + char prev_dir[TED_PATH_MAX]; + *prev_dir = '\0'; + strbuf_cpy(ted->tags_dir, ted->cwd); + while (!streq(prev_dir, ted->tags_dir)) { + strbuf_cpy(prev_dir, ted->tags_dir); + char path[TED_PATH_MAX]; + path_full(ted->tags_dir, "tags", path, sizeof path); + if (fs_file_exists(path)) + return true; + + path_full(ted->tags_dir, "..", path, sizeof path); + strbuf_cpy(ted->tags_dir, path); } - return filename; + if (error_if_does_not_exist) + ted_error(ted, "No tags file. Try running ctags."); + return false; } // is this a file we can generate tags for? @@ -99,19 +98,22 @@ static void tags_generate_at_dir(Ted *ted, bool run_in_build_window, const char // generate/re-generate tags. void tags_generate(Ted *ted, bool run_in_build_window) { - const char *filename = tags_filename(ted, false); - if (!filename) { + if (!get_tags_dir(ted, false)) { char *root = ted_get_root_dir(ted); strcpy(ted->tags_dir, root); free(root); } - change_directory(ted->tags_dir); - strcpy(ted->build_dir, ted->tags_dir); - remove("tags"); // delete old tags file + build_set_working_directory(ted, ted->tags_dir); + + { + char path[TED_PATH_MAX]; + path_full(ted->tags_dir, "tags", path, sizeof path); + remove(path); // delete old tags file + } + if (run_in_build_window) build_queue_start(ted); tags_generate_at_dir(ted, run_in_build_window, ted->tags_dir, 0); if (run_in_build_window) build_queue_finish(ted); - change_directory(ted->cwd); } static int tag_try(FILE *fp, const char *tag) { @@ -140,8 +142,10 @@ static int tag_try(FILE *fp, const char *tag) { size_t tags_beginning_with(Ted *ted, const char *prefix, char **out, size_t out_size, bool error_if_tags_does_not_exist) { assert(out_size); - const char *tags_name = tags_filename(ted, error_if_tags_does_not_exist); - if (!tags_name) return 0; + if (!get_tags_dir(ted, error_if_tags_does_not_exist)) + return 0; + char tags_name[TED_PATH_MAX]; + path_full(ted->tags_dir, "tags", tags_name, sizeof tags_name); FILE *file = fopen(tags_name, "rb"); if (!file) return 0; @@ -200,13 +204,14 @@ size_t tags_beginning_with(Ted *ted, const char *prefix, char **out, size_t out_ // returns true if the tag exists. bool tag_goto(Ted *ted, const char *tag) { - bool already_regenerated_tags; - already_regenerated_tags = false; + bool already_regenerated_tags = false; top:; const Settings *settings = ted_active_settings(ted); + if (!get_tags_dir(ted, true)) + return false; + char tags_name[TED_PATH_MAX]; + path_full(ted->tags_dir, "tags", tags_name, sizeof tags_name); - const char *tags_name = tags_filename(ted, true); - if (!tags_name) return false; FILE *file = fopen(tags_name, "rb"); if (!file) return false; @@ -370,9 +375,10 @@ top:; SymbolInfo *tags_get_symbols(Ted *ted) { // read tags file and extract tag names - const char *filename = tags_filename(ted, true); - if (!filename) return NULL; - FILE *file = fopen(filename, "rb"); + if (!get_tags_dir(ted, true)) return NULL; + char tags_name[TED_PATH_MAX]; + path_full(ted->tags_dir, "tags", tags_name, sizeof tags_name); + FILE *file = fopen(tags_name, "rb"); if (!file) return NULL; SymbolInfo *infos = NULL; diff --git a/ted-internal.h b/ted-internal.h index 6de2cfd..64b3b6e 100644 --- a/ted-internal.h +++ b/ted-internal.h @@ -513,6 +513,8 @@ bool buffer_handle_click(Ted *ted, TextBuffer *buffer, vec2 click, u8 times); /// currently needed to avoid bad positioning when a buffer is created /// and buffer_center_cursor is called immediately after void buffer_center_cursor_next_frame(TextBuffer *buffer); +/// perform a series of checks to make sure the buffer doesn't have any invalid values +void buffer_check_valid(TextBuffer *buffer); // === build.c === void build_frame(Ted *ted, float x1, float y1, float x2, float y2); diff --git a/ted.h b/ted.h index a670566..c8aaf71 100644 --- a/ted.h +++ b/ted.h @@ -22,15 +22,12 @@ extern "C" { #include "command.h" /// Version number -#define TED_VERSION "2.4.3" +#define TED_VERSION "3.0" /// Maximum path size ted handles. #define TED_PATH_MAX 1024 /// Config filename #define TED_CFG "ted.cfg" - -// If you are adding new languages, DO NOT change the constant values -// of the previous languages. It will mess up config files which use :set-language! enum { /// avoid using this and use LANG_TEXT instead. LANG_NONE = 0, @@ -87,7 +84,6 @@ typedef u32 SyntaxState; /// types of syntax highlighting enum SyntaxCharType { - // do not change these numbers as it will break backwards compatibility with plugins SYNTAX_NORMAL = 0, SYNTAX_KEYWORD = 1, SYNTAX_BUILTIN = 2, @@ -143,8 +139,6 @@ typedef struct { /// line number (0-indexed) u32 line; /// UTF-32 index of character in line - /// - /// (not the same as column, since a tab is `settings->tab_width` columns) u32 index; } BufferPos; @@ -155,9 +149,9 @@ enum { }; /// see \ref KEY_COMBO enum { - KEY_MODIFIER_CTRL_BIT, - KEY_MODIFIER_SHIFT_BIT, - KEY_MODIFIER_ALT_BIT + KEY_MODIFIER_CTRL_BIT = 0, + KEY_MODIFIER_SHIFT_BIT = 1, + KEY_MODIFIER_ALT_BIT = 2, }; /// see \ref KEY_COMBO #define KEY_MODIFIER_CTRL ((u32)1<build_dir` before running this! +/// +/// make sure you call \ref build_set_working_directory before calling this! void build_queue_finish(Ted *ted); /// set up the build output buffer. void build_setup_buffer(Ted *ted); +/// set directory for build commands. +void build_set_working_directory(Ted *ted, const char *dir); /// run a single command in the build window. -/// make sure you set `ted->build_dir` before running this! +/// +/// make sure you call \ref build_set_working_directory before calling this! void build_start_with_command(Ted *ted, const char *command); /// figure out which build command to run, and run it. void build_start(Ted *ted); -- cgit v1.2.3