summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.c1
-rw-r--r--main.c3
-rw-r--r--tags.c86
-rw-r--r--ted.cfg2
-rw-r--r--ted.h15
5 files changed, 107 insertions, 0 deletions
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"