diff --git a/bb.c b/bb.c index 285538e..197ec36 100644 --- a/bb.c +++ b/bb.c @@ -132,9 +132,9 @@ static int compare_files(const void *v1, const void *v2, void *v); static void deselect_entry(bb_t *bb, entry_t *e); static int fputs_escaped(FILE *f, const char *str, const char *color); static void init_term(void); -static entry_t* load_entry(bb_t *bb, const char *path); +static entry_t* load_entry(bb_t *bb, const char *path, int clear_dots); static void* memcheck(void *p); -static void normalize_path(const char *root, const char *path, char *pbuf); +static void normalize_path(const char *root, const char *path, char *pbuf, int clear_dots); static void populate_files(bb_t *bb, const char *path); static void print_bindings(void); static bb_result_t process_cmd(bb_t *bb, const char *cmd); @@ -714,24 +714,13 @@ void set_scroll(bb_t *bb, int newscroll) * Warning: this does not deduplicate entries, and it's best if there aren't * duplicate entries hanging around. */ -entry_t* load_entry(bb_t *bb, const char *path) +entry_t* load_entry(bb_t *bb, const char *path, int clear_dots) { struct stat linkedstat, filestat; if (!path || !path[0]) return NULL; if (lstat(path, &filestat) == -1) return NULL; char pbuf[PATH_MAX]; - if (path[0] == '~' && (path[1] == '\0' || path[1] == '/')) { - char *home; - if (!(home = getenv("HOME"))) - return NULL; - strcpy(pbuf, home); - strcat(pbuf, path+1); - } else if (path[0] == '/') { - strcpy(pbuf, path); - } else { - strcpy(pbuf, bb->path); - strcat(pbuf, path); - } + normalize_path(bb->path, path, pbuf, clear_dots); if (pbuf[strlen(pbuf)-1] == '/' && pbuf[1]) pbuf[strlen(pbuf)-1] = '\0'; @@ -808,11 +797,11 @@ void sort_files(bb_t *bb) } /* - * Prepend `root` to relative paths, replace "~" with $HOME, replace "/foo/." - * with "/foo", replace "/foo/baz/.." with "/foo". + * Prepend `root` to relative paths, replace "~" with $HOME. + * If clear_dots is 1, then also replace "/foo/." with "/foo" and replace "/foo/baz/.." with "/foo". * The normalized path is stored in `normalized`. */ -void normalize_path(const char *root, const char *path, char *normalized) +void normalize_path(const char *root, const char *path, char *normalized, int clear_dots) { if (path[0] == '~' && (path[1] == '\0' || path[1] == '/')) { char *home; @@ -826,21 +815,23 @@ void normalize_path(const char *root, const char *path, char *normalized) } strcat(normalized, path); - char *src = normalized, *dest = normalized; - while (*src) { - while (src[0] == '/' && src[1] == '.') { - // Replace "foo/./?" with "foo/?" - if (src[2] == '/' || src[2] == '\0') { - src += 2; - } else if (src[2] == '.' && (src[3] == '/' || src[3] == '\0')) { - // Replace "foo/baz/../?" with "foo/?" - src += 3; - while (dest > normalized && *(--dest) != '/'); - } else break; + if (clear_dots) { + char *src = normalized, *dest = normalized; + while (*src) { + while (src[0] == '/' && src[1] == '.') { + // Replace "foo/./?" with "foo/?" + if (src[2] == '/' || src[2] == '\0') { + src += 2; + } else if (src[2] == '.' && (src[3] == '/' || src[3] == '\0')) { + // Replace "foo/baz/../?" with "foo/?" + src += 3; + while (dest > normalized && *(--dest) != '/'); + } else break; + } + *(dest++) = *(src++); } - *(dest++) = *(src++); + *dest = '\0'; } - *dest = '\0'; } int cd_to(bb_t *bb, const char *path) @@ -856,7 +847,7 @@ int cd_to(bb_t *bb, const char *path) strcpy(pbuf, bb->marks['-']); if (chdir(pbuf)) return -1; } else { - normalize_path(bb->path, path, pbuf); + normalize_path(bb->path, path, pbuf, 1); if (pbuf[strlen(pbuf)-1] != '/') strcat(pbuf, "/"); if (chdir(pbuf)) return -1; @@ -869,7 +860,7 @@ int cd_to(bb_t *bb, const char *path) populate_files(bb, pbuf); if (prev[0]) { - entry_t *p = load_entry(bb, prev); + entry_t *p = load_entry(bb, prev, 0); if (p) { if (IS_VIEWED(p)) set_cursor(bb, p->index); else try_free_entry(p); @@ -937,7 +928,7 @@ void populate_files(bb_t *bb, const char *path) bb->files = memcheck(realloc(bb->files, (space += 100)*sizeof(void*))); strcpy(&pathbuf[pathbuflen], dp->d_name); // Don't normalize path so we can get "." and ".." - entry_t *entry = load_entry(bb, pathbuf); + entry_t *entry = load_entry(bb, pathbuf, 0); if (!entry) err("Failed to load entry: '%s'", dp->d_name); entry->index = bb->nfiles; bb->files[bb->nfiles++] = entry; @@ -1020,8 +1011,8 @@ bb_result_t process_cmd(bb_t *bb, const char *cmd) if (!value && !bb->nfiles) return BB_INVALID; if (!value) value = bb->files[bb->cursor]->fullname; char pbuf[PATH_MAX]; - normalize_path(bb->path, value, pbuf); - entry_t *e = load_entry(bb, pbuf); + normalize_path(bb->path, value, pbuf, 1); + entry_t *e = load_entry(bb, pbuf, 0); if (e) { deselect_entry(bb, e); return BB_OK; @@ -1044,7 +1035,7 @@ bb_result_t process_cmd(bb_t *bb, const char *cmd) } case 'g': { // +goto: if (!value) return BB_INVALID; - entry_t *e = load_entry(bb, value); + entry_t *e = load_entry(bb, value, 1); if (!e) return BB_INVALID; if (IS_VIEWED(e)) { set_cursor(bb, e->index); @@ -1056,8 +1047,6 @@ bb_result_t process_cmd(bb_t *bb, const char *cmd) if (!lastslash) return BB_INVALID; *lastslash = '\0'; // Split in two cd_to(bb, pbuf); - e = load_entry(bb, lastslash+1); - if (!e) return BB_INVALID; if (IS_VIEWED(e)) { set_cursor(bb, e->index); return BB_OK; @@ -1143,9 +1132,7 @@ bb_result_t process_cmd(bb_t *bb, const char *cmd) case '\0': case 'e': { // +select: if (!value && !bb->nfiles) return BB_INVALID; if (!value) value = bb->files[bb->cursor]->fullname; - char pbuf[PATH_MAX]; - normalize_path(bb->path, value, pbuf); - entry_t *e = load_entry(bb, pbuf); + entry_t *e = load_entry(bb, value, 1); if (e) select_entry(bb, e); return BB_OK; } @@ -1161,9 +1148,7 @@ bb_result_t process_cmd(bb_t *bb, const char *cmd) case 't': { // +toggle: if (!value && !bb->nfiles) return BB_INVALID; if (!value) value = bb->files[bb->cursor]->fullname; - char pbuf[PATH_MAX]; - normalize_path(bb->path, value, pbuf); - entry_t *e = load_entry(bb, pbuf); + entry_t *e = load_entry(bb, value, 1); if (e) toggle_entry(bb, e); return BB_OK; } @@ -1511,7 +1496,7 @@ int main(int argc, char *argv[]) char path[PATH_MAX], curdir[PATH_MAX]; getcwd(curdir, PATH_MAX); strcat(curdir, "/"); - normalize_path(curdir, initial_path, path); + normalize_path(curdir, initial_path, path, 1); if (chdir(path)) err("Not a valid path: %s\n", path); bb_t *bb = memcheck(calloc(1, sizeof(bb_t)));