Eliminar parte de la cadena Isearch que no coincide, o el último carácter si la coincidencia completa

11

Tengo lo siguiente

(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)

El propósito del código es hacer que deleteen isearch elimine toda la cadena fallida (o si no hay una cadena fallida, solo un solo carácter).

Sin embargo, delete-regionestá eliminando el texto del búfer que isearchestá buscando, no el búfer isearch en sí.

¿Cuál es la forma apropiada de hacer esto? La crítica sobre el resto de mi estilo emacs lisp también es bienvenida :)

asmeurer
fuente

Respuestas:

12

Ah, sí. Isearch lee las teclas que escribe, las busca isearch-mode-mape invoca en el búfer actual .

Isearch hace no , a pesar de las apariencias, utilice el minibúfer. Utiliza el área de eco. Es decir, lo que ve allí son mensajes de salida , incluidos los ecos de los caracteres que escribe.

Esto debería hacer lo que pides:

(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)

(Por cierto, su pregunta dice el deletecarácter, pero usted escribió DEL, que es el carácter de retroceso).


Como @Malabarba señala en un comentario, cuando establece la nueva cadena de búsqueda en ""(cadena vacía), se with-isearch-suspendedreanuda buscando la última cadena de búsqueda, en lugar de comenzar con una cadena de búsqueda vacía.

Esta es una " característica " de with-isearch-suspended, en general. Pero debido a que a veces es posible que desee vaciar la cadena de búsqueda para reanudarla, en la versión de with-isearch-suspendedin search + .el he agregado variable isearchp-if-empty-prefer-resuming-with-last, para controlar esto. Si se unen a que nily se establece isearch-new-stringa ""continuación, buscar hojas de vida con una cadena de búsqueda vacío.

Entonces, con Isearch + puedes hacer lo que quieras con esta definición:

(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 "")))))

Me he dado cuenta demasiado ahora que Emacs 24.4 introduce una regresión, que me he presentado Emacs el bug # 20466 para, lo que significa que la unión DELen isearch-mode-mapno es suficiente. Agregaron un enlace separado para <backspace>, además de uno para DEL. Eso significa que <backspace>ya no se traduce a DELIsearch (pero en general sí se traduce así a Emacs).

Así que si quieres la tecla de retroceso para hacer lo que le pida en Emacs 24.4 o posterior, entonces no se puede simplemente unirse DELa mydelete. Tienes que unirte <backspace>a mydelete. Dumb, AFAICT, mais on n'arrete pas le progres ...


He agregado un comando similar a Isearch + y lo he vinculado C-M-l(la misma clave utilizada para eliminar una falta de coincidencia de finalización en Icicles ).

Tenga en cuenta también que C-gen Isearch también, cuando hay una falta de coincidencia, eliminará el texto no coincidente. (Pero C-gtambién tiene efecto cuando la búsqueda es exitosa).


Debería haber mencionado que Isearch + también ha tenido un comportamiento opcional en líneas similares durante bastante tiempo. M-kdurante Isearch alterna entre 3 comportamientos, que están controlados por el valor de la opción isearchp-drop-mismatch:

  • replace-last- Su entrada actual reemplaza el último texto no coincidente. Siempre puede ver su última entrada, incluso si no coincide. Y está disponible para editar con M-e.

  • nil - Su entrada actual se agrega, incluso si la entrada anterior tiene una parte no coincidente.

  • cualquier otra cosa: su entrada actual se ignora (se elimina) si causa una falta de coincidencia. La cadena de búsqueda siempre tiene coincidencias exitosas.

Dibujó
fuente
Por cierto, he pensado en agregar un comando similar a Isearch + desde que agregué el resaltado de la parte fallida (hace años, antes de agregarlo a GNU Emacs), pero nunca lo logré. Lo he hecho ahora . (Sin embargo, no incluí la eliminación de un personaje. El comando que agregué es no operativo si no hay una porción fallida).
Drew
Estoy en OS X. Me refería a borrar hacia atrás.
Asmeurer
El comportamiento isearch + replace-last se ve bastante bien. Sin embargo, ¿hay alguna manera de hacer que no suene la campana cada vez que falla la búsqueda?
asmeurer
2
Subí una nueva versión de isearch+.el. (A) corrige la eliminación automática de desajustes para que la envoltura funcione bien. Y agrega una opción, isearchp-ring-bell-functionque puede usar para suprimir la campana durante la búsqueda.
Drew
3
Malabarba, interesante. Le di una oportunidad al bicho y terminé con esto . En su mayoría, la carga se cultivó isearch-del-chary la respuesta de Drew, pero parece funcionar según lo previsto. La with-isearch-suspendedmacro fue la culpable.
jbm