Comment mapper d [count] d?

18

NB Ce n'est pas un doublon de Comment fonctionne la commande "d3fg"? Veuillez le lire avant de voter pour fermer!

Je suis dans une impasse dans ma quête pour que les petites suppressions fonctionnent comme les grandes . Le problème que j'ai, c'est que je ne peux pas comprendre comment remapper des commandes comme d3d. En fait, je ne peux même pas comprendre comment ils fonctionnent en premier lieu, ni trouver aucune mention d'eux dans l'aide de Vim. *

d3jest simple: il applique l' dopérateur au 3jmouvement,

3ddest également simple: il exécute la ddcommande avec un "nombre" de 3.

d3d semble que cela devrait être simple, il applique l' dopérateur à la… mais qu'est-ce que c'est 3d? Ce n'est pas une motion. Si vous tapez 3dseul, Vim le traite comme un décompte suivi par un opérateur et attend patiemment une nouvelle saisie.

Et vous ne pouvez pas appliquer d'opérateurs à d'autres opérateurs. ddn'est pas décrit dans l'aide comme une séquence de deux opérateurs. Il s'agit d'une commande distincte à deux touches. (cf. dc, qui ne fait rien.)

Il ne semble pas non plus que le positionnement du comptage soit flexible pour les commandes qui nécessitent deux touches: 2gjdéplace le curseur vers le bas de deux lignes d'écran, mais g2jsupprime entièrement les deux premières touches et déplace le curseur vers le bas d'une ligne.

Alors, comment ça marche? Est-ce juste un cas particulier dans le code interne de Vim? Existe-t-il un moyen de créer un d[count]dmappage?

EDIT : Est-ce un objet texte? :h text-objectsne comprend pas dans la liste des « commandes texte de sélection d'objet », mais il ne comprend dd dans la liste des suppressions « groupées de petits aux grands objets ». Et d2awsupprime le mot sous le curseur et le suivant. En revanche, c2dne fait rien.

* Je suis sûr que certaines mentions doivent exister, mais je ne le trouve pas. Je l' ai lu :help deleting, :help motion.txtet essayé :helpgrep dNdpour toutes les valeurs de N de 1-9 .

Riches
la source
2
Je pense que le dernier dfait office de confirmation; C'est donc la même chose que d3<CR>. y3yet c3cfonctionnent également de la même façon ... Je ne trouve pas de documentation à ce sujet, cependant, dans Vim: help, vi (1), nvi (1) ou la spécification POSIX ... Il se comporte de la même manière dans viet nvibtw .
Martin Tournoij
1
D'une certaine manière, ddest identique à d_. _place le curseur sur le premier non vide de la ( [count]-1) ème ligne vers le bas, mais il est dans le sens des lignes, donc lorsqu'il est associé à un opérateur, il fonctionne sur des lignes entières. Pour cette raison, il est logique qu'un décompte puisse apparaître entre les deux dal.
tommcdo

Réponses:

28

Mode en attente de l'opérateur

Entre la saisie d' un opérateur (tel que d, cou gU) et un mouvement (comme w, i}ou /foo<CR>), Vim est en mode opérateur en instance. Vous pouvez créer des mappages pour cela en utilisant :omapet :onoremap.

Dans mes exemples, je vais mapper l'opérateur en attente dsur w. C'est un choix aléatoire, car je ne sais pas pourquoi vous vouliez réellement l'utiliser.

Créer une omap

Créons un mappage pour den mode Opérateur en attente. Je vais supposer que nous écrivons VimScript ici (comme dans le vôtre .vimrc), donc je vais omettre les :s.

onoremap d w

