cannot validate read -e entry when bound to TAB
Configuration Information [Automatically generated, do not change]: Machine: x86_64 OS: linux-gnu Compiler: gcc Compilation CFLAGS: -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wall uname output: Linux debvirt 6.0.0-2-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.0.5-1 (2022-10-28) x86_64 GNU/Linux Machine Type: x86_64-pc-linux-gnu Bash Version: 5.2 Patch Level: 2 Release Status: release Description: When read -e is bound to tabulation i.e. bind -x '"\C-i": "function"' it is not possible to validate the entry after the first iteration. It is possible to validate by pressing Ctrl-j, but that is not a viable solution. I tried to bind 'RETURN: "\C-j"' but that does not work. It is not a new behavior in 5.2, but since then I used to work around this issue with read -set .001 -d '' DISCARD before the actual read -e Alas, this does not work anymore with 5.2 (-e and -t combination triggers shell exit or, when used in a script, prevents further use of read -e). Is there a solution to this problem? The return of the previous behavior of -e and -t combination would be fine for me although I don't understand why I need this. Below is an example to reproduce the problem. Thanks. Repeat-By: #!/usr/bin/env bash _comp() { COMPREPLY=() local cur="${COMP_WORDS[COMP_CWORD]}" read -d '' -ra COMPREPLY < <(echo "$cur$RANDOM") return 0 } f_complete() { declare COMPLETE COMP_LINE IFS=$' \t\n' declare -a COMP_WORDS declare -i COMP_CWORD COMP_POINT COMP_LINE="${PROGNAME:-dummy} $READLINE_LINE" COMP_POINT=${#COMP_LINE} read -d '' -ra COMP_WORDS <<<"$COMP_LINE" [[ "${COMP_LINE: -1}" == [[:blank:]] ]] && COMP_WORDS+=( "" ) (( COMP_CWORD=${#COMP_WORDS[@]} - 1 )) _comp COMPLETE="${COMPREPLY[0]} " READLINE_LINE="${COMP_WORDS[*]:1:(( ${#COMP_WORDS[@]} - 2 ))} $COMPLETE" READLINE_LINE="${READLINE_LINE# }" READLINE_POINT="${#READLINE_LINE}" return 0 } set -o emacs bind -x '"\C-i": "f_complete"' while true; do ### 'read -e -t' used to solve the issue but not anymore in Bash 5.2 ### (at least 5.2.2(1)-release (x86_64-pc-linux-gnu)) #read -set .001 -d '' DISCARD read -e -p "entry> " ENTRY ### use TAB completion here sleep .2; echo "you typed $ENTRY" done
Re: compgen stops processing backslashes after any call to bind
On 16/12/2022 23:18, Chet Ramey wrote: Your arguments undergo word expansion, including double-quote processing, before compgen sees them. Thank you very much for your thorough explanation. I also take this opportunity to thank you for https://lists.gnu.org/archive/html/bug-bash/2022-11/msg00035.html and I thank Koichi too. I had seen, using set -x, that backslashes were given special treatment but, in my naive view, I didn't grasp that was a consequence of a larger problem. So I have a function that works now. Maybe someone will have a wiser solution. #!/usr/bin/env bash [[ "$(find /tmp/ -maxdepth 1 -type d -name "DirA")" ]] && exit 2 mkdir -p /tmp/Dir\\A/dirB/dir\\C/dirD/ touch /tmp/Dir\\A/dirB/dir\\C/dirD/fileA set -o emacs f_comp() { local COMP CPR="${1%\/*}" CPO="${1##*\/}" #echo 1>&2; set -x COMP="$(compgen -f "${CPR//\\/}${1:+/}${CPO//\\/}")" set +x CPR="${COMP%\/*}" CPO="${COMP##*\/}" printf '%s' "${CPR///\\}${1:+/}$CPO" } bind -X for DF in "/tmp/Dir" "/tmp/Dir\\A" "/tmp/Dir\\A/" "/tmp/Dir\\A/dir\\" \ "/tmp/Dir\\A/dirB" "/tmp/Dir\\A/dirB/" \ "/tmp/Dir\\A/dirB/dir\\" \ "/tmp/Dir\\A/dirB/dir\\C/dir" \ "/tmp/Dir\\A/dirB/dir\\C/dirD/file"; do printf '%s\n' "$(( ++COUNT )) $DF >>> $(f_comp "$DF")" done rm -rf /tmp/Dir\\A/ ### Output: 1 /tmp/Dir >>> /tmp/Dir\A 2 /tmp/Dir\A >>> /tmp/Dir\A 3 /tmp/Dir\A/ >>> /tmp/Dir\A/dir\\B 4 /tmp/Dir\A/dir\ >>> /tmp/Dir\A/dir\\B 5 /tmp/Dir\A/dir\\B >>> /tmp/Dir\A/dir\\B 6 /tmp/Dir\A/dir\\B/ >>> /tmp/Dir\A/dir\\B/dir\\\C 7 /tmp/Dir\A/dir\\B/dir\\\ >>> /tmp/Dir\A/dir\\B/dir\\\C 8 /tmp/Dir\A/dir\\B/dir\\\C/dir >>> /tmp/Dir\A/dir\\B/dir\\\C/dirD 9 /tmp/Dir\A/dir\\B/dir\\\C/dirD/file >>> /tmp/Dir\A/dir\\B/dir\\\C/dirD/fileA
Re: compgen stops processing backslashes after any call to bind
Well, it is said that directories sometimes harbor more than one item :) Fabien (of1) #!/usr/bin/env bash [[ -e "/tmp/Dir\\A" ]] && exit 2 mkdir -p /tmp/Dir\\A/dirB/ /tmp/Dir\\A/dir\\C/ touch /tmp/Dir\\A/fileA "/tmp/Dir\\A/file\\ B" f_comp() { local CP CPR="${1%\/*}" CPO="${1##*\/}" declare -a COMP readarray -t COMP \ < <(compgen -f "${CPR//\\/}${1:+/}${CPO//\\/}") for CP in "${COMP[@]}"; do CPR="${CP%\/*}" printf '%s\n' "${CPR///\\}${1:+/}${CP##*\/}" done } set -o emacs bind -X for DF in "/tmp/Dir\\A" "/tmp/Dir\\A/" "/tmp/Dir\\A/dir\\" \ "/tmp/Dir\\A/file\\"; do printf '%s\n' "$(( ++COUNT )) $DF >>>" "$(f_comp "$DF")" "" done rm -rf /tmp/Dir\\A/ ### Output: 1 /tmp/Dir\A >>> /tmp/Dir\A 2 /tmp/Dir\A/ >>> /tmp/Dir\A/file\ \\B /tmp/Dir\A/fileA /tmp/Dir\A/dir\\\C /tmp/Dir\A/dir\\B 3 /tmp/Dir\A/dir\ >>> /tmp/Dir\A/dir\\\C /tmp/Dir\A/dir\\B 4 /tmp/Dir\A/file\ >>> /tmp/Dir\A/file\ \\B /tmp/Dir\A/fileA
Re: Enable compgen even when programmable completions are not available?
On 27/06/2023 21:05, Kerin Millar wrote: It doesn't work at all for >=5.2. The reason for this is interesting and I may make a separate post about it. Prior to 5.2, it can easily be tricked into printing names that do not exist. $ VAR=$'\nNONEXISTENT=' ./declare-P | grep ^NONEXISTENT NONEXISTENT Thank you. I was just reading the discussion in Gentoo forum and realizing that I've been to quickly: it doesn't pass the FOO=$'\nBAR BAZ QUUX=' test. But what about this? (I also quickly tested with Bash 5.2.15). FOO=$'\nBAR BAZ QUUX=' VAR=$'\nNONEXISTENT=' declare-P() { local curVar declare -a curVars readarray -t curVars <<<"$1" curVars=( "${curVars[@]%%=*}" ) curVars=( "${curVars[@]##* }" ) for curVar in "${curVars[@]}"; do ### we can use [[ -v "$curVar" ]] at some point! [[ "${curVar//[a-zA-Z0-9_]}" || \ "${curVar:0:1}" == [0-9] || \ ! -v "$curVar" || \ ! "$curVar" =~ $2 ]] || printf '%s\n' "$curVar" done } declare-P "$(declare -p)" echo "##" declare-P "$(declare -p)" "QU|^NON|VAR"