Sintaxe de Expansão Zsh

1

Eu tenho andado por aí com minha configuração zsh e estou confuso em alguns pontos com a sintaxe de expansão zsh. Muito disso é baseado em coisas que encontrei nos seguintes recursos:

Configuração

Minha configuração atual do zsh é assim:

~/.config/zsh/rcsentry
~/.zshenv               symlink -> ~/.config/zsh/rcsentry
~/.config/zsh/.zshenv   symlink -> ~/.config/zsh/rcsentry
~/.config/zsh/.zshrc    symlink -> ~/.config/zsh/rcsentry
~/.config/zsh/.zlogin   symlink -> ~/.config/zsh/rcsentry
~/.config/zsh/.zprofile symlink -> ~/.config/zsh/rcsentry

Meu rcsentry está atualmente reduzido a um estado mínimo, enquanto eu tento entender exatamente como isso funciona. Atualmente, contém:

if [[ -o rcs ]]; then

    rcs_fn="${(%):-%1N}"
    rcs_fp="${(%):-%N}"

    echo "rcs_fn: $rcs_fn"
    echo "rcs_fp: $rcs_fp"

    if [[ "$rcs_fn" == ".zshenv" ]]; then

        echo "initializing XDG environment variables ..."
        export XDG_CACHE_HOME="${XDG_CACHE_HOME:=$HOME/.cache}"
        export XDG_CONFIG_HOME="${XDG_CONFIG:=$HOME/.config}"
        export XDG_DATA_HOME="${XDG_DATA_HOME:=$HOME/.local/share}"

        echo "initializing ZSH environment variables ..."
        export ZDOTDIR="${ZDOTDIR:=$XDG_CONFIG_HOME/zsh}"
    fi

    unset rcs_fn
    unset rcs_fp

fi

Ao executar um novo shell, recebo a saída esperada:

rcs_fn: .zshenv
rcs_fp: /Users/me/.zshenv
initializing XDG environment variables ...
initializing ZSH environment variables ...
rcs_fn: .zshrc
rcs_fp: /Users/me/.config/zsh/.zshrc
rcs_fn: .zlogin
rcs_fp: /Users/me/.config/zsh/.zlogin

Documentação & Interpretação

Eu tenho algumas coisas sobre as quais estou confuso, mas agora estou tentando limitá-lo a entender explicitamente o seguinte:

Estou começando pela seguinte sintaxe:

rcs_fn="${(%):-%1N}"

Inicialmente, não entendi o que isso significava. Mesmo tentando referenciar os documentos para descobrir isso é um desafio. Eu sei o que isso faz - mas estou tentando descobrir como entender a sintaxe. Então, a partir dos documentos, encontrei o seguinte:

If the opening brace is directly followed by an opening parenthesis, the string
up to the matching closing parenthesis will be taken as a list of flags.

-- 'man zshexpn' -> PARAMETER EXPANSION -> Parameter Expansion Flags

Acredito que isso indica que (%) é uma lista de sinalizadores sendo usados em uma instrução de expansão de paremeter.

%   Expand all % escapes in the resulting words in the same way as in prompts
(see EXPANSION OF PROMPT SEQUENCES in zshmisc(1)). If this flag is given twice,
full prompt  expansion is done on the resulting words, depending on the setting
of the PROMPT_PERCENT, PROMPT_SUBST and PROMPT_BANG options.

-- 'man zshexpn' -> PARAMETER EXPANSION -> Parameter Expansion Flags

Acredito que isso indica que (%) é, na verdade, um sinalizador de expansão de parâmetro, dizendo ao zsh que toda a instrução deve ter todos os sinais% expandidos como normalmente ocorre em uma string de prompt.

%N    The name of the script, sourced file, or shell function that zsh is
currently executing, whichever was started most recently.  If there is none,
this is equivalent to the parameter $0.  An  integer  may  follow the  '%' 
to  specify  a  number of trailing path components to show; zero means the
full path.  A negative integer specifies leading components.

-- 'man zshmisc' -> SIMPLE PROMPT ESCAPES

Dadas as suposições anteriores, acredito que isso indica que %1N é uma expansão imediata, que se expande para o nome do arquivo que contém o código atualmente sendo executado por zsh.

${name:-word}
    If name is set, or in the second form is non-null, then substitute its value;
    otherwise substitute word. In the second form name may be omitted, in which
    case word is always substituted.

-- 'man zshexpn' -> PARAMETER EXPANSION

Acredito que isso possa indicar que a sintaxe geral da instrução é uma substituição de palavras. Se esse fosse o caso, acredito que o valor do nome está vazio (a única coisa antes de : seria os sinalizadores de expansão) e, portanto, a segunda parte %1N é inserida automaticamente. Isso parece muito estranho para mim, como se eu estivesse interpretando a sintaxe completamente errada de alguma forma.

