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

Re: typeset -p output gives shows variables which can't be read back in



On Feb 27,  6:44am, Rocky Bernstein wrote:
} 
} A little bit of context of why I am doing this. Recently in the zsh
} debugger I've added the ability to go into a nested zsh, and often one
} wants the existing environment of the debugged program preserved in
} this nested zsh.

You're kind of doomed here from the start.  If the debugger is inside
a shell function, for example, you're never going to get scoping back.
 
} I would like to save to a file shell variables so that I can run a
} nested zsh and then read these back in.  It is becoming a bit of a
} challenge because this in the output:
} 
} typeset -i10 -r !=0

Hm, I'm a bit surprised the '!' isn't quoted there; but the real issue
is that you get "not an identifier" or the like for a number of those,
and "can't change type" for ones that come from zsh/parameter, plus a
few "read-only variable" complaints.

} typeset -ar '*'

Hmm, strange.  That one does NOT give "not an identifier" ...

} *=()

... but that of course bombs with a globbing error.

} Failing a better solution, I think what I'll have to do is store IFS=''
} typeset -p into an array and check each item of the array.

The zsh/parameter module $parameters hash already tells you nearly all
you need to know.  Something like this:

    () {
      local param type
      for param type in "${(kv@)parameters}"
      do
        case "$type" in
        (*local*) continue;;   # Skip loop variables
        (*export*) continue;;  # No need to dump/restore if exported?
        (*special*) continue;; # Maintained by the shell
        (*readonly*) continue;;
        (*) typeset -p "$param";;
        esac
      done
    }

You can avoid zsh/parameter by parsing the output of "typeset +m +":

    () {
      local param type description
      typeset +m + | while read -A description
      do
        param="${description[-1]}"
        description[-1]=()
        if (( ${#description} ))
        then type="${description[*]}"
        else type=scalar
        fi
        case "$type" in
        (*local*) continue;;   # Skip loop variables
        (*export*) continue;;  # No need to dump/restore if exported?
        (*readonly*) continue;;
        (*) typeset -p "$param";;
        esac
      done
    }

However, that doesn't let you catch "special" parameters, though you
can still filter the readonly subset.

Note both of these techniques still miss things like:

    typeset -T foo FOO

I.e., there's no way to discover by examination that an array and scalar
have been tied together.

} But then we come to the typeset -ar '*' line which I guess flows onto the
} next line.

Not exactly "flows", but for arrays and associative arrays (hashes) the 
value can't be supplied in the typeset command, so an assignment line is
needed.

Also you may have to be careful with the order of assignments when you
read the file back in.  Some assignments to special variables (like to
the "options" hash) might change shell behavior in unexpected ways.



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