Survive a removed CWD, as well as an empty root

All the omitted error checking sometimes sucks a lot,
and I need to include it later anyway.
This commit is contained in:
Přemysl Eric Janouch 2020-10-02 16:31:36 +02:00
parent 2d6d0582a1
commit cf80a15501
Signed by: p
GPG Key ID: A0420B94F92B9493
1 changed files with 22 additions and 14 deletions

36
sdn.cpp
View File

@ -791,6 +791,11 @@ fun operator< (const entry &e1, const entry &e2) -> bool {
return a.filename < b.filename; return a.filename < b.filename;
} }
fun at_cursor () -> const entry & {
static entry invalid;
return g.cursor >= int (g.entries.size ()) ? invalid : g.entries[g.cursor];
}
fun reload (bool keep_anchor) { fun reload (bool keep_anchor) {
g.unames.clear(); g.unames.clear();
while (auto *ent = getpwent ()) while (auto *ent = getpwent ())
@ -803,8 +808,8 @@ fun reload (bool keep_anchor) {
endgrent(); endgrent();
string anchor; string anchor;
if (keep_anchor && !g.entries.empty ()) if (keep_anchor)
anchor = g.entries.at (g.cursor).filename; anchor = at_cursor ().filename;
auto now = time (NULL); g.now = *localtime (&now); auto now = time (NULL); g.now = *localtime (&now);
auto dir = opendir ("."); auto dir = opendir (".");
@ -832,8 +837,8 @@ fun reload (bool keep_anchor) {
longest = max (longest, compute_width (entry.cols[col])); longest = max (longest, compute_width (entry.cols[col]));
} }
g.cursor = min (g.cursor, int (g.entries.size ()) - 1); g.cursor = max (0, min (g.cursor, int (g.entries.size ()) - 1));
g.offset = min (g.offset, int (g.entries.size ()) - 1); g.offset = max (0, min (g.offset, int (g.entries.size ()) - 1));
if (g.inotify_wd != -1) if (g.inotify_wd != -1)
inotify_rm_watch (g.inotify_fd, g.inotify_wd); inotify_rm_watch (g.inotify_fd, g.inotify_wd);
@ -986,16 +991,16 @@ fun search (const wstring &needle) {
} }
fun fix_cursor_and_offset () { fun fix_cursor_and_offset () {
g.cursor = max (g.cursor, 0);
g.cursor = min (g.cursor, int (g.entries.size ()) - 1); g.cursor = min (g.cursor, int (g.entries.size ()) - 1);
g.cursor = max (g.cursor, 0);
// Decrease the offset when more items can suddenly fit // Decrease the offset when more items can suddenly fit
int pushable = visible_lines () - (int (g.entries.size ()) - g.offset); int pushable = visible_lines () - (int (g.entries.size ()) - g.offset);
g.offset -= max (pushable, 0); g.offset -= max (pushable, 0);
// Make sure the cursor is visible // Make sure the cursor is visible
g.offset = max (g.offset, 0);
g.offset = min (g.offset, int (g.entries.size ()) - 1); g.offset = min (g.offset, int (g.entries.size ()) - 1);
g.offset = max (g.offset, 0);
if (g.offset > g.cursor) if (g.offset > g.cursor)
g.offset = g.cursor; g.offset = g.cursor;
@ -1040,7 +1045,7 @@ fun pop_levels (const string& old_cwd) {
} }
fix_cursor_and_offset (); fix_cursor_and_offset ();
if (!anchor.empty () && g.entries[g.cursor].filename != anchor) if (!anchor.empty () && at_cursor ().filename != anchor)
search (to_wide (anchor)); search (to_wide (anchor));
} }
@ -1112,7 +1117,7 @@ fun change_dir (const string &path) {
return; return;
} }
level last {g.offset, g.cursor, g.cwd, g.entries[g.cursor].filename}; level last {g.offset, g.cursor, g.cwd, at_cursor ().filename};
g.cwd = full_path; g.cwd = full_path;
bool same_path = last.path == g.cwd; bool same_path = last.path == g.cwd;
reload (same_path); reload (same_path);
@ -1128,8 +1133,11 @@ fun change_dir (const string &path) {
// Roughly follows the POSIX description of the PWD environment variable // Roughly follows the POSIX description of the PWD environment variable
fun initial_cwd () -> string { fun initial_cwd () -> string {
char cwd[4096] = ""; getcwd (cwd, sizeof cwd); char cwd[4096] = ""; const char *pwd = getenv ("PWD");
const char *pwd = getenv ("PWD"); if (!getcwd (cwd, sizeof cwd)) {
show_message (strerror (errno));
return pwd;
}
if (!pwd || pwd[0] != '/' || strlen (pwd) >= PATH_MAX) if (!pwd || pwd[0] != '/' || strlen (pwd) >= PATH_MAX)
return cwd; return cwd;
@ -1198,7 +1206,7 @@ fun handle (wint_t c) -> bool {
c = WEOF; c = WEOF;
} }
const auto &current = g.entries[g.cursor]; const auto &current = at_cursor ();
bool is_directory = bool is_directory =
S_ISDIR (current.info.st_mode) || S_ISDIR (current.info.st_mode) ||
S_ISDIR (current.target_info.st_mode); S_ISDIR (current.target_info.st_mode);
@ -1300,7 +1308,7 @@ fun handle (wint_t c) -> bool {
search (g.editor_line); search (g.editor_line);
}; };
g.editor_on_confirm = [] { g.editor_on_confirm = [] {
choose (g.entries[g.cursor]); choose (at_cursor ());
}; };
break; break;
case ACTION_RENAME_PREFILL: case ACTION_RENAME_PREFILL:
@ -1310,7 +1318,7 @@ fun handle (wint_t c) -> bool {
g.editor = L"rename"; g.editor = L"rename";
g.editor_on_confirm = [] { g.editor_on_confirm = [] {
auto mb = to_mb (g.editor_line); auto mb = to_mb (g.editor_line);
rename (g.entries[g.cursor].filename.c_str (), mb.c_str ()); rename (at_cursor ().filename.c_str (), mb.c_str ());
reload (true); reload (true);
}; };
break; break;
@ -1642,7 +1650,7 @@ fun save_config () {
to_string (i->offset), to_string (i->cursor), i->filename}); to_string (i->offset), to_string (i->cursor), i->filename});
write_line (*config, {"history", hostname, ppid, g.cwd, write_line (*config, {"history", hostname, ppid, g.cwd,
to_string (g.offset), to_string (g.cursor), to_string (g.offset), to_string (g.cursor),
g.entries[g.cursor].filename}); at_cursor ().filename});
} }
int main (int argc, char *argv[]) { int main (int argc, char *argv[]) {