From ce6d4861fb0c45419f5d9f8a1ee3fbe74f72c0f0 Mon Sep 17 00:00:00 2001 From: jfreegman Date: Wed, 17 Oct 2018 00:18:43 -0400 Subject: [PATCH] Fix bug where autocomplete added a forward slash to files with no extension Also slightly refactored the line complete functions --- src/autocomplete.c | 56 +++++++++++++++++++++++++++++++--------------- src/autocomplete.h | 29 ++++++++++++++---------- src/misc_tools.h | 4 ++-- 3 files changed, 57 insertions(+), 32 deletions(-) diff --git a/src/autocomplete.c b/src/autocomplete.c index 5468131..aa394bf 100644 --- a/src/autocomplete.c +++ b/src/autocomplete.c @@ -85,17 +85,22 @@ static size_t get_str_match(ToxWindow *self, char *match, size_t match_sz, char return snprintf(match, match_sz, "%s", matches[0]); } -/* looks for all instances in list that begin with the last entered word in line according to pos, +/* + * Looks for all instances in list that begin with the last entered word in line according to pos, * then fills line with the complete word. e.g. "Hello jo" would complete the line * with "Hello john". If multiple matches, prints out all the matches and semi-completes line. * * list is a pointer to the list of strings being compared, n_items is the number of items * in the list, and size is the size of each item in the list. * + * dir_search should be true if the line being completed is a file path. + * * Returns the difference between the old len and new len of line on success. * Returns -1 on error. + * + * Note: This function should not be called directly. Use complete_line() and complete_path() instead. */ -int complete_line(ToxWindow *self, const void *list, size_t n_items, size_t size) +static int complete_line_helper(ToxWindow *self, const void *list, size_t n_items, size_t size, bool dir_search) { ChatContext *ctx = self->chatwin; @@ -116,14 +121,6 @@ int complete_line(ToxWindow *self, const void *list, size_t n_items, size_t size return -1; } - /* TODO: generalize this */ - bool dir_search = !strncmp(ubuf, "/sendfile", strlen("/sendfile")) - || !strncmp(ubuf, "/avatar", strlen("/avatar")); - -#ifdef PYTHON - dir_search = dir_search || !strncmp(ubuf, "/run", strlen("/run")); -#endif - /* isolate substring from space behind pos to pos */ char tmp[MAX_STR_SIZE]; snprintf(tmp, sizeof(tmp), "%s", ubuf); @@ -133,7 +130,7 @@ int complete_line(ToxWindow *self, const void *list, size_t n_items, size_t size char *sub = calloc(1, strlen(ubuf) + 1); if (sub == NULL) { - exit_toxic_err("failed in complete_line", FATALERR_MEMORY); + exit_toxic_err("failed in complete_line_helper", FATALERR_MEMORY); } if (!s && !dir_search) { @@ -219,6 +216,21 @@ int complete_line(ToxWindow *self, const void *list, size_t n_items, size_t size } strcpy(&ubuf[strt], match); + + /* If path points to a file with no extension don't append a forward slash */ + if (dir_search && *endchrs == '/') { + const char *path_start = strchr(ubuf+1, '/'); + + if (!path_start) { // should never happen + return -1; + } + + if (file_type(path_start) == FILE_TYPE_REGULAR) { + endchrs = ""; + diff -= n_endchrs; + } + } + strcpy(&ubuf[strt + match_len], endchrs); strcpy(&ubuf[strt + match_len + n_endchrs], tmpend); @@ -237,6 +249,16 @@ int complete_line(ToxWindow *self, const void *list, size_t n_items, size_t size return diff; } +int complete_line(ToxWindow *self, const void *list, size_t n_items, size_t size) +{ + return complete_line_helper(self, list, n_items, size, false); +} + +static int complete_path(ToxWindow *self, const void *list, size_t n_items, size_t size) +{ + return complete_line_helper(self, list, n_items, size, true); +} + /* Transforms a tab complete starting with the shorthand "~" into the full home directory. */ static void complete_home_dir(ToxWindow *self, char *path, int pathsize, const char *cmd, int cmdlen) { @@ -266,15 +288,13 @@ static void complete_home_dir(ToxWindow *self, char *path, int pathsize, const c ctx->len = ctx->pos; } -/* Attempts to match /command line to matching directories. +/* Attempts to match /command "" line to matching directories. + * If there is only one match the line is auto-completed. * - * If only one match, auto-complete line. - * - * Returns diff between old len and new len of ctx->line. - * Returns -1 if no matches or > 1 match. + * Returns the diff between old len and new len of ctx->line on success. + * Returns -1 if no matches or more than one match. */ #define MAX_DIRS 512 - int dir_match(ToxWindow *self, Tox *m, const wchar_t *line, const wchar_t *cmd) { char b_path[MAX_STR_SIZE]; @@ -337,5 +357,5 @@ int dir_match(ToxWindow *self, Tox *m, const wchar_t *line, const wchar_t *cmd) print_matches(self, m, dirnames, dircount, NAME_MAX + 1); } - return complete_line(self, dirnames, dircount, NAME_MAX + 1); + return complete_path(self, dirnames, dircount, NAME_MAX + 1); } diff --git a/src/autocomplete.h b/src/autocomplete.h index 4c2c90d..64f5887 100644 --- a/src/autocomplete.h +++ b/src/autocomplete.h @@ -23,20 +23,25 @@ #ifndef AUTOCOMPLETE_H #define AUTOCOMPLETE_H -/* looks for all instances in list that begin with the last entered word in line according to pos, - then fills line with the complete word. e.g. "Hello jo" would complete the line - with "Hello john". If multiple matches, prints out all the matches and semi-completes line. - - list is a pointer to the list of strings being compared, n_items is the number of items - in the list, and size is the size of each item in the list. - - Returns the difference between the old len and new len of line on success, -1 if error */ +/* + * Looks for all instances in list that begin with the last entered word in line according to pos, + * then fills line with the complete word. e.g. "Hello jo" would complete the line + * with "Hello john". If multiple matches, prints out all the matches and semi-completes line. + * + * list is a pointer to the list of strings being compared, n_items is the number of items + * in the list, and size is the size of each item in the list. + * + * Returns the difference between the old len and new len of line on success. + * Returns -1 on error. + */ int complete_line(ToxWindow *self, const void *list, size_t n_items, size_t size); -/* attempts to match /command "" line to matching directories. - - if only one match, auto-complete line. - return diff between old len and new len of ctx->line, -1 if no matches or > 1 match */ +/* Attempts to match /command "" line to matching directories. + * If there is only one match the line is auto-completed. + * + * Returns the diff between old len and new len of ctx->line on success. + * Returns -1 if no matches or more than one match. + */ int dir_match(ToxWindow *self, Tox *m, const wchar_t *line, const wchar_t *cmd); #endif /* AUTOCOMPLETE_H */ diff --git a/src/misc_tools.h b/src/misc_tools.h index 92f48ee..dd97683 100644 --- a/src/misc_tools.h +++ b/src/misc_tools.h @@ -86,13 +86,13 @@ int string_is_empty(const char *string); /* Same as above but for wide character strings */ int wstring_is_empty(const wchar_t *string); -/* convert a multibyte string to a wide character string (must provide buffer) */ +/* converts a multibyte string to a wide character string (must provide buffer) */ int char_to_wcs_buf(wchar_t *buf, const char *string, size_t n); /* converts wide character string into a multibyte string and puts in buf. */ int wcs_to_mbs_buf(char *buf, const wchar_t *string, size_t n); -/* convert a multibyte string to a wide character string and puts in buf) */ +/* converts a multibyte string to a wide character string and puts in buf) */ int mbs_to_wcs_buf(wchar_t *buf, const char *string, size_t n); /* Returns 1 if connection has timed out, 0 otherwise */