Supprimer la partie de la chaîne Isearch qui ne correspond pas, ou le dernier caractère si la correspondance est complète

11

J'ai le suivant

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

Le but du code est de faire deleteen isearch supprimer toute la chaîne échouée (ou s'il n'y a pas de chaîne échouée juste un seul caractère).

Cependant, la delete-regionsuppression de texte du tampon isearchest en cours de recherche, pas le tampon de recherche lui-même.

Quelle est la bonne façon de procéder? La critique sur le reste de mon style lisp emacs est également la bienvenue :)

asmeurer
la source

Réponses:

12

Ah oui. Isearch lit les clés que vous tapez, les recherche isearch-mode-mapet les appelle dans le tampon actuel .

Isearch n'utilise pas , malgré les apparences, le mini-tampon . Il utilise la zone d'écho. Autrement dit, ce que vous voyez là est en fait des messages de sortie , y compris des échos des caractères que vous tapez.

Cela devrait faire ce que vous demandez:

(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, votre question dit le deletecaractère, mais vous avez écrit DEL, qui est le caractère de retour arrière.)


Comme @Malabarba le fait remarquer dans un commentaire, lorsque vous définissez la nouvelle chaîne de recherche sur ""(chaîne vide), with-isearch-suspendedreprend en recherchant la dernière chaîne de recherche, en commençant plutôt par une chaîne de recherche vide.

C'est une " caractéristique " de with-isearch-suspended, en général. Mais parce que vous voudrez parfois vraiment vider la chaîne de recherche pour la reprise, dans la version de with-isearch-suspendeddans isearch + .el, j'ai ajouté une variable isearchp-if-empty-prefer-resuming-with-last, pour contrôler cela. Si vous liez cela à nilet que vous définissez isearch-new-stringsur, la ""recherche reprend avec une chaîne de recherche vide.

Donc avec Isearch + vous pouvez faire ce que vous voulez avec cette définition:

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

Je remarque aussi maintenant que Emacs 24.4 introduit une régression, que j'ai déposé bug Emacs # 20466 pour, ce qui signifie que la liaison DELen isearch-mode-mapne suffit pas. Ils ont ajouté une liaison distincte pour <backspace>, en plus d'une pour DEL. Cela signifie que <backspace>n'est plus traduit en DEL, pour Isearch (mais il est toujours aussi traduit pour Emacs en général).

Donc, si vous voulez que la touche Retour arrière fasse ce que vous avez demandé dans Emacs 24.4 ou version ultérieure, vous ne pouvez pas simplement vous lier DELà mydelete. Vous devez vous lier <backspace>à mydelete. Dumb, AFAICT, mais on n'arrete pas le progres ...


J'ai ajouté une commande similaire à Isearch + et je l'ai liée à C-M-l(la même clé utilisée pour supprimer un décalage d'achèvement dans Icicles ).

Sachez également que C-gdans Isearch, en cas de non-concordance, supprimera également le texte non-concordant. (Mais a C-gégalement un effet lorsque la recherche est réussie.)


J'aurais dû mentionner que Isearch + a également eu un comportement facultatif dans le même sens depuis un bon moment maintenant. M-kpendant Isearch bascule entre 3 comportements, qui sont contrôlés par la valeur de l'option isearchp-drop-mismatch:

  • replace-last- Votre entrée actuelle remplace le dernier texte incompatible. Vous pouvez toujours voir votre dernière entrée, même s'il s'agit d'un décalage. Et il est disponible pour l'édition en utilisant M-e.

  • nil - Votre entrée actuelle est ajoutée, même si l'entrée précédente a une partie non appariée.

  • toute autre chose - Votre entrée actuelle est ignorée (supprimée) si elle provoque une incompatibilité. La chaîne de recherche a toujours des correspondances réussies.

A dessiné
la source
BTW, j'ai pensé à ajouter une commande similaire à Isearch + depuis que j'ai ajouté la mise en évidence de la partie échouée (il y a des années, avant de l'ajouter à GNU Emacs), mais je n'y suis jamais parvenu. Je l'ai fait maintenant . (Je n'ai pas inclus la suppression d'un personnage, cependant. La commande que j'ai ajoutée est un no-op s'il n'y a pas de partie ayant échoué.)
Drew
Je suis sur OS X. Je voulais dire supprimer à l'envers.
asmeurer
Le comportement isearch + replace-last est plutôt sympa. Est-il possible de ne pas sonner à chaque fois que la recherche échoue?
asmeurer
2
J'ai téléchargé une nouvelle version de isearch+.el. Il (a) corrige la suppression automatique de la non-concordance afin que le bouclage fonctionne correctement. Et il ajoute une option, isearchp-ring-bell-functionque vous pouvez utiliser pour supprimer la cloche pendant la recherche.
Drew
3
Malabarba, intéressant. J'ai pris une photo du bug et je me suis retrouvé avec ça . Surtout cultivé par la cargaison isearch-del-charet la réponse de Drew, mais cela semble fonctionner comme prévu. La with-isearch-suspendedmacro était le coupable.
jbm