Elimina parte della stringa Isearch che non corrisponde o l'ultimo carattere se la corrispondenza completa


11

Ho il seguente

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

Lo scopo del codice è quello di far deleteeliminare in isearch l'intera stringa non riuscita (o se non esiste una stringa guasta solo un singolo carattere).

Tuttavia, l' delete-regioneliminazione del testo dal buffer isearchsta effettuando la ricerca, non il buffer isearch stesso.

Qual è il modo corretto per farlo? Anche la critica al resto del mio stile emacs lisp è benvenuta :)

Risposte:


12

Ah sì. Isearch legge le chiavi digitate, le cerca isearch-mode-mape le invoca nel buffer corrente .

Isearch fa non , a dispetto delle apparenze, utilizzare il minibuffer. Utilizza l'area dell'eco. Cioè, quello che vedi in realtà sono messaggi di output , inclusi echi dei caratteri digitati.

Questo dovrebbe fare quello che chiedi:

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

(A proposito, la tua domanda dice il deletepersonaggio, ma hai scritto DEL, che è il personaggio backspace.)


Come sottolinea @Malabarba in un commento, quando si imposta la nuova stringa di ricerca su ""(stringa vuota), si with-isearch-suspendedriprende cercando l'ultima stringa di ricerca, iniziando invece con una stringa di ricerca vuota.

Questa è una " caratteristica " di with-isearch-suspended, in generale. Ma poiché a volte potresti davvero voler svuotare la stringa di ricerca per riprenderla, nella versione di with-isearch-suspendedin isearch + .el ho aggiunto una variabile isearchp-if-empty-prefer-resuming-with-last, per controllare questo. Se lo associ a nile hai impostato isearch-new-stringsu, la ""ricerca riprende con una stringa di ricerca vuota.

Quindi con Isearch + puoi fare quello che vuoi con questa definizione:

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

Ho notato anche ora che Emacs 24.4 ha introdotto una regressione, che ho archiviato Emacs bug # 20466 per, il che significa che il legame DELin isearch-mode-mapnon è sufficiente. Hanno aggiunto un'associazione separata per <backspace>, oltre a una per DEL. Ciò significa che <backspace>non viene più tradotto in DEL, per Isearch (ma in genere viene comunque tradotto per Emacs).

Quindi, se si desidera che il tasto Backspace per fare quello che hai chiesto in Emacs 24.4 o successivo, allora non si può semplicemente legare DELa mydelete. Hai bisogno di legarsi <backspace>a mydelete. Dumb, AFAICT, mais on n'arrete pas le progres ...


Ho aggiunto un comando simile a Isearch + e lo ho associato C-M-l(la stessa chiave utilizzata per rimuovere una mancata corrispondenza del completamento in Icicles ).

C-gRicorda anche che in Isearch anche, in caso di mancata corrispondenza, verrà rimosso il testo non corrispondente. (Ma C-gha anche un effetto quando la ricerca ha esito positivo.)


Avrei dovuto menzionare che Isearch + ha anche avuto un comportamento facoltativo lungo linee simili per un bel po 'di tempo. M-kdurante Isearch commuta tra 3 comportamenti, che sono controllati dal valore dell'opzione isearchp-drop-mismatch:

  • replace-last- L'input corrente sostituisce l'ultimo testo non corrispondente. Puoi sempre vedere il tuo ultimo input, anche se si tratta di una mancata corrispondenza. Ed è disponibile per la modifica utilizzando M-e.

  • nil - L'input corrente viene aggiunto, anche se l'input precedente ha una parte non corrispondente.

  • qualsiasi altra cosa: il tuo input corrente viene ignorato (rimosso) se causa una mancata corrispondenza. La stringa di ricerca ha sempre corrispondenze riuscite.


A proposito, ho pensato di aggiungere un comando simile a Isearch + da quando ho aggiunto l'evidenziazione della parte fallita (anni fa, prima di aggiungerlo a GNU Emacs), ma non ci sono mai riuscito. L'ho fatto ora . (Non ho incluso la cancellazione di un personaggio, comunque. Il comando che ho aggiunto è no-op se non ci sono parti fallite.)
Estratto il

Sono su OS X. Intendevo cancellare all'indietro.
asmeurer

Il comportamento isearch + replace-last sembra piuttosto carino. C'è un modo per far sì che non suoni la campana ogni volta che la ricerca fallisce?
asmeurer

2
Ho caricato una nuova versione di isearch+.el. (A) corregge la rimozione automatica del disadattamento in modo che avvolgente funzioni OK. E aggiunge un'opzione, isearchp-ring-bell-functionche puoi usare per sopprimere la campana durante la ricerca.
Estratto il

3
Malabarba, interessante. Ho preso un colpo al bug e ho finito con questo . Per lo più culted cargo dalla isearch-del-charrisposta di Drew ma sembra funzionare come previsto. La with-isearch-suspendedmacro era il colpevole.
jbm
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.