diff options
-rw-r--r-- | colors.c | 28 | ||||
-rw-r--r-- | command.c | 27 | ||||
-rw-r--r-- | config.c | 1 | ||||
-rw-r--r-- | lsp-write.c | 1 | ||||
-rw-r--r-- | main.c | 4 | ||||
-rw-r--r-- | os-posix.c | 56 | ||||
-rw-r--r-- | os-win.c | 2 | ||||
-rw-r--r-- | os.h | 2 | ||||
-rw-r--r-- | ted.h | 2 |
9 files changed, 93 insertions, 30 deletions
@@ -7,7 +7,7 @@ typedef struct { const char *name; } ColorName; -static ColorName const color_names[] = { +static ColorName color_names[] = { {COLOR_UNKNOWN, "unknown"}, {COLOR_TEXT, "text"}, {COLOR_TEXT_SECONDARY, "text-secondary"}, @@ -62,12 +62,28 @@ static ColorName const color_names[] = { static_assert_if_possible(arr_count(color_names) == COLOR_COUNT) +int color_name_cmp(const void *av, const void *bv) { + const ColorName *a = av, *b = bv; + return strcmp(a->name, b->name); +} + +void color_init(void) { + qsort(color_names, arr_count(color_names), sizeof *color_names, color_name_cmp); +} + ColorSetting color_setting_from_str(const char *str) { - // @TODO(optimize): sort color_names, binary search - for (int i = 0; i < COLOR_COUNT; ++i) { - ColorName const *n = &color_names[i]; - if (streq(n->name, str)) - return n->setting; + int lo = 0; + int hi = COLOR_COUNT; + while (lo < hi) { + int mid = (lo + hi) / 2; + int cmp = strcmp(color_names[mid].name, str); + if (cmp < 0) { + lo = mid + 1; + } else if (cmp > 0) { + hi = mid; + } else { + return color_names[mid].setting; + } } return COLOR_UNKNOWN; } @@ -7,7 +7,7 @@ typedef struct { const char *name; Command cmd; } CommandName; -static CommandName const command_names[] = { +static CommandName command_names[] = { {"unknown", CMD_UNKNOWN}, {"noop", CMD_NOOP}, {"left", CMD_LEFT}, @@ -99,11 +99,28 @@ static CommandName const command_names[] = { static_assert_if_possible(arr_count(command_names) == CMD_COUNT) +int command_name_cmp(const void *av, const void *bv) { + const CommandName *a = av, *b = bv; + return strcmp(a->name, b->name); +} + +void command_init(void) { + qsort(command_names, arr_count(command_names), sizeof *command_names, command_name_cmp); +} + Command command_from_str(const char *str) { - // @TODO(optimize): sort command_names, do a binary search - for (int i = 0; i < CMD_COUNT; ++i) { - if (streq(command_names[i].name, str)) - return command_names[i].cmd; + int lo = 0; + int hi = CMD_COUNT; + while (lo < hi) { + int mid = (lo + hi) / 2; + int cmp = strcmp(command_names[mid].name, str); + if (cmp < 0) { + lo = mid + 1; + } else if (cmp > 0) { + hi = mid; + } else { + return command_names[mid].cmd; + } } return CMD_UNKNOWN; } @@ -279,7 +279,6 @@ static u32 config_parse_key_combo(ConfigReader *cfg, const char *str) { {"Enter", NULL, SDLK_RETURN}, {"Equals", "Equal", SDLK_EQUALS}, }; - // @TODO(optimize): sort key_names (and split keyname1/2); do a binary search for (size_t i = 0; i < arr_count(key_names); ++i) { KeyName const *k = &key_names[i]; if (streq_case_insensitive(str, k->keyname1) || (k->keyname2 && streq_case_insensitive(str, k->keyname2))) { diff --git a/lsp-write.c b/lsp-write.c index bb41d03..c32b8f6 100644 --- a/lsp-write.c +++ b/lsp-write.c @@ -332,7 +332,6 @@ static void message_writer_write_and_free(LSP *lsp, JSONWriter *o) { printf("%s%s%s\n",term_bold(stdout),content,term_clear(stdout)); #endif - // @TODO: does write always write the full amount? probably not. this should be fixed. process_write(lsp->process, content, strlen(content)); str_builder_free(&builder); @@ -28,6 +28,7 @@ FUTURE FEATURES: - write first to <path>.tmp then rename to <path>. this prevents freak occurences, e.g. power outage during file write, from losing (all) data. +- manual.md - better handling of backspace with space indentation - CSS highlighting - styles ([color] sections) @@ -318,6 +319,9 @@ int main(int argc, char **argv) { setlocale(LC_ALL, "C.UTF-8"); #endif + command_init(); + color_init(); + // read command-line arguments const char *starting_filename = NULL; switch (argc) { @@ -249,29 +249,53 @@ const char *process_geterr(Process *p) { } long long process_write(Process *proc, const char *data, size_t size) { - assert(proc->stdin_pipe); // check that process hasn't been killed - ssize_t bytes_written = write(proc->stdin_pipe, data, size); - if (bytes_written >= 0) { - return (long long)bytes_written; - } else if (errno == EAGAIN) { - return 0; - } else { - strbuf_printf(proc->error, "%s", strerror(errno)); + if (!proc->stdin_pipe) { // check that process hasn't been killed + strbuf_printf(proc->error, "Process terminated"); + return -2; + } + if (size > LLONG_MAX) { + strbuf_printf(proc->error, "Too much data to write."); return -2; } + size_t so_far = 0; + while (so_far < size) { + ssize_t bytes_written = write(proc->stdin_pipe, data + so_far, size - so_far); + if (bytes_written >= 0) { + so_far += (size_t)bytes_written; + } else if (errno == EAGAIN) { + return (long long)so_far; + } else { + strbuf_printf(proc->error, "%s", strerror(errno)); + return -2; + } + } + return (long long)size; } static long long process_read_fd(Process *proc, int fd, char *data, size_t size) { - assert(fd); - ssize_t bytes_read = read(fd, data, size); - if (bytes_read >= 0) { - return (long long)bytes_read; - } else if (errno == EAGAIN) { - return -1; - } else { - strbuf_printf(proc->error, "%s", strerror(errno)); + if (!fd) { // check that process hasn't been killed + strbuf_printf(proc->error, "Process terminated"); + return -2; + } + if (size > LLONG_MAX) { + strbuf_printf(proc->error, "Too much data to read."); return -2; } + size_t so_far = 0; + while (so_far < size) { + ssize_t bytes_read = read(fd, data + so_far, size - so_far); + if (bytes_read > 0) { + so_far += (size_t)bytes_read; + } else if (bytes_read == 0) { + return (long long)so_far; + } else if (errno == EAGAIN) { + return so_far == 0 ? -1 : (long long)so_far; + } else { + strbuf_printf(proc->error, "%s", strerror(errno)); + return -2; + } + } + return (long long)size; } long long process_read(Process *proc, char *data, size_t size) { @@ -130,7 +130,7 @@ void time_sleep_ns(u64 ns) { } #error "@TODO : implement process_write, separate_stderr, working_directory" - +#error "@TODO : make sure process_read & process_write do what they're supposed to for both blocking & non-blocking read/writes." #include "process.h" struct Process { @@ -104,6 +104,7 @@ const char *process_geterr(Process *process); // returns: // -2 on error // or a non-negative number indicating the number of bytes written. +// If stdin is set to blocking, fewer than `size` bytes will be written only if an error occured. long long process_write(Process *process, const char *data, size_t size); // read from stdout+stderr // returns: @@ -111,6 +112,7 @@ long long process_write(Process *process, const char *data, size_t size); // -1 if no data is available right now // 0 on end of file // or a positive number indicating the number of bytes read to data (at most size) +// If stdout is set to blocking, fewer than `size` bytes will be read only if an error occured or end-of-file was reached. long long process_read(Process *process, char *data, size_t size); // like process_read, but reads stderr. // this function ALWAYS RETURNS -2 if separate_stderr is not specified in the ProcessSettings. @@ -1009,6 +1009,7 @@ void build_check_for_errors(Ted *ted); void build_frame(Ted *ted, float x1, float y1, float x2, float y2); // === colors.c === +void color_init(void); ColorSetting color_setting_from_str(const char *str); const char *color_setting_to_str(ColorSetting s); Status color_from_str(const char *str, u32 *color); @@ -1017,6 +1018,7 @@ Status color_from_str(const char *str, u32 *color); ColorSetting color_for_symbol_kind(SymbolKind kind); // === command.c === +void command_init(void); Command command_from_str(const char *str); const char *command_to_str(Command c); void command_execute(Ted *ted, Command c, i64 argument); |