Exclua parte da sequência Isearch que não corresponde ou o último caractere se a correspondência completa

11

Eu tenho o seguinte

(defun isearch-del-fail-or-char ()
  "Delete failed isearch text, or if there is none, a single character."
  (interactive)
  (if (isearch-fail-pos)
      (delete-region (isearch-fail-pos) (point))
    (isearch-del-char)))

(define-key isearch-mode-map (kbd "DEL") 'isearch-del-fail-or-char)

O objetivo do código é fazer deletecom que o isearch exclua toda a cadeia com falha (ou, se não houver uma cadeia com falha, apenas um caractere).

No entanto, a delete-regionexclusão de texto do buffer isearchestá sendo pesquisada, não o buffer isearch em si.

Qual é a maneira correta de fazer isso? A crítica sobre o resto do meu estilo emacs lisp também é bem-vinda :)

asmeurer
fonte

Respostas:

12

Ah sim. O Isearch lê as chaves que você digita, as procura isearch-mode-mape as invoca no buffer atual .

ISearch faz não , apesar das aparências, use o minibuffer. Ele usa a área de eco. Ou seja, o que você vê é realmente mensagens de saída , incluindo ecos dos caracteres digitados.

Isso deve fazer o que você pede:

(defun mydelete ()
  "Delete the failed portion of the search string, or the last char if successful."
  (interactive)
  (with-isearch-suspended
      (setq isearch-new-string
            (substring
             isearch-string 0 (or (isearch-fail-pos) (1- (length isearch-string))))
            isearch-new-message
            (mapconcat 'isearch-text-char-description isearch-new-string ""))))

(define-key isearch-mode-map (kbd "DEL") 'mydelete)

(BTW, sua pergunta diz o deletepersonagem, mas você escreveu DEL, que é o caractere de backspace.)


Como @Malabarba aponta em um comentário, quando você define a nova sequência de pesquisa como ""(sequência vazia), with-isearch-suspendedretoma pesquisando a última sequência de pesquisa, em vez de começar com uma sequência de pesquisa vazia.

Este é um " recurso " de with-isearch-suspended, em geral. Mas porque às vezes você pode realmente deseja esvaziar a cadeia de pesquisa para a retomada, na versão de with-isearch-suspendedem isearch + .El variável eu adicionei isearchp-if-empty-prefer-resuming-with-last, para controlar isso. Se você vincular isso nile definir isearch-new-stringcomo "", a pesquisa será retomada com uma sequência de pesquisa vazia.

Portanto, com o Isearch +, você pode fazer o que quiser com esta definição:

(defun mydelete ()
  "Delete the failed portion of the search string, or the last char if successful."
  (interactive)
  (let ((isearchp-if-empty-prefer-resuming-with-last  nil))
    (with-isearch-suspended
        (setq isearch-new-string
              (substring
               isearch-string 0 (or (isearch-fail-pos) (1- (length isearch-string))))
              isearch-new-message
              (mapconcat 'isearch-text-char-description isearch-new-string "")))))

Percebo também agora que Emacs 24,4 introduziu uma regressão, que eu arquivado Emacs bug # 20466 para, o que significa que a ligação DELem isearch-mode-mapnão é suficiente. Eles adicionaram uma ligação separada para <backspace>, além de uma para DEL. Isso significa que <backspace>não é mais traduzido DELpara o Isearch (mas ainda assim é traduzido para o Emacs em geral).

Então, se você quer que a tecla Backspace para fazer o que você pediu em Emacs 24.4 ou mais tarde, então você não pode simplesmente ligar DELpara mydelete. Você precisa ligar <backspace>para mydelete. Dumb, AFAICT, mais sobre n'arrete pas le progres ...


Adicionei um comando semelhante ao Isearch + e o vinculeiC-M-l (a mesma chave usada para remover uma incompatibilidade de conclusão no Icicles ).

Esteja ciente também de que, C-gno Isearch, também, quando houver uma incompatibilidade, você removerá o texto incompatível. (Mas C-gtambém tem efeito quando a pesquisa é bem-sucedida.)


Eu deveria ter mencionado que o Isearch + também teve um comportamento opcional ao longo de linhas semelhantes por um bom tempo. M-kdurante o Isearch, alterna entre três comportamentos, que são controlados pelo valor da opção isearchp-drop-mismatch:

  • replace-last- Sua entrada atual substitui o último texto incompatível. Você sempre pode ver sua última entrada, mesmo que seja uma incompatibilidade. E está disponível para edição usando M-e.

  • nil - Sua entrada atual é anexada, mesmo que a entrada anterior tenha uma parte incompatível.

  • qualquer outra coisa - Sua entrada atual será ignorada (removida) se causar uma incompatibilidade. A cadeia de pesquisa sempre tem correspondências bem-sucedidas.

Desenhou
fonte
BTW, pensei em adicionar um comando semelhante ao Isearch + desde que adicionei o destaque da parte com falha (anos atrás, antes de adicioná-lo ao GNU Emacs), mas nunca cheguei a ele. Eu fiz isso agora . (Eu não incluem a eliminação de um personagem, no entanto O comando eu adicionei é um não-op se não houver nenhuma parte falhou..)
de Drew
Estou no OS X. Eu quis dizer excluir para trás.
asmeurer
O comportamento isearch + replace-last parece muito bom. Existe alguma maneira de fazer com que ele não toque a campainha toda vez que a pesquisa falhar?
asmeurer
2
Fiz upload de uma nova versão de isearch+.el. (A) corrige a remoção automática de incompatibilidade, para que a envolvente funcione bem. E adiciona uma opção, isearchp-ring-bell-functionque você pode usar para suprimir a campainha durante a pesquisa.
Tirou
3
Malabarba, interessante. Eu atirei no bug e acabei com isso . Principalmente cultivada por carga isearch-del-chare pela resposta de Drew, mas parece funcionar como pretendido. A with-isearch-suspendedmacro foi a culpada.
jbm