aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rw-r--r--LICENSE2
-rw-r--r--NEWS5
-rw-r--r--README.adoc18
-rwxr-xr-xsdn-open72
-rw-r--r--sdn-open.123
-rw-r--r--sdn-view.15
-rw-r--r--sdn.17
-rw-r--r--sdn.cpp20
9 files changed, 135 insertions, 21 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d0a6042..7e62183 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -33,9 +33,9 @@ include (GNUInstallDirs)
# sdn-mc-ext should be in libexec, but we prefer it in PATH.
install (TARGETS sdn sdn-mc-ext
DESTINATION ${CMAKE_INSTALL_BINDIR})
-install (PROGRAMS sdn-install sdn-view
+install (PROGRAMS sdn-install sdn-open sdn-view
DESTINATION ${CMAKE_INSTALL_BINDIR})
-install (FILES sdn.1 sdn-install.1 sdn-view.1
+install (FILES sdn.1 sdn-install.1 sdn-open.1 sdn-view.1
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
install (FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
diff --git a/LICENSE b/LICENSE
index 7511f3e..689d036 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2017 - 2024, Přemysl Eric Janouch <p@janouch.name>
+Copyright (c) 2017 - 2025, Přemysl Eric Janouch <p@janouch.name>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
diff --git a/NEWS b/NEWS
index 54e2935..1ac3c33 100644
--- a/NEWS
+++ b/NEWS
@@ -5,7 +5,7 @@ Unreleased
- + and - adjust the selection using shell globs;
- t and T insert the selection into the external command line
in relative or absolute form, respectively;
- - Enter is like t but enters directories, and M-Enter is synonymous to t;
+ - Enter is like t but enters directories;
- C-g or Escape clear the selection, similarly to the editor.
* Added an sdn-view script that can process Midnight Commander mc.ext.ini files
@@ -13,6 +13,9 @@ Unreleased
while the original direct pager invocation has been moved to F13 (which also
reflects Midnight Commander)
+ * Added an sdn-open script which does the same kind of processing as above
+ on top of xdg-open. This is what is now executed by M-Enter.
+
1.0.0 (2024-12-21)
diff --git a/README.adoc b/README.adoc
index 8789821..b7aeecf 100644
--- a/README.adoc
+++ b/README.adoc
@@ -5,7 +5,8 @@ sdn
'sdn' is a simple directory navigator that you can invoke while editing shell
commands. It enables you to:
- * take a quick peek at directory contents without running `ls`
+ * take a quick peek at directory contents without running `ls`;
+ * select files to insert into the command line;
* browse the filesystem without all the mess that Midnight Commander does:
there's no need to create a subshell in a new pty. The current command line
can be simply forwarded if it is to be edited. What's more, it will always
@@ -75,6 +76,7 @@ that of git, only named colours aren't supported:
....
cursor 231 202
+select 202 bold
bar 16 255 ul
cwd bold
input
@@ -91,15 +93,19 @@ To obtain more vifm-like controls, you may write the following to your
....
normal h parent
-normal l choose
+normal l enter
....
Helper programs
~~~~~~~~~~~~~~~
-The F3 and F4 keys are normally bound to actions 'view' and 'edit', similarly to
-Norton Commander and other orthodox file managers. The helper programs used
-here may be changed by setting the PAGER and VISUAL (or EDITOR) environment
-variables.
+The F3, F13 and F4 keys are normally bound to actions 'view', 'view-raw',
+and 'edit', similarly to Norton Commander and other orthodox file managers.
+The helper programs used here may be changed by setting the PAGER and VISUAL
+(or EDITOR) environment variables.
+
+If 'view' finds Midnight Commander, it will make use of its configuration
+to apply any matching filter, such as to produce archive listings,
+or it will run the respective command.
While it is mostly possible to get 'mcview' working using an invocation like
`PAGER='mcview -u' sdn`, beware that this helper cannot read files from its
diff --git a/sdn-open b/sdn-open
new file mode 100755
index 0000000..5eb048f
--- /dev/null
+++ b/sdn-open
@@ -0,0 +1,72 @@
+#!/bin/sh -e
+# sdn-open: an opener for sdn that makes use of Midnight Commander configuration
+# to make more kinds of files directly openable
+
+if [ "$#" -ne 1 ]
+then
+ echo "Usage: $0 FILE" >&2
+ exit 2
+fi
+
+# This handles both MC_DATADIR and odd installation locations.
+datadir=
+if command -v mc >/dev/null
+then datadir=$(mc --datadir | sed 's/ (.*)$//')
+fi
+
+config=
+for dir in "$HOME"/.config/mc "$datadir" /etc/mc
+do
+ if [ -n "$dir" -a -f "$dir/mc.ext.ini" ]
+ then
+ config=$dir/mc.ext.ini
+ break
+ fi
+done
+
+# This is often used in %env{} expansion, so let's be on the same page.
+export PAGER=${PAGER:-less}
+
+export MC_EXT_FILENAME=$(realpath "$1")
+export MC_EXT_BASENAME=$(basename "$1")
+export MC_EXT_CURRENTDIR=$(dirname "$MC_EXT_FILENAME")
+output=$(sdn-mc-ext <"$config" "$(file -Lbz "$1")" \
+ "$MC_EXT_FILENAME" "$MC_EXT_BASENAME" "$MC_EXT_CURRENTDIR" Open || :)
+kind=$(echo "$output" | sed -n 1p)
+command=$(echo "$output" | sed -n 2p)
+
+# We're trying to retain any explicit user preferences while navigating through:
+# - Debian-based systems have /etc/alternatives/open as /usr/bin/open,
+# pointing to either /usr/bin/xdg-open or /usr/bin/run-mailcap;
+# - macOS has /usr/bin/open, and typically no xdg-open;
+# - Windows Subsystem for Linux has explorer.exe in PATH,
+# where launched applications may have problems with UNC paths,
+# and possibly also xdg-open that may not be capable of opening much.
+#
+# Both macOS open and Windows explorer.exe are capable of opening files,
+# directories, as well as URLs through native associations.
+if [ -n "$MC_XDG_OPEN" ]
+then :
+elif command -v explorer.exe >/dev/null
+then export MC_XDG_OPEN=explorer.exe
+elif command -v open >/dev/null
+then export MC_XDG_OPEN=open
+elif command -v xdg-open >/dev/null
+then export MC_XDG_OPEN=xdg-open
+fi
+
+case "$kind" in
+cd)
+ # These mostly enter virtual filesystems, which we do not understand.
+ "$MC_XDG_OPEN" "$MC_EXT_FILENAME"
+ ;;
+'')
+ if [ -n "$command" ]
+ then eval "$command"
+ else "$MC_XDG_OPEN" "$MC_EXT_FILENAME"
+ fi
+ ;;
+*)
+ echo "Unsupported: $kind" >&2
+ exit 1
+esac
diff --git a/sdn-open.1 b/sdn-open.1
new file mode 100644
index 0000000..b234329
--- /dev/null
+++ b/sdn-open.1
@@ -0,0 +1,23 @@
+.Dd November 20, 2025
+.Dt SDN-OPEN 1
+.Os
+.Sh NAME
+.Nm sdn-open
+.Nd run Midnight Commander open configuration externally
+.Sh SYNOPSIS
+.Nm sdn-open
+.Ar path
+.Sh DESCRIPTION
+.Nm
+invokes
+.Xr xdg-open 1
+on the passed filename.
+.Pp
+If it succeeds in finding a
+.Xr mc 1
+.Pa mc.ext.ini
+file, it will first process it, and run any matching command instead.
+.Sh REPORTING BUGS
+Use
+.Lk https://git.janouch.name/p/sdn
+to report bugs, request features, or submit pull requests.
diff --git a/sdn-view.1 b/sdn-view.1
index d78d325..b8c26c9 100644
--- a/sdn-view.1
+++ b/sdn-view.1
@@ -1,4 +1,4 @@
-.Dd December 28, 2024
+.Dd December 30, 2024
.Dt SDN-VIEW 1
.Os
.Sh NAME
@@ -16,7 +16,8 @@ or a fallback pager on the passed filename.
If it succeeds in finding a
.Xr mc 1
.Pa mc.ext.ini
-file, it will first process it, and apply any matching filter.
+file, it will first process it, and apply any matching filter,
+or run the respective command.
.Sh REPORTING BUGS
Use
.Lk https://git.janouch.name/p/sdn
diff --git a/sdn.1 b/sdn.1
index 0c9ee8d..8e76708 100644
--- a/sdn.1
+++ b/sdn.1
@@ -1,5 +1,5 @@
\" https://mandoc.bsd.lv/man/roff.7.html#Sentence_Spacing
-.Dd October 27, 2020
+.Dd December 30, 2024
.Dt SDN 1
.Os
.Sh NAME
@@ -95,7 +95,7 @@ names are used for special keys.
To obtain more vifm-like controls and Windows-like quit abilities:
.Bd -literal -offset indent
normal h parent
-normal l choose
+normal l enter
normal M-f4 quit
.Ed
.Pp
@@ -107,7 +107,7 @@ For rxvt, that would be:
define C-ppage ^[[5^
define C-npage ^[[6^
normal C-ppage parent
-normal C-npage choose
+normal C-npage enter
.Ed
.Pp
Escape characters must be inserted verbatim, e.g., by pressing C-v ESC in vi,
@@ -120,6 +120,7 @@ For a black-on-white terminal supporting 256 colours, a theme such as the
following may work:
.Bd -literal -offset indent
cursor 231 202
+select 202 bold
bar 16 255 ul
cwd bold
input
diff --git a/sdn.cpp b/sdn.cpp
index 624047a..c5ea7af 100644
--- a/sdn.cpp
+++ b/sdn.cpp
@@ -1,7 +1,7 @@
//
// sdn: simple directory navigator
//
-// Copyright (c) 2017 - 2024, Přemysl Eric Janouch <p@janouch.name>
+// Copyright (c) 2017 - 2025, Přemysl Eric Janouch <p@janouch.name>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted.
@@ -430,8 +430,8 @@ enum { ALT = 1 << 24, SYM = 1 << 25 }; // Outside the range of Unicode
#define CTRL(char) ((char) == '?' ? 0x7f : (char) & 0x1f)
#define ACTIONS(XX) XX(NONE) XX(HELP) XX(QUIT) XX(QUIT_NO_CHDIR) \
- XX(ENTER) XX(CHOOSE) XX(CHOOSE_FULL) XX(VIEW_RAW) XX(VIEW) XX(EDIT) \
- XX(SORT_LEFT) XX(SORT_RIGHT) \
+ XX(ENTER) XX(OPEN) XX(CHOOSE) XX(CHOOSE_FULL) \
+ XX(VIEW_RAW) XX(VIEW) XX(EDIT) XX(SORT_LEFT) XX(SORT_RIGHT) \
XX(SELECT) XX(DESELECT) XX(SELECT_TOGGLE) XX(SELECT_ABORT) \
XX(UP) XX(DOWN) XX(TOP) XX(BOTTOM) XX(HIGH) XX(MIDDLE) XX(LOW) \
XX(PAGE_PREVIOUS) XX(PAGE_NEXT) XX(SCROLL_UP) XX(SCROLL_DOWN) XX(CENTER) \
@@ -453,7 +453,7 @@ static const char *g_action_names[] = {ACTIONS(XX)};
static map<wint_t, action> g_normal_actions {
{'\r', ACTION_ENTER}, {KEY (ENTER), ACTION_ENTER},
- {ALT | '\r', ACTION_CHOOSE}, {ALT | KEY (ENTER), ACTION_CHOOSE},
+ {ALT | '\r', ACTION_OPEN}, {ALT | KEY (ENTER), ACTION_OPEN},
{'t', ACTION_CHOOSE}, {'T', ACTION_CHOOSE_FULL},
{KEY (F (1)), ACTION_HELP}, {'h', ACTION_HELP},
{KEY (F (3)), ACTION_VIEW}, {KEY (F (13)), ACTION_VIEW_RAW},
@@ -1056,13 +1056,18 @@ fun run_program (initializer_list<const char *> list, const string &filename) {
update ();
}
+fun sdn_open (const string &filename) {
+ run_program ({(const char *) getenv ("SDN_OPENER"), "sdn-open", "xdg-open"},
+ filename);
+}
+
fun view_raw (const string &filename) {
// XXX: we cannot realistically detect that the pager hasn't made a pause
// at the end of the file, so we can't ensure all contents have been seen
run_program ({(const char *) getenv ("PAGER"), "less", "cat"}, filename);
}
-fun view (const string &filename) {
+fun sdn_view (const string &filename) {
run_program ({(const char *) getenv ("SDN_VIEWER"), "sdn-view",
(const char *) getenv ("PAGER"), "less", "cat"}, filename);
}
@@ -1525,12 +1530,15 @@ fun handle (wint_t c) -> bool {
case ACTION_ENTER:
enter (current);
break;
+ case ACTION_OPEN:
+ sdn_open (current.filename);
+ break;
case ACTION_VIEW_RAW:
// Mimic mc, it does not seem sensible to page directories
(is_directory ? change_dir : view_raw) (current.filename);
break;
case ACTION_VIEW:
- (is_directory ? change_dir : view) (current.filename);
+ (is_directory ? change_dir : sdn_view) (current.filename);
break;
case ACTION_EDIT:
edit (current.filename);