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"