Usuń część ciągu Isearch, która nie pasuje, lub ostatni znak, jeśli jest kompletny

11

Mam następujące

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

Celem tego kodu jest spowodowanie, aby deletew isearch usunął cały łańcuch, który się nie powiódł (lub jeśli nie ma żadnego łańcucha, którego nie ma tylko jeden znak).

Jednak delete-regionusuwanie tekstu z bufora isearchjest wyszukiwane, a nie sam bufor isearch.

Jak to zrobić w odpowiedni sposób? Mile widziane są również krytyki dotyczące reszty mojego stylu emacs lisp :)

asmeurer
źródło

Odpowiedzi:

12

O tak. Isearch odczytuje wpisane klucze, przegląda je isearch-mode-mapi wywołuje w bieżącym buforze .

Isearch czy nie , wbrew pozorom, użyj minibufor. Wykorzystuje obszar echa. Oznacza to, że to, co widzisz, to w rzeczywistości komunikaty wyjściowe , w tym echa wpisywanych znaków.

To powinno zrobić to, o co prosisz:

(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, twoje pytanie mówi o deleteznaku, ale napisałeś DEL, który jest znakiem cofania).


Jak wskazuje @Malabarba w komentarzu, po ustawieniu nowego ciągu wyszukiwania na ""(pusty ciąg), with-isearch-suspendedwznawia się, szukając ostatniego ciągu, zamiast zaczynać go.

Jest to ogólnie „ cechawith-isearch-suspended. Ale ponieważ czasami możesz naprawdę chcieć opróżnić szukany ciąg znaków do wznowienia, w wersji with-isearch-suspendedw isearch + .el dodałem zmienną isearchp-if-empty-prefer-resuming-with-last, aby to kontrolować. Jeśli to powiążesz nili ustawisz isearch-new-stringna, ""wyszukiwanie zostanie wznowione z pustym ciągiem wyszukiwania.

Dzięki Isearch + możesz robić, co chcesz dzięki tej definicji:

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

Zauważyłem też, że teraz Emacs 24.4 wprowadzono regresji, co mam złożone Emacs Bug # 20466 do, co oznacza, że wiązanie DELsię isearch-mode-mapnie jest wystarczające. Dodali osobne powiązanie dla <backspace>, oprócz jednego dla DEL. Oznacza to, że <backspace>nie zostanie przetłumaczony na DEL, na iSearch (ale to wciąż nie tak przetłumaczone na Emacsa ogólnie).

Jeśli więc chcesz, aby klawisz Backspace zrobił to, o co prosiłeś w Emacsie 24.4 lub nowszym, nie możesz po prostu się DELz nim powiązać mydelete. Trzeba związać <backspace>się mydelete. Dumb, AFAICT, mais on n'arrete pas le progres ...


Dodałem podobne polecenie do Isearch + i powiązałem je z C-M-l(ten sam klucz, który został użyty do usunięcia niedopasowania ukończenia w Icicles ).

Pamiętaj też, że C-gw Isearch również w przypadku niedopasowania usunie niedopasowany tekst. (Ale C-gdziała również, gdy wyszukiwanie się powiedzie.)


Powinienem wspomnieć, że Isearch + już od dłuższego czasu zachowuje się opcjonalnie podobnie. M-kpodczas Isearch przełącza między 3 zachowaniami, które są kontrolowane przez wartość opcji isearchp-drop-mismatch:

  • replace-last- Bieżące dane wejściowe zastępują ostatni niedopasowany tekst. Zawsze możesz zobaczyć swoje ostatnie wejście, nawet jeśli jest to niezgodność. I jest dostępny do edycji za pomocą M-e.

  • nil - Bieżące wejście jest dołączane, nawet jeśli poprzednie wejście ma niedopasowaną część.

  • cokolwiek innego - Bieżące dane wejściowe są ignorowane (usuwane), jeśli powodują niezgodność. Wyszukiwany ciąg zawsze ma udane dopasowania.

Rysował
źródło
BTW, myślałem o dodaniu podobnego polecenia do Isearch + , odkąd dodałem wyróżnianie nieudanej części (lata temu, zanim dodałem ją do GNU Emacs), ale nigdy się do tego nie przyłączyłem. Zrobiłem to teraz . (Nie dodałem jednak skreślenia postaci. Dodane przeze mnie polecenie nie działa, jeśli nie ma nieudanej części).
Drew
Korzystam z systemu OS X. Chciałem usunąć wstecz.
asmeurer
Zachowanie isearch + replace-last wygląda całkiem nieźle. Czy jest jednak jakiś sposób, aby nie dzwonił za każdym razem, gdy wyszukiwanie nie powiedzie się?
asmeurer
2
Przesłałem nową wersję isearch+.el. To (a) naprawia automatyczne usuwanie niezgodności, dzięki czemu zawijanie działa OK. I dodaje opcję, isearchp-ring-bell-functionktórej można użyć, aby stłumić dzwonek podczas wyszukiwania.
Drew
3
Malabarba, ciekawe. Strzeliłem do robaka i skończyłem z tym . Przeważnie kultywowane z ładunku isearch-del-chari odpowiedź Drew, ale wydaje się, że działa zgodnie z przeznaczeniem. with-isearch-suspendedMakro był winowajcą.
jbm