P: como faço yasnippet
para expandir corretamente uma sequência de texto (reconhecendo campos de trecho) do código elisp?
Um snippet muito simples é apenas uma sequência de caracteres com alguns caracteres de controle entrelaçados. Também podemos usar formulários elisp para criar trechos mais ricos, mas não está claro para mim como expandi-los adequadamente.
Aqui está um exemplo simples que captura o problema. Estou criando um org-mode
snippet para inserir um esqueleto de link, que parece [[source][description]]
. O seguinte snippet simples produz o comportamento desejado de "iniciar no campo de origem e terminar no campo de descrição":
[[$1][$0]]
Podemos misturar o código elisp em trechos (envoltos em `s). Eu teria pensado que o seguinte produziria exatamente o mesmo comportamento da versão mais simples, porque o if
será simplesmente avaliado [[$1][$0]]
como uma string:
`(if t "[[$1][$0]]")`
No entanto, não o faz. Em vez disso, ele age como se os campos $0
e $1
não fossem campos, finalize o trecho e os pontos aponte após o final ]
. Então: como obter o comportamento desejado quando um formulário elisp é avaliado como uma sequência de texto com yasnippet
campos incorporados nessa sequência?
EDIT: conforme solicitado, aqui está o caso de uso específico que inspirou a pergunta. Se a área de transferência do X contiver um link de URL, eu gostaria que ela preenchesse o campo de origem no link organizacional ([[ fonte ] [descrição]]]) e me deixe no campo de destino. Ele usa uma função auxiliar ( dan-xclipboard-link-p
) que retorna o URL, se existir, ou então nil
. Parece-me que eu deveria ser capaz de fazer algo assim:
`(let ((link (dan-xclipboard-link-p)))
(if link
(concat "[[" link "][$0]]")
"[[$1][$0]]"))`
De fato, com uma versão anterior do yasnippet, uma versão desse código funcionava como eu pretendia.
EDIT 2: Curiosamente, esse trecho funciona quando há um link na área de transferência do X, mas falha quando não (ou seja, ele não reconhece $1
como um campo:
[[`(or (dan-xclipboard-link-p) "$1")`][$0]]
(if t (yas-insert-snippet))
? Você pode dar uma condicional mais realista para que possamos entender o caso de uso real? Este pode ser um problema XY com soluções mais elegantes.yas-insert-snippet
se aplica aqui. De qualquer forma, um caso de uso real (que costumava funcionar) está agora em questão.Respostas:
SOLUÇÃO CURTA
Se você não se importar com um
TAB
pressionamento de tecla adicional , definir seu snippet como abaixo deve funcionar.O lisp incorporado retorna o URL da área de transferência, se existir, e o define como o texto padrão no campo
$1
. Você pode digitar no link para alterá-lo ou apenasTAB (yas-next-field)
para mover o ponto para$0
.SOLUÇÃO EM DESTAQUE MAIS COMPLETA
Tive a ideia com base no comentário de @ IqbalAnsari depois de escrever a solução mais curta. Você pode usar o predicado de condição para escolher qual snippet expandir. Por exemplo, defina dois trechos com o mesmo gatilho
SNIPPET 1
SNIPPET 2
Ambos os trechos têm o mesmo gatilho, mas têm predicados invertidos denotados pelo
condition:
. Como tal, apenas um dos trechos será expandido, dependendo do valor retornado por(dan-xclipboard-link-p)
. Dessa forma, você pode posicionar o ponto$0
diretamente.Para responder à pergunta geral, não, não é possível que o yasnippet reconheça campos no elisp, pois analisa blocos elisp incorporados separadamente, sem qualquer preocupação com a sintaxe normal do modelo. Não tenho certeza de como as versões anteriores funcionaram.
fonte