Compare commits

...

3 Commits

Author SHA1 Message Date
9a12fd8021
Add ability to run helpers externally
So far experimental and essentially undocumented.
2020-09-29 01:33:19 +02:00
f596bb8f5e
reload() doesn't really need to know the old path
Just whether it's safe for it to keep an anchor on the current item.

I've left in the safety check for an empty entries array,
for the theoretical case of an empty or entirely filtered-out root
directory.  It will likely crash in that case, anyway,
the cursor may be either -1 or 0.
2020-09-28 22:52:33 +02:00
67da8d965b
Make anchor processing a bit more obvious 2020-09-28 22:18:17 +02:00
2 changed files with 50 additions and 26 deletions

View File

@ -52,9 +52,11 @@ To start using this navigator, put the following in your .zshrc:
....
sdn-navigate () {
# ... possibly zle-line-init
eval "`sdn`"
while eval "`sdn`"; do
[ -z "$cd" ] || cd "$cd"
[ -z "$insert" ] || LBUFFER="$LBUFFER$insert "
[ -z "$helper" ] && break
eval "exec </dev/tty; $helper" || break
zle reset-prompt
# ... possibly zle-line-finish
}
@ -65,19 +67,22 @@ bindkey '\eo' sdn-navigate
bash
----
Here we can't reset the prompt from within a `bind -x` handler but there is
an acceptable workaround:
an acceptable workaround that sadly submits a blank line:
....
sdn-navigate () {
SDN_L=$READLINE_LINE SDN_P=$READLINE_POINT
READLINE_LINE=
eval "`sdn`"
while eval "`sdn`"; do
[[ -z "$cd" ]] || cd "$cd"
[[ -z "$insert" ]] || {
SDN_L="${SDN_L:0:$SDN_P}$insert ${SDN_L:$SDN_P}"
((SDN_P=SDN_P+${#insert}+1))
}
[[ -z "$helper" ]] && break
eval "$helper" || break
done
}
sdn-restore () {
READLINE_LINE=$SDN_L READLINE_POINT=$SDN_P

51
sdn.cpp
View File

@ -504,6 +504,7 @@ static struct {
bool gravity; ///< Entries are shoved to the bottom
bool reverse_sort; ///< Reverse sort
bool show_hidden; ///< Show hidden files
bool ext_helpers; ///< Launch helpers externally
int max_widths[entry::COLUMNS]; ///< Column widths
int sort_column = entry::FILENAME; ///< Sorting column
int sort_flash_ttl; ///< Sorting column flash TTL
@ -512,6 +513,7 @@ static struct {
int message_ttl; ///< Time to live for the message
string chosen; ///< Chosen item for the command line
string ext_helper; ///< External helper to run
bool no_chdir; ///< Do not tell the shell to chdir
bool quitting; ///< Whether we should quit already
@ -784,7 +786,7 @@ fun operator< (const entry &e1, const entry &e2) -> bool {
return a.filename < b.filename;
}
fun reload (const string &old_cwd) {
fun reload (bool keep_anchor) {
g.unames.clear();
while (auto *ent = getpwent ())
g.unames.emplace (ent->pw_uid, ent->pw_name);
@ -796,8 +798,8 @@ fun reload (const string &old_cwd) {
endgrent();
string anchor;
if (!g.entries.empty ())
anchor = g.entries[g.cursor].filename;
if (keep_anchor && !g.entries.empty ())
anchor = g.entries.at (g.cursor).filename;
auto now = time (NULL); g.now = *localtime (&now);
auto dir = opendir (".");
@ -814,7 +816,7 @@ fun reload (const string &old_cwd) {
sort (begin (g.entries), end (g.entries));
g.out_of_date = false;
if (g.cwd == old_cwd && !anchor.empty ()) {
if (!anchor.empty ()) {
for (size_t i = 0; i < g.entries.size (); i++)
if (g.entries[i].filename == anchor)
g.cursor = i;
@ -842,8 +844,20 @@ fun show_message (const string &message, int ttl = 30) {
}
fun run_program (initializer_list<const char*> list, const string &filename) {
endwin ();
if (g.ext_helpers) {
// XXX: this doesn't try them all out, though it shouldn't make any
// noticeable difference
const char *found = nullptr;
for (auto program : list)
if ((found = program))
break;
g.ext_helper = "/bin/sh -c " +
shell_escape (string (found) + " " + shell_escape (filename));
g.quitting = true;
return;
}
endwin ();
switch (pid_t child = fork ()) {
int status;
case -1:
@ -853,8 +867,8 @@ fun run_program (initializer_list<const char*> list, const string &filename) {
setpgid (0, 0);
tcsetpgrp (STDOUT_FILENO, getpgid (0));
for (auto pager : list)
if (pager) execl ("/bin/sh", "/bin/sh", "-c", (string (pager)
for (auto program : list)
if (program) execl ("/bin/sh", "/bin/sh", "-c", (string (program)
+ " " + shell_escape (filename)).c_str (), NULL);
_exit (EXIT_FAILURE);
default:
@ -1089,12 +1103,13 @@ fun change_dir (const string &path) {
auto old_cwd = g.cwd;
level last {g.offset, g.cursor, old_cwd, g.entries[g.cursor].filename};
g.cwd = full_path;
reload (old_cwd);
bool same_path = old_cwd == g.cwd;
reload (same_path);
if (is_ancestor_dir (last.path, g.cwd)) {
g.levels.push_back (last);
g.offset = g.cursor = 0;
} else {
} else if (!same_path) {
pop_levels ();
}
}
@ -1206,12 +1221,12 @@ fun handle (wint_t c) -> bool {
case ACTION_SORT_LEFT:
g.sort_column = (g.sort_column + entry::COLUMNS - 1) % entry::COLUMNS;
g.sort_flash_ttl = 2;
reload (g.cwd);
reload (true);
break;
case ACTION_SORT_RIGHT:
g.sort_column = (g.sort_column + entry::COLUMNS + 1) % entry::COLUMNS;
g.sort_flash_ttl = 2;
reload (g.cwd);
reload (true);
break;
case ACTION_UP:
@ -1284,7 +1299,7 @@ fun handle (wint_t c) -> bool {
g.editor_on_confirm = [] {
auto mb = to_mb (g.editor_line);
rename (g.entries[g.cursor].filename.c_str (), mb.c_str ());
reload (g.cwd);
reload (true);
};
break;
@ -1293,17 +1308,17 @@ fun handle (wint_t c) -> bool {
break;
case ACTION_REVERSE_SORT:
g.reverse_sort = !g.reverse_sort;
reload (g.cwd);
reload (true);
break;
case ACTION_SHOW_HIDDEN:
g.show_hidden = !g.show_hidden;
reload (g.cwd);
reload (true);
break;
case ACTION_REDRAW:
clear ();
break;
case ACTION_RELOAD:
reload (g.cwd);
reload (true);
break;
default:
if (c != KEY (RESIZE) && c != WEOF)
@ -1569,6 +1584,8 @@ fun load_config () {
g.reverse_sort = tokens.at (1) == "1";
else if (tokens.front () == "show-hidden" && tokens.size () > 1)
g.show_hidden = tokens.at (1) == "1";
else if (tokens.front () == "ext-helpers" && tokens.size () > 1)
g.ext_helpers = tokens.at (1) == "1";
else if (tokens.front () == "sort-column" && tokens.size () > 1)
g.sort_column = stoi (tokens.at (1));
else if (tokens.front () == "history")
@ -1585,6 +1602,7 @@ fun save_config () {
write_line (*config, {"gravity", g.gravity ? "1" : "0"});
write_line (*config, {"reverse-sort", g.reverse_sort ? "1" : "0"});
write_line (*config, {"show-hidden", g.show_hidden ? "1" : "0"});
write_line (*config, {"ext-helpers", g.ext_helpers ? "1" : "0"});
write_line (*config, {"sort-column", to_string (g.sort_column)});
@ -1635,7 +1653,7 @@ int main (int argc, char *argv[]) {
load_colors ();
g.start_dir = g.cwd = initial_cwd ();
reload (g.cwd);
reload (false);
pop_levels ();
update ();
@ -1673,5 +1691,6 @@ int main (int argc, char *argv[]) {
cout << "local cd=" << endl;
cout << "local insert=" << shell_escape (g.chosen) << endl;
cout << "local helper=" << shell_escape (g.ext_helper) << endl;
return 0;
}