Удалить часть строки Isearch, которая не соответствует, или последний символ, если полное соответствие

11

У меня есть следующее

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

Цель кода - заставить deleteв isearch удалить всю строку с ошибками (или, если нет строки с ошибкой, только один символ).

Однако при delete-regionудалении текста из буфера isearchвыполняется поиск, а не сам буфер поиска.

Как правильно это сделать? Критика остального моего стиля в Emacs также приветствуется :)

asmeurer
источник

Ответы:

12

О да. Isearch считывает введенные вами ключи, просматривает их isearch-mode-mapи вызывает их в текущем буфере .

ISearch делает не , несмотря на выступления, используйте минибуфер. Он использует область эха. То есть то, что вы видите, на самом деле выводит сообщения, включая отголоски введенных вами символов.

Это должно сделать то, что вы просите:

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

(Кстати, ваш вопрос говорит о deleteперсонаже, но вы написали DEL, что является символом возврата.)


Как указывает @Malabarba в комментарии, когда вы устанавливаете новую строку поиска в значение ""(пустая строка), она with-isearch-suspendedвозобновляется путем поиска последней строки поиска, вместо этого начинается с пустой строки поиска.

Это « особенность » with-isearch-suspended, в общем. Но поскольку иногда вам может понадобиться очистить строку поиска для возобновления, в версии with-isearch-suspendedв isearch + .el я добавил переменную isearchp-if-empty-prefer-resuming-with-last, чтобы контролировать это. Если вы связываете это с nilи вы устанавливаете isearch-new-stringна, ""тогда поиск возобновляется с пустой строкой поиска.

Так что с Isearch + вы можете делать то, что вы хотите с этим определением:

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

Теперь я также заметил, что в Emacs 24.4 введена регрессия, для которой я подал ошибку Emacs # 20466 , что означает, что привязки DELв ней isearch-mode-mapнедостаточно. Они добавили отдельную привязку для <backspace>, в дополнение к одной для DEL. Это означает, что <backspace>больше не переводится DELдля Isearch (но все равно переводится для Emacs в целом).

Поэтому, если вы хотите, чтобы клавиша Backspace выполняла то, что вы просили в Emacs 24.4 или новее, вы не можете просто DELвыполнить привязку mydelete. Вам нужно привязать <backspace>к mydelete. Тупой, AFAICT, mais on n'arrete pas le progres ...


Я добавил аналогичную команду в Isearch + и привязал ее к C-M-l(тот же ключ, который использовался для удаления несоответствия завершения в Icicles ).

Помните также, что C-gв Isearch также, при наличии несоответствия, удалит несоответствующий текст. (Но C-gтакже имеет эффект при успешном поиске.)


Я должен был упомянуть, что Isearch + также имел необязательное поведение в том же духе уже довольно давно. M-kво время Isearch переключается между 3 поведениями, которые контролируются значением option isearchp-drop-mismatch:

  • replace-last- Ваш текущий ввод заменяет последний несоответствующий текст. Вы всегда можете увидеть свой последний ввод, даже если это несоответствие. И это доступно для редактирования с помощью M-e.

  • nil - Ваш текущий ввод добавляется, даже если предыдущий ввод содержит несоответствующую часть.

  • что-нибудь еще - ваш текущий ввод игнорируется (удаляется), если он вызывает несоответствие. Строка поиска всегда имеет успешные совпадения.

Нарисовался
источник
Кстати, я думал о добавлении подобной команды в Isearch + с тех пор, как добавил подсветку неудачной части (несколько лет назад, до того, как я добавил ее в GNU Emacs), но я так и не смог обойти ее. Я сделал это сейчас . (Однако я не включил удаление символа. Я добавил команду, которая не выполняет никаких операций, если нет неудачной части.)
Дрю
Я на OS X. Я имел в виду назад удалить.
asmeurer
Поведение isearch + replace-last выглядит довольно хорошо. Есть ли способ заставить его не звонить в колокол каждый раз, когда поиск не удался?
asmeurer
2
Я загрузил новую версию isearch+.el. Он (а) исправляет автоматическое удаление несоответствия, так что перенос работает нормально. И добавляет опцию, isearchp-ring-bell-functionкоторую вы можете использовать для подавления звонка во время поиска.
Дрю
3
Малабарба, интересно. Я выстрелил в жука и закончил с этим . По большей части из-за груза isearch-del-charи ответа Дрю, но, похоже, он работает как задумано. with-isearch-suspendedМакрос был виновником.
JBM