Set cursor to child when going to parent dir

That is, if it's missing from our history.

This makes for a more consistent experience when traversing
the filesystem.  Arguably, it's only good for when 'h' is
bound to the 'parent' action.

Also make sure that the offset and cursor are reset when
the path is changed.
This commit is contained in:
Přemysl Eric Janouch 2020-09-29 02:36:03 +02:00
parent 1507f2dff9
commit 93172797e1
Signed by: p
GPG Key ID: A0420B94F92B9493
1 changed files with 26 additions and 18 deletions

44
sdn.cpp
View File

@ -1004,7 +1004,19 @@ fun is_ancestor_dir (const string &ancestor, const string &of) -> bool {
return of[ancestor.length ()] == '/' || (ancestor == "/" && ancestor != of);
}
fun pop_levels () {
/// If `path` is equal to the `current` directory, or lies underneath it,
/// return it as a relative path
fun relativize (string current, const string &path) -> string {
if (current == path)
return ".";
if (current.back () != '/')
current += '/';
if (!strncmp (current.c_str (), path.c_str (), current.length ()))
return path.substr (current.length ());
return path;
}
fun pop_levels (const string& old_cwd) {
string anchor; auto i = g.levels.rbegin ();
while (i != g.levels.rend () && !is_ancestor_dir (i->path, g.cwd)) {
if (i->path == g.cwd) {
@ -1015,6 +1027,13 @@ fun pop_levels () {
i++;
g.levels.pop_back ();
}
// Don't pick up bullshit from foreign history entries, especially for /
if (is_ancestor_dir (g.cwd, old_cwd)) {
auto subpath = relativize (g.cwd, old_cwd);
anchor = subpath.substr (0, subpath.find ('/'));
}
fix_cursor_and_offset ();
if (!anchor.empty () && g.entries[g.cursor].filename != anchor)
search (to_wide (anchor));
@ -1047,18 +1066,6 @@ fun absolutize (const string &abs_base, const string &path) -> string {
return abs_base + "/" + path;
}
/// If `path` is equal to the `current` directory, or lies underneath it,
/// return it as a relative path
fun relativize (string current, const string &path) -> string {
if (current == path)
return ".";
if (current.back () != '/')
current += '/';
if (!strncmp (current.c_str (), path.c_str (), current.length ()))
return path.substr (current.length ());
return path;
}
// Roughly follows the POSIX description of `cd -L` because of symlinks.
// HOME and CDPATH handling is ommitted.
fun change_dir (const string &path) {
@ -1105,11 +1112,12 @@ fun change_dir (const string &path) {
bool same_path = last.path == g.cwd;
reload (same_path);
if (is_ancestor_dir (last.path, g.cwd)) {
g.levels.push_back (last);
if (!same_path) {
g.offset = g.cursor = 0;
} else if (!same_path) {
pop_levels ();
if (is_ancestor_dir (last.path, g.cwd))
g.levels.push_back (last);
else
pop_levels (last.path);
}
}
@ -1653,7 +1661,7 @@ int main (int argc, char *argv[]) {
load_colors ();
g.start_dir = g.cwd = initial_cwd ();
reload (false);
pop_levels ();
pop_levels (g.cwd);
update ();
// Invoking keypad() earlier would make ncurses flush its output buffer,