Cleaned up and deduplicated some of the path normalization code.
This commit is contained in:
parent
302ed33d9c
commit
4c717185de
77
bb.c
77
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)));
|
||||
|
Loading…
Reference in New Issue
Block a user