Re: [PATCH 6/8] git-prompt: add fallback for shells without $'...'

avih
2024-07-25T11:38:14Z

On Wednesday, July 24, 2024 at 05:08:54 AM GMT+3, avih <avihpit@yahoo.com> wrote:
> On Tuesday, July 23, 2024 at 11:25:29 PM GMT+3, Junio C Hamano <gitster@pobox.com> wrote:
> > >
> > > +__git_SOH=$'\1' __git_STX=$'\2' __git_ESC=$'\33'
> > > +__git_LF=$'\n' __git_CRLF=$'\r\n'
> > > +
> > > +if [ $'\101' != A ]; then  # fallback for shells without $'...'
> > > +  __git_CRLF=$(printf "\r\n\1\2\33")  # CR LF SOH STX ESC
> > > +  __git_ESC=${__git_CRLF#????}; __git_CRLF=${__git_CRLF%?}
> > > +  __git_STX=${__git_CRLF#???};  __git_CRLF=${__git_CRLF%?}
> > > +  __git_SOH=${__git_CRLF#??};  __git_CRLF=${__git_CRLF%?}
> > > +  __git_LF=${__git_CRLF#?}
> > > +fi
>
> > ... I would prefer to see it done without any "fallback".
> > Just forbid use of $'\octal' notation in the coding
> > guidelines document, and implement just one variant.
>
> ... off the top of my head I wouldn't know how this variant
> should look like. This one printf and splitting it later is a bit
> meh to be used in every script which needs control literals, but
> I also don't have anything cleaner off the top of my head.

I think I misinterpreted the scope of "variant". I thought it meant,
across scripts which need to use $'...', but now I realize it meant
between using $'...' and using the fallback in this patch.

So mainly as a general solution, but also applicable to this patch,
below is my best generalized solution so far, so that scripts don't
have to reinvent the wheel with this "string strip dance" above,
but I'm not too happy with it, mainly due to the gotcha that single
quotes in the value break the world (escape the "eval").

So unless others prefer this solution or have other ideas, I think
it's best to keep the existing "strip dance" which the patch already
has, but make it the only variant instead of being a fallback.

Generalized solution (without namespace-ification):

# assign_as_fmt NAME=FMT ...  -->  NAME=$(printf FMT) ...
# - works also if the output ends in newline
# - NAME must be a valid var name
# - FMT _must_ not include/output single quotes (escapes eval)
# - best used like $'..':  x=$'\r\n'  ->  assign_as_fmt x='\r\n'
#   (which also avoids accidental single quotes, but not '\047')
assign_as_fmt () {
# accumulate " NAME='FMT'" from each "NAME=FMT"
fmt=  # ignore non-locality for now
while [ "${1+x}" ]; do
fmt="$fmt ${1%%=*}='${1#*=}'"
shift
done
eval "$(printf "$fmt")"  # FMTs become values, eval'ed
}

assign_as_fmt \
__git_SOH='\1' __git_STX='\2' __git_ESC='\33' \
__git_LF='\n' __git_CRLF='\r\n'