7. Modifiers
    Any modifiers, as specified by a trailing '#', '%', '/' (possibly doubled) or
    by a set of modifiers of the form ':...'  (see the section 'Modifiers' in the
    section 'History Expansion'), are applied to the words of the value at this
    level.

-- 'man zshexpn' -> PARAMETER EXPANSION -> Parameter Expansion Flags -> Rules

After the optional word designator, you can add a sequence of one or more of the
following modifiers, each pre ceded by a ':'.  These modifiers also work on the
result of filename generation and parameter expansion, except where noted.

-- 'man zshexpn' -> HISTORY EXPANSION -> Modifiers

Eu realmente não tenho certeza de como interpretar isso, ou se é relevante. Parece que pode indicar que : indica que o (@) anterior é um modificador de palavra e que o -%1N é uma sintaxe de geração de nome de arquivo (não faz sentido para mim) ou uma sintaxe de expansão de parâmetro (mas novamente não faz sentido, não vejo% N listado na seção de expansão de parâmetro, apenas na seção de expansão de prompt).

Resumo

Com base no que li nos documentos, acho que se divide da seguinte forma:

:-     indicates a word expansion, with word section empty and substitution '%1N'
(%)    parameter expansion flag, indicating the expression should be expanded as
       if it were in prompt expansion
%1N    a prompt escape, which expands to the name of the file
${..}  explicit parameter expansion, required for parameter expansion flag

Teste

Brincando com isso, acho que descobri a sintaxe. Meu arquivo rcsentry atualizado contém o seguinte:

if [[ -o rcs ]]; then

    # The name of the file containing currently code that is currently executing.
    rcs_fn="${(%):-%1N}"

    # The path of the file containing currently code that is currently executing.
    rcs_fp="${(%):-%N}"

    # The resolved path of the file containing currently code that is currently
    executing.
    rcs_x1="${${(%):-%N}:A}"

    # The resolved path of the parent directory of the file containing currently
    # code that is currently executing.
    rcs_x2="${${${(%):-%N}:A}:h}"


    if [[ "$rcs_fn" == ".zshenv" ]]; then

        # echo "initializing XDG environment variables ..."
        export XDG_CACHE_HOME="${XDG_CACHE_HOME:=$HOME/.cache}"
        export XDG_CONFIG_HOME="${XDG_CONFIG:=$HOME/.config}"
        export XDG_DATA_HOME="${XDG_DATA_HOME:=$HOME/.local/share}"

        # echo "initializing ZSH environment variables ..."
        export ZDOTDIR="${ZDOTDIR:=$XDG_CONFIG_HOME/zsh}"
    fi

    echo "rcs_fn: $rcs_fn"
    echo "rcs_fp: $rcs_fp"
    echo "rcs_x1: $rcs_x1"
    echo "rcs_x2: $rcs_x2"

    unset rcs_fn
    unset rcs_fp

fi

A saída é a esperada:

rcs_fn: .zshenv
rcs_fp: /Users/me/.zshenv
rcs_x1: /Users/me/.config/zsh/rcsentry
rcs_x2: /Users/me/.config/zsh
rcs_fn: .zshrc
rcs_fp: /Users/me/.config/zsh/.zshrc
rcs_x1: /Users/me/.config/zsh/rcsentry
rcs_x2: /Users/me/.config/zsh
rcs_fn: .zlogin
rcs_fp: /Users/me/.config/zsh/.zlogin
rcs_x1: /Users/me/.config/zsh/rcsentry
rcs_x2: /Users/me/.config/zsh

Então, com base nisso tudo, quão errado eu estou?

    
por nfarrar 14.08.2017 / 23:37

1 resposta

2

Sim, sua interpretação está correta (a partir de sua longa pergunta).

Os sinalizadores de expansão de parâmetro aplicam-se a expansões de parâmetros. Quando você quer que ele seja aplicado a qualquer string arbitrária, você precisa armazenar essa string em uma variável como em:

var=%1N
filename=${(%)var}

Ou (como um hack) você pode usar a expansão do parâmetro ${var:-string} e deixar a parte var vazia: ${(%):-%1N} . Isso é um truque comum (veja 1 2 3 4 5 6 7 8 9 10 11 12 13 aqui, por exemplo), embora isso represente um código bastante ilegível. Como alternativa, você pode usar a sintaxe ${param+string} e usar um parâmetro como $- ou $0 ou $# que é sempre definido ( ${(%)-+%1N} ). Isso não é nem mais curto nem mais legível.

Aqui, você também pode usar print -P %1N

    
por 16.08.2017 / 12:56

Tags