vis
a vi-like editor based on Plan 9's structural regular expressions
git clone https://9o.is/git/vis.git
vis-open
(2204B)
1 #!/bin/sh
2 set -e
3
4 # Later, we're going to want to set $IFS to a single newline, so let's prepare one.
5 NL='
6 '
7
8 fatal() {
9 echo "$@" >&2
10 exit 1
11 }
12
13 usage() {
14 fatal "Usage: $(basename "$0") [-f] [-p prompt] [--] [file-pattern]
15
16 Interactively select a file to open
17
18 Options:
19 -f always present given arguments, even when there is only one
20 -p use prompt as prompt string
21 file-pattern list of filenames and directories"
22 }
23
24 # print a list of filenames on stdin and distinguish directories
25 wrap_dirs() {
26 while read -r filename
27 do
28 if [ -d "$filename" ]; then
29 printf '%s/\n' "$filename"
30 else
31 printf '%s\n' "$filename"
32 fi
33 done
34 }
35
36 VIS_OPEN_LINES="${VIS_OPEN_LINES:-0}"
37 VIS_MENU_PROMPT=''
38 ALLOW_AUTO_SELECT='1'
39
40 while getopts fhp: opt; do
41 case "$opt" in
42 f)
43 ALLOW_AUTO_SELECT=''
44 ;;
45 p)
46 VIS_MENU_PROMPT="$OPTARG"
47 ;;
48 *)
49 usage
50 ;;
51 esac
52 done
53 shift "$((OPTIND - 1))"
54
55 # At this point, all the remaining arguments should be the expansion of
56 # any globs that were passed on the command line.
57
58 if [ "$#" -eq 1 ] && [ "$ALLOW_AUTO_SELECT" = '1' ]; then
59 # If there were globs on the command-line, they've expanded to
60 # a single item, so we can just process it.
61
62 if [ -d "$1" ]; then
63 # Recurse and show the contents of the named directory,
64 # We pass -f to force the next iteration to present the
65 # full list, even if it's just an empty directory.
66 cd "$1"
67 IFS="$NL" # Don't split ls output on tabs or spaces.
68 exec "$0" -p "$VIS_MENU_PROMPT" -f "$(ls -1)"
69 else
70 # We've found a single item, and it's not a directory,
71 # so it must be a filename (or file-like thing) to open,
72 # unless the parent directory does not exist.
73 parentdir="$(dirname -- "$1")"
74 if [ -d "$parentdir" ]; then
75 cd "$parentdir"
76 printf '%s/%s\n' "$(pwd -P)" "$(basename -- "${1%\*}")"
77 exit 0
78 else
79 exit 1
80 fi
81 fi
82 fi
83
84 # At this point, we have a bunch of options we need to present to the
85 # user so they can pick one.
86 CHOICE="$(printf '%s\n' '..' "$@" | wrap_dirs | vis-menu -b -l "$VIS_OPEN_LINES" -p "$VIS_MENU_PROMPT")"
87
88 # Did they pick a file or directory? Who knows, let's let the next iteration figure it out.
89 exec "$0" -p "$VIS_MENU_PROMPT" -- "$CHOICE"