Comment puis-je utiliser l'achèvement du mode insertion dans une macro?

11

J'essaie de définir une macro qui génère rapidement une liste de mots aléatoires.
Je veux que la macro transforme cela en une liste comme

a
b
c
d
e

dans ce

arezzo
bywords
czars
détente
eyrie

Ce que j'ai jusqu'à présent:

  • mettre le curseur sur la lettre a
  • démarrer l'enregistrement macro qq
  • a entrer en mode insertion
  • <C-x><C-k> - perform dictionary completion on the character before cursor - in this case the lettera`
  • <C-p>sélectionnez le dernier élément de la liste d'achèvement qui apparaît, sur mon système, c'est le mot arezzo. (NB j'ai longestinclus dans mon 'completeopt'cadre, ce qui est nécessaire pour <C-p>travailler de cette façon lors de l'achèvement:) 'set completeopt=longest,menuone,preview'.
  • <C-y> accepter l'achèvement
  • ^[^[ quitter le mode d'insertion
  • j passer à la ligne suivante, prêt à faire la même opération sur la ligne suivante
  • q arrête d'enregistrer

lorsque je crée la macro et que j'exécute les étapes manuellement, tout fonctionne bien, mais lorsque j'exécute la macro, je vois un message clignotant dans la ligne de commande quelque chose comme:

analyse du fichier du dictionnaire

et rien ne se passe, des commandes de la macro uniquement jsont exécutées, c'est-à-dire que le curseur se déplace le long de la ligne, mais aucune des commandes de fin n'est exécutée.
Est-il possible d'utiliser des compléments de mode d'insertion dans une macro, et si oui, comment faire?

the_velour_fog
la source
Je ne comprends pas votre <C-p>étape ... quand je fais ça dans mon vim, ça donne juste le message back at original- ne sélectionne pas le dernier élément .. J'ai utilisé la touche fléchée vers le haut deux fois pour sélectionner le dernier mot (mon cas azures), j'ai appuyé sur enter et alors Esc+j+q.. cela fonctionne très bien sur l'exécution de la macro
Sundeep
1
@spasic ah bon point, j'aurais dû le mentionner, mais j'utilise set completeopt=longest,menuone,previewson longestoption qui provoque <C-p>l'insertion immédiate. Si je retire longestde la completeoptchaîne, j'obtiens le même comportement que vous. De plus, oui, les touches fléchées ont fonctionné! merci (j'ai oublié que vous pouvez les utiliser pour naviguer dans la liste d'achèvement)
the_velour_fog
Peut-être que le menu contextuel interfère. Essayez peut-être :set completeopt=et a<c-x><c-k><esc>jcomme macro.
Antony
@Antony Je ne sais pas pourquoi le <Cp> ne fonctionnait pas, mais les touches fléchées directionnelles ont fonctionné.
the_velour_fog

Réponses:

2

EDIT : vous êtes vraiment après l'achèvement du dictionnaire; vous n'avez pas nécessairement besoin du mode d'insertion (mode Ctrl + X) pour ce faire. Comme vous l'avez découvert, cela rend le travail avec les macros très difficile. Le script ci-dessous peut être utilisé pour compléter le dictionnaire sans mode d'insertion, de sorte que vous pouvez facilement le répéter à l'intérieur d'une macro.

Ajoutez le code ci-dessous à votre .vimrcfichier, fermez et rouvrez toutes les fenêtres vim pour générer la nouvelle fonction, puis enregistrez-vous en appuyant alternativement sur <C-k>pour terminer et jsur la ligne suivante. J'ai ajouté une vérification pour l' longestoption et si elle est désactivée, elle choisit une entrée aléatoire en utilisant l'heure aléatoire du système. S'il trouve l' longestoption, il recherche manuellement l'entrée la plus longue dans le dictionnaire et l'insère.

Si vous n'aimez pas la <C-k>cartographie, n'hésitez pas à la modifier comme bon vous semble. Cela devrait fonctionner avec n'importe quel mappage que vous aimez.

En outre, la commande pour renvoyer l'expression pour le mappage à évaluer ajoute un \<esc>caractère à la fin afin que nous quittions le mode d'insertion automatiquement après chaque insertion, et un 0cwà l'avant pour entrer en mode d'insertion pour commencer et assurez-vous d'écraser le mot entier correctement. Selon le comportement exact que vous souhaitez (si vos mots ne sont pas bien au bcwdébut de chaque ligne), vous pouvez utiliser à la place pour trouver le début du mot réel. Cependant, vous verrez alors des bizarreries en revenant aux mots qui commencent la ligne. Il y a probablement une commande plus avancée pour ignorer la fin de ligne et faire les deux à la fois, mais je n'ai pas pu en trouver une.

map <expr> <C-k> CompleteDictionary()
fun! CompleteDictionary()
    let cword = expand(“<cword>”)
    let res = []
    for m in readfile(&dictionary)
        if m =~ '^' . cword
            call add(res, m)
        endif
    endfor
    if &completeopt =~ 'longest'
        let max = 0
        let maxindex = 0
        let index = 0
        for item in res
            if strlen(item) > max
                let max = strlen(item)
                let maxindex = index
            endif
            let index = index + 1
        endfor
        return "0cw" . res[maxindex] . "\<esc>"
    else
        return "0cw" . res[system('@echo %RANDOM%') % len(res)] . "\<esc>"
    endif
endfun

De plus, il ne serait pas difficile d'étendre la logique ici pour créer des mappages alternatifs (en utilisant, par exemple, des paramètres de fonction) qui exécutent n'importe quelle fonction fournie par le mode d'insertion. Je serai heureux de répondre à ces exigences et de mettre à jour ce script lorsque j'en aurai le temps.

Tim
la source
Cela ressemble à une explication plausible du problème, mais j'ai essayé vos deux solutions suggérées, et aucune ne semblait vous aider.
Rich
Avez-vous également essayé la sleepcommande?
Tim
Oui, mais uniquement avec la valeur suggérée de 5 secondes. Avez-vous réussi à faire fonctionner l'une ou l'autre solution? Pourriez-vous publier une liste complète des étapes?
Rich
Ce n'est pas moi qui ai écrit la question. Cependant, je peux reproduire le problème: vous devez ajouter le plus long de la completeoptmanière décrite dans les commentaires (encore une fois, pas par moi). edit : Oups, 'longest'est requis pour l' ctrl-pétape: non ctrl-y. Toujours les étapes décrites par le travail question pour moi-asker en vim -Nu NONEavec completeoptmodifiées.
Rich
Je pense avoir trouvé une solution, donnez-moi quelques minutes pour mettre à jour ma réponse avec.
Tim