Troque o comportamento padrão do comando pelo comportamento do Cu

7

Muitos comandos do Emacs alteram seu comportamento quando chamados com um ou mais C-uprefixos. Em alguns casos, o comportamento padrão de um comando é menos útil para mim do que o comportamento que recebo quando o prefixo C-u. Ao mesmo tempo, não quero me livrar completamente do comportamento padrão.

Para dar um exemplo concreto, o quit-windowcomando (vinculado a qin help-mode) sai da janela atual e enterra o buffer exibido nela por padrão. Quando chamado C-u, mata o buffer. Eu gostaria que o comando matasse o buffer por padrão e o enterrasse quando chamado com um C-uprefixo.

P: Como posso dizer ao Emacs para que um comando se comporte como se fosse chamado com um C-u prefixo por padrão enquanto move o comportamento padrão para o C-u prefixo ?

Eu sei que poderia resolver isso redefinindo o comando original ou agrupando-o em um comando personalizado que passa o prefixo args de acordo com minhas preferências. Mas prefiro fazer algo assim:

(swap-args 'quit-window)
itsjeyd
fonte

Respostas:

4

Algo assim:

(defun swap-args (fun)
  (if (not (equal (interactive-form fun)
                  '(interactive "P")))
      (error "Unexpected")
    (advice-add
     fun
     :around
     (lambda (x &rest args)
       "Swap the meaning the universal prefix argument"
       (if (called-interactively-p 'any)
           (apply x (cons (not (car args)) (cdr args)))
         (apply x args))))))

Obviamente, só funciona para (interactive "P"). Para outros tipos interactive, pode não fazer sentido negar o primeiro argumento.

abo-abo
fonte
11
Poderia ser um pouco mais simples usando em :filter-argsvez de :around, eu acho.
npostavs 26/05
Obrigado, swap-argsfunciona porque torna o C-ucomportamento o padrão ao aplicá-lo a um comando. No entanto, quando chamo o comando com C-u, não recebo o comportamento original. Talvez called-interactively-pseja a culpa? Meu entendimento é que, com um argumento arg 'any, essa função retornará apenas nilse o comando que contém for chamado do Lisp, portanto, ao invocar o comando recomendado por meio de uma ligação de chave, o ramo else não poderá ser alcançado.
Itsjeyd 27/05
'anyfoi bom, eu usei em funcallvez de applypor engano.
abo-abo 27/05
2
Você deve adicionar algo à doutrina também, caso contrário, isso deve ser confuso.
Gilles 'SO- stop be evil'
11
Irritantemente, algumas funções (por exemplo org-insert-subheading) verificam literalmente o argumento universal bruto (aparentemente (4)) em vez de uma verificação convincente da verdade.
Olajorgenb
1

Outro método baseado no fato de que uma interactive-formpropriedade no plist da função substitui o formulário especificado no código: ( ref )

(put 'org-insert-subheading
     'interactive-form
     '(interactive (progn (if current-prefix-arg
                              '(nil)
                            '((4))))))

Usando (interactive-form 'function)para obter as especificações atuais, também é possível lidar com especificações mais complexas.

Eu acho que a melhor solução (se possível) é envolver a função com (let ((prefix-arg (not current-prefix-arg)))embora

olejorgenb
fonte
0

Não é tão fácil quanto se pensava. No entanto, como é trivial ter o comando swapped:

(defun my-quit-window-args-swapped (&optional bury window)
"Adapted docstring blah, blah "
  (interactive "P")
  (quit-restore-window window (if bury 'bury 'kill)))
Andreas Röhler
fonte
Obrigado, mas como mencionei na minha pergunta, estou procurando uma solução genérica que possa ser aplicada a diferentes comandos, não um wrapper específico para o quit-windowcomando.
Itsjeyd 27/05
@itsjeyd Não há restrição finita do WRT para resultar e emprego de um argumento. Não é sobre "(swap-args ..." mas sobre o uso e significado de args - que é livre, finalmente.
Andreas Röhler
11
Eu deveria ter escolhido minhas palavras com mais cuidado. Não pretendi sugerir que sua solução não possa ser adaptada para funcionar com outros comandos. É uma solução perfeitamente boa para a troca de C-ucomportamento e padrão , e tenho certeza de que outras pessoas que encontrarem sua postagem serão ajudadas por ela! Pessoalmente, não vou usá-lo porque tenho vários comandos cujo comportamento quero alterar e gostaria de evitar a necessidade de definir vários wrappers.
itsjeyd 27/05
@itsjeyd AFAIU, a única coisa definida aqui é a maneira como o corpo recebe o Cu. Não existe um padrão em que ponto do corpo o argumento é usado; também existem muitas maneiras de usá-lo - em um sentido booleano aqui. Claro, você pode empregar algum tipo de IA para cobrir e lidar com todas essas possibilidades. :)
Andreas Röhler