aboutsummaryrefslogtreecommitdiff
path: root/vis-open
diff options
context:
space:
mode:
authorTim Allen <screwtape@froup.com>2016-05-22 21:30:43 +1000
committerTim Allen <screwtape@froup.com>2016-05-28 17:49:51 +1000
commitcb53860369efa1a70a59a804ba88ba755be0acc1 (patch)
treefb2539b76eafd42db2683988d7c0b2e7ecf92c04 /vis-open
parentc5668016204d028fddc7a14d056b629095b527cf (diff)
downloadvis-cb53860369efa1a70a59a804ba88ba755be0acc1.tar.gz
vis-cb53860369efa1a70a59a804ba88ba755be0acc1.tar.xz
Rewrite vis-open to be more robust.
Rather than try to loop manually and build up a path, this new version exec's itself for each new directory scanned. Functional changes include: - We `set -e` at the top of the script, so any surprising permission-denied errors will automatically cause the script to exit with a helpful error message. - We now support the GNU "--" convention for splitting options from filename arguments, just in case somebody happens across a directory with a file named "-h" or "-p". - If launched with a single filename parameter, we automatically return it - if somebody writes ":e somepattern*" and it matches exactly one file, we might as well open it directly. - If we select a single filename parameter, we use `realpath` to build an absolute path for it - much more reliable than trying to build up a path while the user is navigating around. - If launched with a single directory parameter, we change into that directory and re-exec ourselves with ".." and all the files in that directory as arguments. This means we don't have to handle selection and recursion at the same time. - Note that if we recurse into a directory, we pass the "-f" parameter to suppress auto-selection - otherwise recursing into an empty directory would immediately select the ".." entry and pop you back out, which would be confusing. - The new version doesn't bother trying to manipulate `$VIS_MENU_ARGS` and sometimes add a prompt to it. Setting no prompt is the same as setting the prompt to an empty string, so we can just use an empty string as the default value. One specific use-case that this change cleans up is giving ":e" a pattern that matches multiple directories (for example, running ":e *e*" in the root of the vis repo). "ls -1" would list the contents of each directory (without a prefix, so you couldn't select those files) but would also print the directory names as headings followed by a colon, so you couldn't usefully select the directory names either. We get around this by only ever running "ls -1" without any arguments, so it only scans the current directory.
Diffstat (limited to 'vis-open')
-rwxr-xr-xvis-open51
1 files changed, 35 insertions, 16 deletions
diff --git a/vis-open b/vis-open
index 75ad679..f4bf037 100755
--- a/vis-open
+++ b/vis-open
@@ -1,38 +1,57 @@
#!/bin/sh
+set -e
-PATTERN="."
-VIS_MENU_ARGS="-b"
+VIS_MENU_PROMPT=""
+ALLOW_AUTO_SELECT=1
while [ $# -gt 0 ]; do
case "$1" in
-h|--help)
- echo "usage: $(basename $0) [-h] [-p prompt] [file-pattern]"
+ echo "usage: $(basename $0) [-h] [-p prompt] [-f] [--] [file-pattern]"
exit 0;
;;
-p)
- VIS_MENU_ARGS="$VIS_MENU_ARGS -p $2"
+ VIS_MENU_PROMPT=$2
shift
shift
;;
+ -f)
+ ALLOW_AUTO_SELECT=""
+ shift
+ ;;
+ --)
+ break
+ ;;
*)
- PATTERN=$*
break
;;
esac
done
-DIR=""
-[ ! -z "$PATTERN" -a "$PATTERN" != "." -a -d "$PATTERN" ] && DIR="$PATTERN"
+# At this point, all the remaining arguments should be the expansion of
+# any globs that were passed on the command line.
-while true; do
- SEL=$({ echo ..; ls -1 $PATTERN 2>/dev/null || echo $PATTERN; } | vis-menu $VIS_MENU_ARGS)
- [ -z "$SEL" ] && exit 1
- [ ! -z "$DIR" ] && SEL="$DIR/$SEL"
- if [ -d "$SEL" ]; then
- DIR="$SEL"
- PATTERN="$DIR"
+if [ $# -eq 1 -a "$ALLOW_AUTO_SELECT" = 1 ]; then
+ # If there were globs on the command-line, they've expanded to
+ # a single item, so we can just process it.
+
+ if [ -d "$1" ]; then
+ # Recurse and show the contents of the named directory,
+ # We pass -f to force the next iteration to present the
+ # full list, even if it's just an empty directory.
+ cd "$1"
+ exec "$0" -p "$VIS_MENU_PROMPT" -f .. $(ls -1)
else
- echo "$SEL"
+ # We've found a single item, and it's not a directory,
+ # so it must be a filename (or file-like thing) to open.
+ echo $(realpath "$1")
exit 0
fi
-done
+fi
+
+# At this point, we have a bunch of options we need to present to the
+# user so they can pick one.
+CHOICE=$(printf "%s\n" "$@" | vis-menu -b -p "$VIS_MENU_PROMPT")
+
+# Did they pick a file or directory? Who knows, let's let the next iteration figure it out.
+exec "$0" -p "$VIS_MENU_PROMPT" "$CHOICE"