Combine duas funções interativas
Por exemplo, desejo classificar um arquivo e remover as linhas duplicadas. Eu corro M-x sortseguido por M-x delete-duplicate-lines. Eu queria combiná-los em uma única função interativa. Aqui está uma tentativa de resolver isso.
(defun sort-and-dedup ()
""
(interactive)
(sort)
(delete-duplicate-lines)
)
Isso dá um erro dizendo que as funções subjacentes não têm um número suficiente de argumentos. Eu meio que entendo por que esse é o caso (o argumento interativo versus não interativo, entre alguns outros), mas não sei o que fazer exatamente. Você pode me dizer como corrigir isso?
Editar 1:
O código acima está errado de várias maneiras. Veja a resposta aceita para obter informações. E obrigado pela ajuda.
Editar 2:
Isso é o que eu pretendia fazer.
(defun sort-and-dedup-region (beg end)
(interactive "r")
(sort-lines nil beg end)
(delete-duplicate-lines beg end nil t))
(defun sort-and-dedup ()
(interactive)
(sort-and-dedup-region
(point-min)
(point-max)))
Respostas
[Acredito que você quis dizer sort-lines, não sort- essa é a única maneira pela qual a pergunta faz sentido, então vou supor.]
Ambos sort-linese delete-duplicate-linesoperam na região selecionada . Você deve selecionar uma região antes de chamá-los, caso contrário, eles reclamarão que não há região. Portanto, você terá que fazer a mesma coisa em sua função: assumir que você recebeu uma região e reclamar se não houver nenhuma.
Uma região é especificada por duas posições no buffer, convencionalmente denominadas BEGe `END. Portanto, sua função será semelhante a esta:
(defun sort-and-dedup (beg end)
(interactive <mumble>)
(sort-lines nil beg end)
(delete-duplicate-lines beg end))
O primeiro argumento para classificar as linhas informa se deve classificar na ordem inversa.
Ao chamar a função interativamente, você especifica uma região definindo uma marca em uma extremidade e, em seguida, movendo o ponto para a outra extremidade (ou iniciando em uma extremidade e arrastando com o mouse até a outra extremidade). Então, como você comunica essas posições para a função? Ao fornecer um argumento para interactive: se você olhar para a string doc (com C-h f interactive RET), você descobrirá que ré o que você precisa para especificar uma região - o Emacs irá providenciar para traduzir a região que você escolheu (independentemente de como você escolheu) em um par de posições (BEG e END) que serão passadas para sua função.
Portanto, a função é semelhante a esta:
(defun sort-and-dedup (beg end)
(interactive "r")
(sort-lines nil beg end)
(delete-duplicate-lines beg end))
Como alternativa, como @Dan sugere, você pode usar call-interactivelye deixar cada função descobrir o que precisa. Mas você ainda terá que especificar uma região com antecedência:
(defun sort-and-dedup ()
(interactive)
(call-interactively #'sort-lines)
(call-interactively #'delete-duplicate-lines))
EDITAR: incorporando a sugestão de @phil (e agora vejo que você realmente implementou isso e adicionou à sua pergunta), você pode escrever uma função que chama (a primeira definição de) sort-and-dedupcom os argumentos necessários para operar em todo o buffer:
(defun sort-and-dedup-whole-buffer()
(interactive)
(sort-and-dedup (point-min) (point-max)))
Você pode vinculá-lo a uma sequência de teclas se for fazer isso com frequência:
(define-key global-map (kbd "M-S-<f10>" #'sort-and-dedup-whole-buffer)
embora eu pessoalmente não fizesse isso: as sequências-chave são uma mercadoria rara, então eu tentaria usá-las M-x sort-and-dedup-whole-buffer RETpor um tempo; se isso se tornar um incômodo, eu o vincularia a uma sequência chave.
Eu também revisito todos os meus principais defs a cada dois anos e recupero aqueles que não uso mais. Eu os mantenho em seus próprios arquivos, carregados explicitamente pelo meu arquivo init, para que possa localizá-los e revisá-los facilmente.