J’ai utilisé vim puis neovim pendant plus de 15 ans comme éditeur de texte. Mon utilisation a évolué avec le temps, et avec mes configurations, mes habitudes également.
Après avoir détourné le regard face à l’utilisation d’IA génératives pour la génération et la revue de code au sein de neovim, et aux différents sponsors éditant des solutions pour faciliter l’intégration de LLMs dans les workflows. La réaction récente de l’équipe de développement sur la présence d’une citation de DHH sur le site vitrine de neovim m’a fait revoir ma position. J’ai, en effet, évité les logiciels comme hyprland lorsqu’une alternative existe, ma limite étant le soutien aux comportements néfastes.
Il s’avère que dans ce cas, les alternatives sont pléthores. Effectivement, contrairement au passage de vim à neovim, le changement ne sera pas transparent, mais c’est un coût que je suis prêt à payer. J’ai déjà changé de disposition de lettres sur le clavier… deux fois (azerty → bépo → ergo‑L), j’ai même dû réapprendre à utiliser vim après avoir fait l’erreur d’avoir réassigné les commandes de base par leur équivalent positionnel, ce qui leur faisait perdre leur sémantique et en plus cassait d’autres raccourcis en aval…
Sur ce, je me suis lancé dans helix en me disant que j’apprendrais sur le tas. Ce choix repose sur un constat simple : je souhaite juste un éditeur de texte qui fonctionne d’emblée sans avoir 1 000 lignes de configuration, dont 500 uniquement pour paramétrer mes LSPs. De plus, après avoir regardé la liste des éditeurs de texte, leurs rapports avec l’IA générative, et mis en regard avec le constat précédent, je me suis dit que c’était un combat perdu d’avance face à l’engouement généralisé.
J’utilise déjà un éditeur modal, qu’est-ce qui pourrait mal se passer ? Je lance
donc hx --tutor et fais déjà le deuil de
telescope.nvim (un
explorateur de code/fichiers en
recherche approximative)
et découvre que… c’est natif.
Plusieurs choses changent, notamment, la grammaire de l’éditeur : champs-action pour helix contre action-champs pour (neo)vi(m), mais je m’y attendais déjà. Je savais aussi que j’allais lutter contre ma mémoire musculaire, et commence par remettre mes raccourcis usuels dans un premier temps pour rendre l’éditeur utilisable sans trop souffrir :
^pour aller au premier caractère utile,0pour le premier caractère de la ligne et$pour le dernier ;{/}pour naviguer dans les paragraphes ;gqpour reformater la sélection en fonction de la taille maximale des lignes (usuellement 80 dans mon cas).
Bon, très vite, je me rends compte qu’en fait, je n’utilise plus ^ mais _
depuis un moment grâce à ergo‑L (c’est presque le même déplacement, _ peut
prendre en compte un compteur (pour prendre le premier caractère de la (compte –
1)-ième ligne à partir de la ligne en cours) contrairement à ^ mais je
n’utilise jamais cette commande avec un compteur) et je change ça. Pour le reste
la seule chose qui me dérange est que $ réécrit une commande existante
(shell_keep_pipe, je n’ai pas encore investigué les cas d’usages). Je me suis
noté d’essayer d’utiliser plus souvent son équivalent gl dans helix (d’autant
plus que c’est un poil plus accessible que $, mais c’est débattable), mais ce
n’est pas encore rentré. {/} semble redondant avec [/] et pour le
moment, je n’ai rien remarqué d’étrange. J’avais également le raccourci W pour
:w. Comme c’est une commande native (et un déplacement utile : aller au MOT
suivant au lieu du mot suivant (la différence est que dans « porte‑monnaie »,
“porte”, “‑” et “monnaie” sont des mots, mais “porte-monnaie” est un MOT
(lettres entourées d’espaces))), je l’ai remplacé par <Space>t (lors de la
rédaction de ce billet) de manière purement arbitraire (sur un raccourci
inutilisé), juste pour avoir un raccourci “sous les doigts” lorsque je tape,
comme c’est une commande que je lance… souvent. En bonus, comme c’est une
commande souvent effectuée, c’est rentré presque immédiatement dans mes doigts.
Pour le reste, les habitudes se prennent étonnamment vite, et je me suis surpris
à faire des mip dans neovim au lieu de vip pour sélectionner un paragraphe.
J’ai aussi remarqué que beaucoup de comportement par défaut se rapprochent de ce
que j’avais avec ma
dernière configuration en date reposant sur
kickstart.nvim, ce qui a aidé
pour ma transition.
Pour le moment, ce qui m’a le plus manqué est
l’absence de textobject
pour les phrases, ce qui me laisse à penser qu’helix est plus un éditeur de code
qu’un éditeur de texte (même s’il y a des alternatives, auxquelles je me fais
pour le moment, comme naviguer via fFtT pour sélectionner le morceau choisi).
Quelques particularités de :reflow qui font qu’il est inutilisable pour du
markdown (il découpe les liens…) qui font que je passe par un formateur
externe pour ça (ce qui se fait très facilement dans la configuration des
langages).
Bien entendu, mon erreur la plus courante reste encore l’envie de taper sur x
pour supprimer le caractère sous le curseur et non d (comme la sélection se
fait avant la commande et non après, cette distinction x/d n’est plus
utile).
Il ne reste plus qu’à voir à l’usage ce que cela va donner. Pour le moment, je suis satisfait du changement.
Mes fichiers de configuration
Pour finir, contrairement à ma configuration neovim qui est versionnée, je ne l’ai pas encore fait pour helix. Mais comme celle-ci fait 50 + 19 lignes, je vais simplement la partager ici (elle est encore en évolution, comme je n’ai pas encore utilisé helix assez longtemps pour avoir fait tous les changements dont je pourrais avoir besoin) :
$XDG_CONFIG_HOME/helix/config.toml
theme = "rose_pine_dawn"
[editor]
auto-format = false
line-number = "relative"
rulers = [81]
[editor.whitespace.render]
nbsp = "all"
nnbsp = "all"
[editor.whitespace.characters]
nbsp = "⍽"
nnbsp = "␣"
[editor.statusline]
left = ["mode", "spinner", "read-only-indicator", "file-modification-indicator",
"version-control"]
center = ["file-name"]
right = ["diagnostics", "selections", "register", "position", "file-encoding",
"file-line-ending", "file-type"]
[editor.cursor-shape]
insert = "bar"
[editor.indent-guides]
render = true
skip-levels = 1
[editor.soft-wrap]
enable = true
[keys.select]
"{" = "goto_prev_paragraph"
"}" = "goto_next_paragraph"
"_" = "goto_first_nonwhitespace"
"0" = "goto_line_start"
"$" = "goto_line_end"
"g" = { "q" = ":reflow" }
[keys.normal]
"esc" = ["collapse_selection", "keep_primary_selection"]
"{" = "goto_prev_paragraph"
"}" = "goto_next_paragraph"
"_" = "goto_first_nonwhitespace"
"0" = "goto_line_start"
"$" = "goto_line_end"
"space" = { "t" = ":w", "T" = ":format" }
"g" = { "q" = ":reflow" }
"Z" = { "Z" = ":wq" }
$XDG_CONFIG_HOME/helix/languages.toml
[[language]]
name = "markdown"
language-servers = ["marksman", "ltex-ls-plus"]
formatter = { command = 'prettier', args = ["--parser", "markdown", "--prose-wrap", "always"] }
[[language]]
name = "javascript"
language-servers = ["typescript-language-server", "vscode-eslint-language-server"]
[language-server.tinymist.config]
preview.background.enabled = true
preview.background.args = ["--data-plane-host=127.0.0.1:0", "--invert-colors=never", "--open"]
# TODO: clean up rules
[language-server.ltex-ls-plus.config]
ltex.enabledRules = { "en" = [ "EN_CONSISTENT_APOS" ] }
ltex.disabledRules = { "fr" = [ "APOS_TYP", "FRENCH_WHITESPACE", "CHANGE", "ISSUE", ], en = [ "DASH_RULE", "TWO_HYPHENS", "CHANGE", "ISSUE", "CHECK", "ACTUALLY", "CONSISTENT", "EN_CONSISTENT_APOS", "WHITESPACE_RULE", "ARROWS" ] }
ltex.additionalRules = { "enablePickyRules" = "true" }
ltex.language = "auto"
ltex.diagnosticSeverity = "information"
Note : pour que vscode-eslint-language-server fonctionne, j’ai dû
recompiler helix comme la dernière release ne contient pas
cette demande de fusion
comme indiqué sur
ce post reddit.
Remerciements : Merci à HS-157 pour sa relecture.