Cela fait ddagir comme dw. Cela fait aussi d[count]dagir comme d[count]w. Mais je parie que vous ne vouliez pas affecter le comportement de dd(c'est-à-dire non [count]fourni).

Mappages d'expressions

Les mappages d'expressions vous permettent d'évaluer une expression VimScript pour produire le côté droit du mappage. L'expression doit correspondre à une chaîne. Les mappages d'expressions sont indiqués par le <expr>mot - clé.

Vim possède également des variables intégrées qui sont remplies à différents moments et sont souvent utiles lors des mappages. L'un d'eux est celui v:countqui est [count]fourni à un opérateur ou à un mouvement.

Mettons tout cela ensemble. Si aucun [count]n'est fourni, le v:countsera 0. Nous pouvons dire à notre mappage de ne l'utiliser dque dans ce cas.

onoremap <expr> d v:count == 0 ? 'd' : 'w'

Se ddcomporte désormais comme la valeur par défaut (supprime une ligne), mais d[count]dse comporte comme d[count]w. Cool!

Restreindre à utiliser après l' dopérateur

Vous remarquerez peut-être quelque chose, cependant. Se cdcomporte maintenant aussi comme cw. Ce n'est peut-être pas un problème, mais pour être complet, limitons-le afin qu'il ne fonctionne qu'après l' dopérateur.

Vim a une autre variable, v:operatorqui contient l'opérateur le plus récemment utilisé. Vérifions cela aussi avant de faire quelque chose de spécial.

onoremap <expr> d (v:count == 0 \|\| v:operator != 'd') ? 'd' : 'w'

REMARQUE: Étant donné que les :mapcommandes peuvent être chaînées |, nous devons les échapper dans notre expression ici. Ainsi, l'opérateur logique OU ||devient \|\|.

Cool, donc cdet c[count]dsont de retour à ne rien faire, comme ils le faisaient auparavant. C'est bien pour que d'autres plugins puissent définir cd.

Je ne veux pas simplement supprimer une autre motion

Si vous vouliez mapper d[count]dsur quelque chose de totalement différent, rien à voir avec la suppression de texte, nous pouvons aussi le faire fonctionner.

Lorsque vous tapez des commandes en mode Normal et que vous commencez à taper une commande par erreur, vous pouvez appuyer sur <Esc>pour annuler cette commande. La même chose s'applique à vos mappages.

Faisons d[count]dchanger la ligne actuelle à quoi que ce [count]soit.

onoremap <expr> d (v:count == 0 \|\| v:operator != 'd') ? 'd' : '<Esc>cc' . v:count . '<Esc>'

La dernière partie de la mise en correspondance est une expression VimScript: <Esc>cc' . v:count . '<Esc>'. C'est <Esc>pour annuler la dcommande en attente , puis ccpour changer la ligne en cours, v:countpour taper la valeur de [count](en mode Insertion), et <Esc>pour revenir en mode Normal. Notez que nous construisons une chaîne en utilisant ici l'opérateur de concaténation VimScript, ..


Votre cas d'utilisation réel sera probablement différent de ce que j'ai décrit ici, mais j'espère que cela vous aidera à faire bouger les choses.

Happy Vimming!

tommcdo
la source
Très bonne réponse! A voté. J'ai fait un lien vers mon cas d'utilisation (également sur vi.SE) au début de la question, mais je suppose que vous devez l'avoir manqué. J'ai essentiellement besoin de faire :omap d d(!), Mais malheureusement le mode en attente d'opérateur n'est jamais réellement atteint à cause de mon mappage pour d qui définit la fonction d'opérateur personnalisé. J'espère qu'il est possible de modifier les choses pour d3dqu'elles fonctionnent correctement. (Faites-moi savoir si vous avez des idées, ou n'hésitez pas à publier une solution complète à l'autre question si vous préférez.) Si je ne peux pas le comprendre rapidement, je l'accepterai et publierai une autre question plus spécifique. Merci!
Rich
1
En fait, après réflexion, j'accepte cela maintenant. Vous avez expliqué à la fois comment créer une telle cartographie, et aussi comment cela fonctionne sous le capot, qui étaient les deux choses que j'ai posées.
Rich