Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: [BUG] Can't mark unset variables as read-only



On Wed, Apr 29, 2015 at 12:57 PM, Mikael Magnusson <mikachu@xxxxxxxxx> wrote:
> On Wed, Apr 29, 2015 at 12:36 PM, Peter Stephenson
> <p.stephenson@xxxxxxxxxxx> wrote:
>> On Wed, 29 Apr 2015 08:35:43 +0200
>> Martijn Dekker <martijn@xxxxxxxx> wrote:
>>> Unlike other shells, zsh can't mark an unset variable as read-only.
>>
>> Yes, the standard does indeed require that ability.  As you can imagine,
>> something like this that completely breaks the normal programming model
>> of variables (a variable can't have state if it's unset because it
>> doesn't exist) is a nightmare to implement; however, it can at least be
>> limited to the POSIXBUILTINS option and maybe the cases using that are
>> simple enough that it mostly works.  I'm sure there are any number of
>> strange edge cases, though.
>>
>> The output of "readonly -p" is still broken (doesn't show the unset
>> variables in a fashion that can be used for restoring the current state)
>> but it was anyway:
>>
>>   typeset -ar '*'
>>   *=()
>>
>> Er, no, I don't think that's going to work.
>>
>> So that can be fixed separately.
>
> I wanted the opposite thing the other day, sort of. I have a ZLE
> widget that looks at $WIDGET, and I wanted to reuse it by calling it
> from another widget, setting WIDGET to another value first. However,
> ZLE makes $WIDGET readonly special, and I couldn't find any
> combination of flags that let me make a non-readonly local WIDGET. Is
> that possible?
>
> % zle -N h; h() { local -h WIDGET; WIDGET=hi; echo $WIDGET }; bindkey '^[h' h
> % <press alt-h>
> h: read-only variable: WIDGET
> % zle -N h; h() { local +r -h WIDGET; WIDGET=hi; echo $WIDGET }; bindkey '^[h' h
> % <press alt-h>
> h:local: WIDGET: can't change type of a special parameter
> % zle -N h; h() { local WIDGET; WIDGET=hi; echo $WIDGET }; bindkey '^[h' h
> % <press alt-h>WIDGET=h
>
> h: read-only variable: WIDGET
>
> compared to
> % () { readonly foo=3; () { local foo=5; echo $foo }; echo $foo }
> 5
> 3

Even when you think about something for a couple of days, you don't
realize what the answer is until after you send the question to a
public forum.

ZLE makes the scope of the WIDGET parameter start inside the widget
function already (which is confusing), so it is already local. The
answer is to start another parameter scope first,
% zle -N h; h() { () { local -h WIDGET; WIDGET=hi; echo $WIDGET } };
bindkey '^[h' h
% <press alt-h>hi

-- 
Mikael Magnusson



Messages sorted by: Reverse Date, Date, Thread, Author