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?