From 42572f5c445497296ae70100d5e51370c8bba410 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Fri, 19 Feb 2021 11:13:16 -0500 Subject: started tags --- config.c | 1 + main.c | 3 +++ tags.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ted.cfg | 2 ++ ted.h | 15 +++++++++++ 5 files changed, 107 insertions(+) create mode 100644 tags.c diff --git a/config.c b/config.c index 23fe5c9..fcdf7c0 100644 --- a/config.c +++ b/config.c @@ -202,6 +202,7 @@ void config_read(Ted *ted, char const *filename) { }; OptionString const options_string[] = { {"build-default-command", settings->build_default_command, sizeof settings->build_default_command}, + {"tags-filename", settings->tags_filename, sizeof settings->tags_filename}, }; FILE *fp = fopen(filename, "rb"); diff --git a/main.c b/main.c index bbcbeda..a1c3cc0 100644 --- a/main.c +++ b/main.c @@ -61,6 +61,7 @@ no_warn_end #include "syntax.c" #include "buffer.c" #include "ted.c" +#include "tags.c" #include "ui.c" #include "find.c" #include "node.c" @@ -389,6 +390,8 @@ int main(int argc, char **argv) { ted->scroll_total_x = ted->scroll_total_y = 0; //printf("%p\n",(void *)ted->drag_buffer); + + tags_read_if_changed(ted, &ted->tags); ted_update_window_dimensions(ted); diff --git a/tags.c b/tags.c new file mode 100644 index 0000000..b1fac23 --- /dev/null +++ b/tags.c @@ -0,0 +1,86 @@ +void tags_free(TagsFile *f) { + free(f->file_data); + arr_free(f->tags); + memset(f, 0, sizeof *f); +} + +void tags_read(Ted *ted, TagsFile *f) { + change_directory(ted->cwd); + Settings const *settings = &ted->settings; + char const *tags_filename = settings->tags_filename; + FILE *file = fopen(tags_filename, "rb"); + tags_free(f); + if (file) { + fseek(file, 0, SEEK_END); + size_t file_size = (size_t)ftell(file); + fseek(file, 0, SEEK_SET); + char *file_data = ted_calloc(ted, file_size + 1, 1); + if (file_data) { + f->file_data = file_data; + fread(file_data, 1, file_size, file); + char *p = file_data; + while (1) { + // each line in the file is of the format: + // tag name\tfile name\taddress + // or + // tag name\tfile name\taddress;" additional information + + char *end = p + strcspn(p, "\n"); + bool eof = *end == '\0'; + char *name = p; + char *name_end = strchr(name, '\t'); + if (name_end) { + *name_end = '\0'; + char *filename = name_end + 1; + char *filename_end = strchr(filename, '\t'); + if (filename_end) { + *filename_end = '\0'; + char *address = filename_end + 1; + char *address_end = address; + int backslashes = 0; + while (1) { + bool is_end = false; + switch (*address_end) { + case '\n': + case '\r': + is_end = true; + break; + case '\\': + ++backslashes; + break; + case '/': + if (address_end != address && backslashes % 2 == 0) + is_end = true; + break; + } + if (is_end) break; + if (*address_end != '\\') backslashes = 0; + ++address_end; + } + *address_end = '\0'; + if (address_end - address > 2 && address_end[-2] == ';' && address_end[-1] == '"') { + address_end[-2] = '\0'; + } + Tag tag = {.name = name, .file = filename, .address = address}; + arr_add(f->tags, tag); + } + } + if (eof) break; // end of file + p = end + 1; + } + } + f->last_modified = time_last_modified(tags_filename); + fclose(file); + } else { + ted_seterr(ted, "tags file does not exist."); + } +} + +void tags_read_if_changed(Ted *ted, TagsFile *f) { + Settings const *settings = &ted->settings; + char const *tags_filename = settings->tags_filename; + struct timespec modify_time = time_last_modified(tags_filename); + if (!timespec_eq(modify_time, f->last_modified)) { + tags_read(ted, f); + } +} \ No newline at end of file diff --git a/ted.cfg b/ted.cfg index b65ba41..ed665e0 100644 --- a/ted.cfg +++ b/ted.cfg @@ -24,6 +24,8 @@ line-numbers = on # If set to "on", when a file is changed by another program, it will be reloaded by ted without asking you. auto-reload = off build-default-command = make +# file name for ctags output +tags-filename = tags [keyboard] # motion and selection diff --git a/ted.h b/ted.h index e5bc126..4676fb7 100644 --- a/ted.h +++ b/ted.h @@ -79,6 +79,7 @@ typedef struct { u8 padding; u8 scrolloff; char build_default_command[256]; + char tags_filename[128]; // [i] = comma-separated string of file extensions for language i, or NULL for none char *language_extensions[LANG_COUNT]; } Settings; @@ -159,6 +160,18 @@ typedef struct { BufferEdit *redo_history; // dynamic array of redo history } TextBuffer; +typedef struct { + char const *name; + char const *file; + char const *address; +} Tag; + +typedef struct { + Tag *tags; // dynamic array of tags + char *file_data; + struct timespec last_modified; // time when tags file was last modified +} TagsFile; + ENUM_U16 { MENU_NONE, MENU_OPEN, @@ -254,6 +267,8 @@ typedef struct Ted { bool build_shown; // are we showing the build output? bool building; // is the build process running? + TagsFile tags; + BuildError *build_errors; // dynamic array of build errors u32 build_error; // build error we are currently "on" -- cgit v1.2.3