Comment traiter le soulignement comme une partie du mot?

34

J'utilise le evilmode Emacs + .

Lorsque je positionne le curseur sur e(à l'état normal) dans un bloc de texte tel que abc_def_ghi, ciw(changer le mot intérieur) ne change que la defpartie de la chaîne, alors que Vim modifierait la totalité abc_def_ghi.

Comment puis-je forcer evilà traiter le trait de soulignement comme le fait Vim (c'est-à-dire comme faisant partie du mot)?

Kossak
la source

Réponses:

26

Solution de contournement la plus simple: permet ciWde sélectionner un mot délimité par des espaces.

Le problème le plus important concerne la valeur du _caractère dans la table de syntaxe . Le problème est qu’il _s’agit par défaut d’un constituant de symbole dans la table de syntaxe et que vous souhaitez le traiter comme un constituant de mot.

Si vous utilisez emacs 24.4, vous pouvez essayer de l'activer superword-mode. Je n'ai pas essayé moi-même, donc votre kilométrage peut varier.

Une alternative consiste simplement à modifier vous-même la table de syntaxe et à indiquer à Emacs que vous souhaitez que le _caractère soit considéré comme un mot constituant, comme suit:

(modify-syntax-entry ?_ "w")

Une fois que vous avez fait cela, ciwfonctionne comme vous le souhaitez, de sorte qu'il sélectionne tout abc_def_ghiplutôt que juste def.

Faire cela de cette manière peut toutefois être exagéré, surtout si vous voulez seulement que cela _compte dans le mot pour l’objet texte. Au lieu de cela, vous pouvez conseiller evil-inner-wordcomme suit:

(defadvice evil-inner-word (around underscore-as-word activate)
  (let ((table (copy-syntax-table (syntax-table))))
    (modify-syntax-entry ?_ "w" table)
    (with-syntax-table table
      ad-do-it)))

Maintenant, _reste un symbole constitutif de tout sauf de l'objet texte de mot intérieur, donc ciwfera exactement ce que vous voulez sans toucher à la fonctionnalité de quoi que ce soit d'autre.

Vous pouvez en savoir plus sur la modification des tables de syntaxe sur le nœud EmacsWiki .

Dan
la source
Cela fonctionne comme un charme. Pour modifier tous les mouvements ( w, aw, etc.), vous pouvez faire la même chose avec les fonctions suivantes aussi: evil-forward-word-begin, evil-forward-word-end, evil-backward-word-begin, evil-backward-word-end, evil-a-word, evil-inner-word. Remarque: vous devez modifier underscore-as-worddifférentes valeurs uniques (arbitraires).
sitaktif
(modify-syntax-entry ?_ "w")n'a pas fonctionné pour moi pour une raison quelconque. Le faire de manière interactive n'a pas fonctionné non plus. Une idée pourquoi ou comment je peux déboguer ceci? Je suis sur Spacemacs au cas où cela serait pertinent.
Helder S Ribeiro
1
Ceci explique mon problème. Apparemment, vous devez faire explicitement référence à la table de syntaxe cible. Dans mon cas, j'ai utilisé (modify-syntax-entry ?_ "w" rust-mode-syntax-table), alors cela a fonctionné.
Helder S Ribeiro
Quels sont les effets inattendus de la modification de l'entrée de syntaxe?
luntain
FTR: superword-moden'affecte pas le mouvement dans evil-mode. Ce n'est donc pas un élément constitutif de la modification des tables de syntaxe.
Bonjour Angel
28

L'extrait suivant fera en sorte que Mal traite un symbole Emacs comme un mot.

(with-eval-after-load 'evil
    (defalias #'forward-evil-word #'forward-evil-symbol)
    ;; make evil-search-word look for symbol rather than word boundaries
    (setq-default evil-symbol-word-search t))

Cela a l'avantage de changer en fonction de la langue:

foo-bar

est un symbole lisp-modemais deux symboles (séparés par -) dans c-mode.

Erik
la source
14

La FAQ de spacemacs offre la solution suivante spécifique à la langue:

;; For python
(add-hook 'python-mode-hook #'(lambda () (modify-syntax-entry ?_ "w")))
;; For ruby
(add-hook 'ruby-mode-hook #'(lambda () (modify-syntax-entry ?_ "w")))
;; For Javascript
(add-hook 'js2-mode-hook #'(lambda () (modify-syntax-entry ?_ "w")))

Cela fonctionne également dans les Emacs ordinaires. Avec le mal sur, il fonctionne avec toutes les commandes liées à mot ( w, e, *, #, etc.)

Plus généralement, cela le fera pour tous les principaux modes:

(add-hook 'after-change-major-mode-hook
          (lambda ()
            (modify-syntax-entry ?_ "w")))
ejoubaud
la source
2
Utiliser 'prog-mode-hookune option pour couvrir toutes les langues?
BallpointBen
2

Emacs 24 a introduit superword-mode, un mode mineur qui traite les soulignements comme des mots. evil-moderespecte ce paramètre.

Voici la documentation:

(superword-mode &optional ARG)

Basculer le mouvement et l’édition du super-mot (mode Super-mot). Avec un argument préfixe ARG, activez le mode Superword si ARGest positif et désactivez-le. Si appelé depuis Lisp, activez le mode si ARGomis ou nul.

Le mode Superword est un mode mineur avec tampon local. L'activer modifie la définition des mots, de sorte que les symboles sont traités comme des parties de mots: par exemple, in superword-mode, "this_is_a_symbol"compte pour un mot.

BallpointBen
la source
Si vous utilisez evil-mode, malheureusement, il y a un bug quand superword-modeest activé. Cela provoque un comportement erratique quand evil-forward-word-beginon l'appelle: github.com/emacs-evil/evil/issues/721
modulitos
0

En fait, j'aime assez ce comportement car je pourrais vouloir simplement éditer une partie du mot et garder les autres parties intactes. Si je veux reprendre tout le mot, je peux toujours utiliser E, Wou Bles variantes majuscules. Cela me donne un contrôle plus fin.

xji
la source