Compare commits
3 Commits
e60ffeeb20
...
9a12fd8021
Author | SHA1 | Date | |
---|---|---|---|
9a12fd8021 | |||
f596bb8f5e | |||
67da8d965b |
25
README.adoc
25
README.adoc
@ -52,9 +52,11 @@ To start using this navigator, put the following in your .zshrc:
|
|||||||
....
|
....
|
||||||
sdn-navigate () {
|
sdn-navigate () {
|
||||||
# ... possibly zle-line-init
|
# ... possibly zle-line-init
|
||||||
eval "`sdn`"
|
while eval "`sdn`"; do
|
||||||
[ -z "$cd" ] || cd "$cd"
|
[ -z "$cd" ] || cd "$cd"
|
||||||
[ -z "$insert" ] || LBUFFER="$LBUFFER$insert "
|
[ -z "$insert" ] || LBUFFER="$LBUFFER$insert "
|
||||||
|
[ -z "$helper" ] && break
|
||||||
|
eval "exec </dev/tty; $helper" || break
|
||||||
zle reset-prompt
|
zle reset-prompt
|
||||||
# ... possibly zle-line-finish
|
# ... possibly zle-line-finish
|
||||||
}
|
}
|
||||||
@ -65,19 +67,22 @@ bindkey '\eo' sdn-navigate
|
|||||||
bash
|
bash
|
||||||
----
|
----
|
||||||
Here we can't reset the prompt from within a `bind -x` handler but there is
|
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-navigate () {
|
||||||
SDN_L=$READLINE_LINE SDN_P=$READLINE_POINT
|
SDN_L=$READLINE_LINE SDN_P=$READLINE_POINT
|
||||||
READLINE_LINE=
|
READLINE_LINE=
|
||||||
|
|
||||||
eval "`sdn`"
|
while eval "`sdn`"; do
|
||||||
[[ -z "$cd" ]] || cd "$cd"
|
[[ -z "$cd" ]] || cd "$cd"
|
||||||
[[ -z "$insert" ]] || {
|
[[ -z "$insert" ]] || {
|
||||||
SDN_L="${SDN_L:0:$SDN_P}$insert ${SDN_L:$SDN_P}"
|
SDN_L="${SDN_L:0:$SDN_P}$insert ${SDN_L:$SDN_P}"
|
||||||
((SDN_P=SDN_P+${#insert}+1))
|
((SDN_P=SDN_P+${#insert}+1))
|
||||||
}
|
}
|
||||||
|
[[ -z "$helper" ]] && break
|
||||||
|
eval "$helper" || break
|
||||||
|
done
|
||||||
}
|
}
|
||||||
sdn-restore () {
|
sdn-restore () {
|
||||||
READLINE_LINE=$SDN_L READLINE_POINT=$SDN_P
|
READLINE_LINE=$SDN_L READLINE_POINT=$SDN_P
|
||||||
|
51
sdn.cpp
51
sdn.cpp
@ -504,6 +504,7 @@ static struct {
|
|||||||
bool gravity; ///< Entries are shoved to the bottom
|
bool gravity; ///< Entries are shoved to the bottom
|
||||||
bool reverse_sort; ///< Reverse sort
|
bool reverse_sort; ///< Reverse sort
|
||||||
bool show_hidden; ///< Show hidden files
|
bool show_hidden; ///< Show hidden files
|
||||||
|
bool ext_helpers; ///< Launch helpers externally
|
||||||
int max_widths[entry::COLUMNS]; ///< Column widths
|
int max_widths[entry::COLUMNS]; ///< Column widths
|
||||||
int sort_column = entry::FILENAME; ///< Sorting column
|
int sort_column = entry::FILENAME; ///< Sorting column
|
||||||
int sort_flash_ttl; ///< Sorting column flash TTL
|
int sort_flash_ttl; ///< Sorting column flash TTL
|
||||||
@ -512,6 +513,7 @@ static struct {
|
|||||||
int message_ttl; ///< Time to live for the message
|
int message_ttl; ///< Time to live for the message
|
||||||
|
|
||||||
string chosen; ///< Chosen item for the command line
|
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 no_chdir; ///< Do not tell the shell to chdir
|
||||||
bool quitting; ///< Whether we should quit already
|
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;
|
return a.filename < b.filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reload (const string &old_cwd) {
|
fun reload (bool keep_anchor) {
|
||||||
g.unames.clear();
|
g.unames.clear();
|
||||||
while (auto *ent = getpwent ())
|
while (auto *ent = getpwent ())
|
||||||
g.unames.emplace (ent->pw_uid, ent->pw_name);
|
g.unames.emplace (ent->pw_uid, ent->pw_name);
|
||||||
@ -796,8 +798,8 @@ fun reload (const string &old_cwd) {
|
|||||||
endgrent();
|
endgrent();
|
||||||
|
|
||||||
string anchor;
|
string anchor;
|
||||||
if (!g.entries.empty ())
|
if (keep_anchor && !g.entries.empty ())
|
||||||
anchor = g.entries[g.cursor].filename;
|
anchor = g.entries.at (g.cursor).filename;
|
||||||
|
|
||||||
auto now = time (NULL); g.now = *localtime (&now);
|
auto now = time (NULL); g.now = *localtime (&now);
|
||||||
auto dir = opendir (".");
|
auto dir = opendir (".");
|
||||||
@ -814,7 +816,7 @@ fun reload (const string &old_cwd) {
|
|||||||
sort (begin (g.entries), end (g.entries));
|
sort (begin (g.entries), end (g.entries));
|
||||||
g.out_of_date = false;
|
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++)
|
for (size_t i = 0; i < g.entries.size (); i++)
|
||||||
if (g.entries[i].filename == anchor)
|
if (g.entries[i].filename == anchor)
|
||||||
g.cursor = i;
|
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) {
|
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 ()) {
|
switch (pid_t child = fork ()) {
|
||||||
int status;
|
int status;
|
||||||
case -1:
|
case -1:
|
||||||
@ -853,8 +867,8 @@ fun run_program (initializer_list<const char*> list, const string &filename) {
|
|||||||
setpgid (0, 0);
|
setpgid (0, 0);
|
||||||
tcsetpgrp (STDOUT_FILENO, getpgid (0));
|
tcsetpgrp (STDOUT_FILENO, getpgid (0));
|
||||||
|
|
||||||
for (auto pager : list)
|
for (auto program : list)
|
||||||
if (pager) execl ("/bin/sh", "/bin/sh", "-c", (string (pager)
|
if (program) execl ("/bin/sh", "/bin/sh", "-c", (string (program)
|
||||||
+ " " + shell_escape (filename)).c_str (), NULL);
|
+ " " + shell_escape (filename)).c_str (), NULL);
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
default:
|
default:
|
||||||
@ -1089,12 +1103,13 @@ fun change_dir (const string &path) {
|
|||||||
auto old_cwd = g.cwd;
|
auto old_cwd = g.cwd;
|
||||||
level last {g.offset, g.cursor, old_cwd, g.entries[g.cursor].filename};
|
level last {g.offset, g.cursor, old_cwd, g.entries[g.cursor].filename};
|
||||||
g.cwd = full_path;
|
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)) {
|
if (is_ancestor_dir (last.path, g.cwd)) {
|
||||||
g.levels.push_back (last);
|
g.levels.push_back (last);
|
||||||
g.offset = g.cursor = 0;
|
g.offset = g.cursor = 0;
|
||||||
} else {
|
} else if (!same_path) {
|
||||||
pop_levels ();
|
pop_levels ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1206,12 +1221,12 @@ fun handle (wint_t c) -> bool {
|
|||||||
case ACTION_SORT_LEFT:
|
case ACTION_SORT_LEFT:
|
||||||
g.sort_column = (g.sort_column + entry::COLUMNS - 1) % entry::COLUMNS;
|
g.sort_column = (g.sort_column + entry::COLUMNS - 1) % entry::COLUMNS;
|
||||||
g.sort_flash_ttl = 2;
|
g.sort_flash_ttl = 2;
|
||||||
reload (g.cwd);
|
reload (true);
|
||||||
break;
|
break;
|
||||||
case ACTION_SORT_RIGHT:
|
case ACTION_SORT_RIGHT:
|
||||||
g.sort_column = (g.sort_column + entry::COLUMNS + 1) % entry::COLUMNS;
|
g.sort_column = (g.sort_column + entry::COLUMNS + 1) % entry::COLUMNS;
|
||||||
g.sort_flash_ttl = 2;
|
g.sort_flash_ttl = 2;
|
||||||
reload (g.cwd);
|
reload (true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACTION_UP:
|
case ACTION_UP:
|
||||||
@ -1284,7 +1299,7 @@ fun handle (wint_t c) -> bool {
|
|||||||
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 (g.entries[g.cursor].filename.c_str (), mb.c_str ());
|
||||||
reload (g.cwd);
|
reload (true);
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1293,17 +1308,17 @@ fun handle (wint_t c) -> bool {
|
|||||||
break;
|
break;
|
||||||
case ACTION_REVERSE_SORT:
|
case ACTION_REVERSE_SORT:
|
||||||
g.reverse_sort = !g.reverse_sort;
|
g.reverse_sort = !g.reverse_sort;
|
||||||
reload (g.cwd);
|
reload (true);
|
||||||
break;
|
break;
|
||||||
case ACTION_SHOW_HIDDEN:
|
case ACTION_SHOW_HIDDEN:
|
||||||
g.show_hidden = !g.show_hidden;
|
g.show_hidden = !g.show_hidden;
|
||||||
reload (g.cwd);
|
reload (true);
|
||||||
break;
|
break;
|
||||||
case ACTION_REDRAW:
|
case ACTION_REDRAW:
|
||||||
clear ();
|
clear ();
|
||||||
break;
|
break;
|
||||||
case ACTION_RELOAD:
|
case ACTION_RELOAD:
|
||||||
reload (g.cwd);
|
reload (true);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (c != KEY (RESIZE) && c != WEOF)
|
if (c != KEY (RESIZE) && c != WEOF)
|
||||||
@ -1569,6 +1584,8 @@ fun load_config () {
|
|||||||
g.reverse_sort = tokens.at (1) == "1";
|
g.reverse_sort = tokens.at (1) == "1";
|
||||||
else if (tokens.front () == "show-hidden" && tokens.size () > 1)
|
else if (tokens.front () == "show-hidden" && tokens.size () > 1)
|
||||||
g.show_hidden = tokens.at (1) == "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)
|
else if (tokens.front () == "sort-column" && tokens.size () > 1)
|
||||||
g.sort_column = stoi (tokens.at (1));
|
g.sort_column = stoi (tokens.at (1));
|
||||||
else if (tokens.front () == "history")
|
else if (tokens.front () == "history")
|
||||||
@ -1585,6 +1602,7 @@ fun save_config () {
|
|||||||
write_line (*config, {"gravity", g.gravity ? "1" : "0"});
|
write_line (*config, {"gravity", g.gravity ? "1" : "0"});
|
||||||
write_line (*config, {"reverse-sort", g.reverse_sort ? "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, {"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)});
|
write_line (*config, {"sort-column", to_string (g.sort_column)});
|
||||||
|
|
||||||
@ -1635,7 +1653,7 @@ int main (int argc, char *argv[]) {
|
|||||||
|
|
||||||
load_colors ();
|
load_colors ();
|
||||||
g.start_dir = g.cwd = initial_cwd ();
|
g.start_dir = g.cwd = initial_cwd ();
|
||||||
reload (g.cwd);
|
reload (false);
|
||||||
pop_levels ();
|
pop_levels ();
|
||||||
update ();
|
update ();
|
||||||
|
|
||||||
@ -1673,5 +1691,6 @@ int main (int argc, char *argv[]) {
|
|||||||
cout << "local cd=" << endl;
|
cout << "local cd=" << endl;
|
||||||
|
|
||||||
cout << "local insert=" << shell_escape (g.chosen) << endl;
|
cout << "local insert=" << shell_escape (g.chosen) << endl;
|
||||||
|
cout << "local helper=" << shell_escape (g.ext_helper) << endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user