diff options
author | Přemysl Eric Janouch <p@janouch.name> | 2024-12-28 00:28:22 +0100 |
---|---|---|
committer | Přemysl Eric Janouch <p@janouch.name> | 2024-12-28 04:58:13 +0100 |
commit | 3075d47aeb52f6549e957023d353d4c5cb857e54 (patch) | |
tree | 1a0c0fbf331d78a8a62106aeea7662bbf6af1ba9 /sdn-view | |
parent | 85b2d8a2ee966794768f26cfc2404c850d33e096 (diff) | |
download | sdn-3075d47aeb52f6549e957023d353d4c5cb857e54.tar.gz sdn-3075d47aeb52f6549e957023d353d4c5cb857e54.tar.xz sdn-3075d47aeb52f6549e957023d353d4c5cb857e54.zip |
Add and integrate a script to execute mc.ext.ini
Tsk, tsk, parasiting on what we wanted to replace.
macOS is annoying to port to.
Unfortunately, this script is also very slow, for some reason.
Diffstat (limited to 'sdn-view')
-rwxr-xr-x | sdn-view | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/sdn-view b/sdn-view new file mode 100755 index 0000000..b53db49 --- /dev/null +++ b/sdn-view @@ -0,0 +1,211 @@ +#!/bin/sh -e +# sdn-view: a viewer for sdn that makes use of Midnight Commander configuration +# to make more kinds of files directly viewable + +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 + +export SDN_VIEW_CONFIG= +for dir in "$HOME"/.config/mc "$datadir" /etc/mc +do + if [ -n "$dir" -a -f "$dir/mc.ext.ini" ] + then + SDN_VIEW_CONFIG=$dir/mc.ext.ini + break + fi +done + +export PAGER=${PAGER:-less} +export MC_EXT_FILENAME=$(realpath "$1") +export MC_EXT_BASENAME=$(basename "$1") +export MC_EXT_CURRENTDIR=$(dirname "$1") +export SDN_VIEW_TYPE=$(file -bz "$1") +process() (awk -f - <<'EOF' +BEGIN { + if (!(Config = ENVIRON["SDN_VIEW_CONFIG"])) + exit + + Verb = "View" + Section = "" + while ((getline < Config) > 0) { + if (/^\s*(#.*)?$/) { + # Skip. + } else if (/^\[[^]]+\]$/) { + Sections[++SectionsLen] = Section = substr($0, 2, length($0) - 2) + } else if (/^[^=]+=[^=]*$/) { + split($0, kv, "=") + Keys[Section, kv[1]] = kv[2] + } + } + + Type = ENVIRON["SDN_VIEW_TYPE"] + Path = ENVIRON["MC_EXT_FILENAME"] + Basename = ENVIRON["MC_EXT_BASENAME"] + Dirname = ENVIRON["MC_EXT_CURRENTDIR"] + + for (i = 1; i <= SectionsLen; i++) { + if (Sections[i] == "mc.ext.ini" || + Sections[i] == "Default" || + Sections[i] ~ /^Include[\/]/) + continue + try(Sections[i]) + } + + # Not attempting any inclusions here. + print expand_command(Keys["Default", Verb]) +} + +function try(section, pair, a, key, full, include) { + for (pair in Keys) { + split(pair, a, SUBSEP) + if (a[1] == section) + full[a[2]] = Keys[pair] + } + if ("Include" in full) { + delete full["Open"] + delete full["View"] + delete full["Edit"] + include = "Include/" full["Include"] + for (pair in Keys) { + split(pair, a, SUBSEP) + if (a[1] == include) + full[a[2]] = Keys[pair] + } + } + if (ENVIRON["SDN_VIEW_DEBUG"]) { + print "[" section "]" > "/dev/stderr" + for (key in full) + print " " key ": " full[key] > "/dev/stderr" + } + if (Verb in full && section_matches(full, Type, Basename)) { + print expand_command(full[Verb]) + exit + } +} + +function shell_escape(string) { + gsub(/'/, "'\\''", string) + return "'" string "'" +} + +function expand_command(cmd, toview, out, seq, argument, value, a, pipe) { + out = "" + while (match(cmd, /%[a-zA-Z]*\{[^}]*\}|%[a-zA-Z]+|%%/)) { + out = out substr(cmd, 1, RSTART - 1) + seq = substr(cmd, RSTART + 1, RLENGTH - 1) + cmd = substr(cmd, RSTART + RLENGTH) + + argument = "" + if (match(seq, /\{.*\}$/)) { + argument = substr(seq, RSTART + 1, RLENGTH - 2) + seq = substr(seq, 1, RSTART - 1) + } + + if (seq == "%") { + out = out "%" + } else if (seq == "p") { + out = out shell_escape(Basename) + } else if (seq == "f") { + out = out shell_escape(Path) + } else if (seq == "d") { + out = out shell_escape(Dirname) + } else if (seq == "view") { + toview = 1 + + sub(/^ +/, "", cmd) + split(argument, a, /,/) + for (value in a) { + if (a[value] == "hex") + pipe = pipe " | od -t x1" + + # more(1) and less(1) either ignore or display this: + #if (a[value] == "nroff") + # pipe = pipe " | col -b" + } + } else if (seq == "var") { + value = "" + if (!match(argument, /:.*/)) { + if (argument in ENVIRON) + value = ENVIRON[argument] + } else { + value = substr(argument, RSTART + 1) + argument = substr(argument, 1, RSTART - 1) + if (argument in ENVIRON) + value = ENVIRON[argument] + } + out = out shell_escape(value) + } else if (seq == "") { + print Config ": prompting not supported" > "/dev/stderr" + return + } else { + print Config ": unsupported: %" seq > "/dev/stderr" + return + } + } + out = out cmd pipe + + # While the processing is mostly generic for all verbs, + # we'd have to distinguish non-view commands in this AWK script's output. + if (!toview) + return + + # In the case of out == "", we should just explicitly pass it to the pager, + # however it currently mixes with the case of "we can't use this View=". + return out +} + +function section_matches(section, type, basename, value) { + if ("Directory" in section) + return 0 + + if ("Type" in section) { + value = section["Type"] + if ("TypeIgnoreCase" in section && + section["TypeIgnoreCase"] == "true") { + type = tolower(type) + value = tolower(value) + } + gsub(/\\\\/, "\\", value) + gsub(/\\ /, " ", value) + if (type !~ value) + return 0 + } + if ("Regex" in section) { + value = section["Regex"] + if ("RegexIgnoreCase" in section && + section["RegexIgnoreCase"] == "true") { + basename = tolower(basename) + value = tolower(value) + } + gsub(/\\\\/, "\\", value) + return basename ~ value + } else if ("Shell" in section) { + value = section["Shell"] + if ("RegexIgnoreCase" in section && + section["ShellIgnoreCase"] == "true") { + basename = tolower(basename) + value = tolower(value) + } + if (value !~ /^[.]/) + return value == basename + return length(basename) >= length(value) && + substr(basename, length(basename) - length(value) + 1) == value + } + return type != "" +} +EOF +) +command=$(process) +if [ -z "$command" ] +then "$PAGER" -- "$MC_EXT_FILENAME" +else eval "$command" | "$PAGER" +fi |