vis

a vi-like editor based on Plan 9's structural regular expressions

git clone https://9o.is/git/vis.git

vis-complete

(1724B)


      1 #!/bin/sh
      2 set -e
      3 
      4 fatal() {
      5 	echo "$@" >&2
      6 	exit 1
      7 }
      8 
      9 usage() {
     10 	fatal "Usage: $(basename "$0") [--file|--word] [--] pattern
     11 
     12 Interactively complete file or word
     13 
     14 Options:
     15     --file   expand pattern into a list of matching file names (default)
     16     --word   apply pattern to a list of words from standard input
     17     pattern  pattern to be completed"
     18 }
     19 
     20 basic_regex_quote() { printf "%s" "$1" | sed 's|[\\.*^$[]|\\&|g'; }
     21 glob_quote () { printf "%s" "$1" | sed 's|[\\?*[]]|\\&|g'; }
     22 
     23 COMPLETE_WORD=0
     24 FIND_FILE_LIMIT="${FIND_FILE_LIMIT:-1000}"
     25 
     26 while [ $# -gt 0 ]; do
     27 	case "$1" in
     28 	--file)
     29 		COMPLETE_WORD=0
     30 		shift
     31 		;;
     32 	--word)
     33 		COMPLETE_WORD=1
     34 		shift
     35 		;;
     36 	--)
     37 		shift
     38 		break
     39 		;;
     40 	-*|'')
     41 		usage
     42 		;;
     43 	*)
     44 		break
     45 		;;
     46 	esac
     47 done
     48 
     49 [ "$#" -lt 1 ] && usage
     50 
     51 PATTERN="$1"
     52 
     53 if [ $COMPLETE_WORD = 1 ]; then
     54 	# shellcheck disable=SC1003
     55 	tr -s '\t {}()[],<>%^&.\\' '\n' |
     56 		grep "^$(basic_regex_quote "$PATTERN")." |
     57 		sort -u
     58 else
     59 	# Expand to absolute path because of the -path option below.
     60 	# shellcheck disable=SC2088
     61 	case $PATTERN in
     62 		/*)
     63 			XPATTERN="$PATTERN"
     64 			;;
     65 		'~'|'~/'*)
     66 			XPATTERN="$HOME$(echo "$PATTERN" | tail -c +2)"
     67 			;;
     68 		*)
     69 			XPATTERN="$PWD/$PATTERN"
     70 			;;
     71 	esac
     72 
     73 	# The first path condition rules out paths that start with "." unless
     74 	# they start with "..". That way, hidden paths should stay hidden, but
     75 	# non-normalised paths should still show up.
     76 	find "$(dirname "$XPATTERN")" \
     77 		-name '.*' -prune \
     78 		-o \( \
     79 			! -name '.*' \
     80 			-a -path "$(glob_quote "$XPATTERN")*" \
     81 			-print \
     82 		\) 2>/dev/null |
     83 		head -n "$FIND_FILE_LIMIT" |
     84 		sort |
     85 		sed "s|^$(dirname "$XPATTERN")/||"
     86 fi |
     87 	vis-menu -b |
     88 	sed "s|^$(basename "$PATTERN")$(echo "$PATTERN" | tail -c 2 | grep -F /)||" |
     89 	tr -d '\n'