cannot validate read -e entry when bound to TAB

2022-11-10 Thread of1

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

2022-12-17 Thread of1

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

2022-12-19 Thread of1

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?

2023-06-27 Thread of1

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"