From 37034a6549ca23f6d59deefae3d5f845c74683d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Paulo=20G=2E=20Garcia?= Date: Sun, 1 Aug 2021 15:22:01 -0300 Subject: [PATCH 1/3] complete-filename: allow shell expansions and escape "spaces". Enclose prefix within double quotes so that we can properly use environment variables. Force "tilda expansion" by replacind "~" with "$HOME". Escape occurrences of spaces in vis-open output. --- lua/plugins/complete-filename.lua | 8 ++-- vis-complete | 76 ++++++++++++++++++-------------------- 2 files changed, 41 insertions(+), 43 deletions(-) --- a/lua/plugins/complete-filename.lua +++ b/lua/plugins/complete-filename.lua @@ -15,7 +15,8 @@ vis:map(vis.modes.INSERT, "", -- Strip leading delimiters for some languages local _, j = string.find(prefix, "[[(<'\"]+") if j then prefix = prefix:sub(j + 1) end - local cmd = string.format("vis-complete --file '%s'", prefix:gsub("'", "'\\''")) + local cmd = string.format('vis-complete --file "%s"', + prefix:gsub("^~", "$HOME"):gsub("'", "'\\''")) local status, out, err = vis:pipe(file, { start = 0, finish = 0 }, cmd) if status ~= 0 or not out then if err then vis:info(err) end @@ -43,13 +44,14 @@ vis:map(vis.modes.INSERT, "", range.start = pos range.finish = pos end - local cmd = string.format("vis-open -- '%s'*", prefix:gsub("'", "'\\''")) + local cmd = string.format('vis-open -- "%s"*', + prefix:gsub("^~", "$HOME"):gsub("'", "'\\''")) local status, out, err = vis:pipe(file, { start = 0, finish = 0 }, cmd) if status ~= 0 or not out then if err then vis:info(err) end return end - out = out:gsub("\n$", "") + out = out:gsub("\n$", ""):gsub(" ", "\\ ") file:delete(range) file:insert(range.start, out) win.selection.pos = range.start + #out --- a/vis-complete +++ b/vis-complete @@ -1,65 +1,61 @@ #!/bin/sh set -e -basic_regex_quote() { printf "%s" "$1" | sed 's|[\\.*^$[]|\\&|g'; } -glob_quote () { printf "%s" "$1" | sed 's|[\\?*[]]|\\&|g'; } +basic_regex_quote() { printf "%s" "$1" | sed 's/[|\\.*^$[]/\\&/g'; } + +print_completion() { + sort -u \ + | vis-menu -b -i -l $VIS_MENU_LINES \ + | sed "s|^$1||" \ + | tr -d '\n' +} PATTERN="" -COMPLETE_WORD=0 +COMPLETE_MODE='-' # -) stdin; w) split stdin in words; f) find(1) filenames FIND_FILE_LIMIT=1000 +VIS_MENU_LINES=0 while [ $# -gt 0 ]; do case "$1" in -h|--help) - echo "usage: $(basename "$0") [-h] [--file|--word] [pattern]" + echo "usage: $(basename "$0") [-h] [-l lines] [--file|--word] [pattern]" exit 0; ;; --file) + COMPLETE_MODE='f' shift ;; --word) - COMPLETE_WORD=1 + COMPLETE_MODE='w' shift ;; + -l) + VIS_MENU_LINES=$2 + shift 2 + ;; *) PATTERN="$1" + QPATTERN=$(basic_regex_quote "$PATTERN") # Avoid problems with sed and grep. break ;; esac done -if [ $COMPLETE_WORD = 1 ]; then - tr -s '[:blank:]_' '\n' | - grep "^$(basic_regex_quote "$PATTERN")." | - sort -u -else - # Expand to absolute path because of the -path option below. - case $PATTERN in - /*) - XPATTERN=$PATTERN - ;; - '~'|'~/'*) - XPATTERN=$HOME$(echo $PATTERN | tail -c +2) - ;; - *) - XPATTERN=$PWD/$PATTERN - ;; - esac - - # The first path condition rules out paths that start with "." unless - # they start with "..". That way, hidden paths should stay hidden, but - # non-normalised paths should still show up. - find $(dirname "$XPATTERN") \ - -name '.*' -prune \ - -o \( \ - ! -name '.*' \ - -a -path "$(glob_quote "$XPATTERN")*" \ - -print \ - \) 2>/dev/null | - head -n $FIND_FILE_LIMIT | - sort | - sed "s|^$(dirname $XPATTERN)/||" -fi | - vis-menu -b | - sed "s|^$(basename $PATTERN)$(echo $PATTERN | tail -c 2 | fgrep /)||" | - tr -d '\n' +case $COMPLETE_MODE in + -) + grep "^$QPATTERN." | print_completion "$QPATTERN" + ;; + w) + tr -cs '[:alnum:]_' '\n' \ + | grep "^$PATTERN." \ + | print_completion "$PATTERN" + ;; + f) + find "$PATTERN"* \ + -name ".*" -prune \ + -o -print 2> /dev/null \ + | head -n $FIND_FILE_LIMIT \ + | sed "s|^$(dirname "$QPATTERN".)/||" \ + | print_completion "${QPATTERN##*/}" + ;; +esac