Debian-facile

Bienvenue sur Debian-Facile, site d'aide pour les nouveaux utilisateurs de Debian.

Vous n'êtes pas identifié(e).

#1 06-05-2020 18:26:47

Elzen
Modérateur
Distrib. : Debian Sid GNU/Linux
Noyau : amd64 (à jour le vendredi)
(G)UI : Touhy
Inscription : 01-07-2014

Vim, espaces, tabulations et indentation.

Poulpe o/

(Oui, parce que le poulpe n'a que huit bras, donc il est obligé d'utiliser Vim plutôt qu'Emacs big_smile)


Troll à part, il y a un comportement de Vim qui me semble assez problématique, et, vu que ça fait plusieurs fois que j'essaye d'en parler et qu'à chaque fois ça a l'air assez difficile à suivre, je me suis dit qu'un petit sujet sur le forum aussi clair que possible aurait une petite chance d'aider.

Précisons que le point n'est pas d'alimenter l'éternel débat sur la question des espaces ou des tabulations, simplement de reconnaître que les deux existent et sont utilisées, et que donc, n'importe quel dev participant à plusieurs projets est susceptible de tomber, un jour où l'autre, sur un cas où les gens ont fait l'autre choix, et qu'on ne va probablement pas les faire changer d'avis. Or, tout le monde étant a priori d'accord sur le fait que mélanger les deux sera problématique, et qu'il vaut donc mieux chercher à les éviter.

Donc, si je me retrouve au milieu d'espaces, je veux utiliser des espaces, si je me retrouve au milieu de tabulations, je veux utiliser des tabulations, et « t'as qu'à juste bouder quand les gens ont fait d'autres choix » n'est pas une bonne réponse. On est d'accord ? big_smile

Si oui, prenons un Vim de base, avec un ~/.vimrc tout simple :

set list listchars=tab:→»
set autoindent


Rien de plus. La première ligne ne sert qu'à ce que le souci que j'essaye de mettre en lumière ne soit visuellement évident, mais on pourrait la retirer, ça ne changerait pas grand chose à ce que je vais essayer d'exposer ici. La seconde, en revanche, est celle qui pose problème.

Avec ce réglage de base, si on ouvre un fichier qui se trouve être indenté par des espaces, qu'on choisit une ligne indentée, et qu'on va à la ligne, à partir du moment où le nombre d'espaces à recopier depuis la ligne d'au dessus est supérieure ou égale à la taille d'une tabulation (8 par défaut, je sais que ça se règle mais ce n'est pas le propos ici) Vim va automatiquement convertir ces espaces en tabulation en recopiant l'indentation. Et va donc se mettre à coller des tabs au milieu d'espaces, ce qui n'est pas top.

Il existe un moyen simple de l'empêcher de faire ça, qui est de rajouter cette commande :

set expandtab


Ce faisant, Vim va tout faire pour éviter les tabulations : l'appui sur la touche concerné va insérer autant d'espaces à la place ; et quand on fera un saut de ligne, il recopiera les espaces proprement, sans rien y changer, et donc tout ira pour le mieux.

…du moins, tant qu'on ne manipule que des fichiers indentés par des espaces. Si en revanche, avec ce réglage, on ouvre un fichier qui contenait des tabulations, celles-ci seront bel et bien présentes… mais dès qu'on lui demandera d'ajouter une ligne dans ce fichier, Vim, comme on le lui a demandé, refusera d'y mettre des tabulations, et remplacera celles-ci par des espaces. Et donc, de nouveau, on se retrouvera à mélanger les deux, ce qui n'est toujours pas top.

On a donc a priori deux comportements possibles :
– Soit Vim s'entête à fiche des tabulations chaque fois qu'il le peut, peu importe qu'il y ait des espaces ou pas,
– Soit Vim refuse catégoriquement de fiche des tabulations, et mettra donc des espaces, peu importe qu'il y ait des tabulations ou pas.

Ce qui me semble d'autant plus problématique que Vim est à ma connaissance le seul éditeur à avoir ce comportement étrange : tous ceux à part lui qui gèrent l'auto-indentation se contentent de bêtement recopier ce qu'on trouve à la ligne d'au dessus sans chercher à remplacer les tabs par des espaces ou les espaces par des tabs, ce qui soit dit en passant est quand même sacrément plus simple, comme façon de faire.

Je n'ai trouvé, jusque là, que deux manières de régler le souci :
– Soit laisser cette conf' minimale en l'état, et aller manuellement taper « :set expandtab » chaque fois qu'on a besoin d'éditer un fichier qui se trouve être indenté par des espaces pour éviter que Vim y cause des soucis, ce qui est quand même un peu lourd,
– Soit recourir à des solutions du type « un fichier de conf' spécifique par projet/type de fichiers à éditer », ce qui ne me semble pas tellement plus satisfaisant, au sens où il s'agit de rajouter des tonnes de conf' spécifiques pour ajuster le comportement aberrant en fonction de la situation, donc de résoudre un problème de comportement trop complexe en ajoutant encore plus de complexité.

Vim est un logiciel plutôt cool par ailleurs et ça m'embêterait de le jeter juste pour ça ; mais n'empêche que dans pas mal de cas, je préfère ouvrir un autre éditeur juste pour un comportement de base qui ne marche pas sur la tête au niveau de l'indentation.

Pour avoir déjà abordé le sujet avec pas mal de monde, je suis conscient du fait qu'un certain nombre d'entre vous auront envie de réagir en disant que, comme eux n'utilisent exclusivement que des tabs ou que des espaces, le problème ne se pose pas pour eux. Sauf que ça ne me paraît pas spécialement aider.

Donc voilà, si vous avez une autre idée que ça, je veux bien smile

(P.S.: je sais qu'il existe également un « smartindent » un peu différent de l'« autoindent » dont je parle ici. Sauf erreur de ma part, ce dernier essaye d'être encore plus interventionniste en ajoutant ou retirant automatiquement un niveau d'indentation en fonction de ce qui précédait, mais sans rien changer au souci de fond. Ce n'est donc pas ce qui m'intéresse ici. D'ailleurs, d'une manière générale, chaque fois, jusque là, qu'un logiciel a essayé d'être intelligent à ma place, ça s'est plutôt mal passé, et c'est plus ou moins le cas ici.)

Hors ligne

#2 06-05-2020 19:21:14

Beta-Pictoris
Membre
Lieu : Angers
Distrib. : Buster
Inscription : 11-08-2015

Re : Vim, espaces, tabulations et indentation.

Tu peux demander à vim d'activer la directive "expandtab", en fonction du fichier que tu édites, en ajoutant une ligne (nommée modeline) au dit fichier (après le shebang par exemple) :

# vim: noexpandtab


Ou selon la version de vim :

# vim: set noexpandtab



Pour que ça fonctionne, tu dois aussi ajouter la directive suivante à ton vimrc :

set modeline

Dernière modification par Beta-Pictoris (06-05-2020 19:25:05)

Hors ligne

#3 06-05-2020 19:40:10

Elzen
Modérateur
Distrib. : Debian Sid GNU/Linux
Noyau : amd64 (à jour le vendredi)
(G)UI : Touhy
Inscription : 01-07-2014

Re : Vim, espaces, tabulations et indentation.

Par « en fonction du fichier que tu édites », tu veux bien dire soit entrer cette commande à la main quand j'ouvre un fichier qui en a besoin, soit avoir une configuration suffisamment compliquée pour qu'il charge ou pas des trucs selon le type de fichier ou le projet concerné ? Parce que si c'est ça, il me semble que c'est à peu près ce que j'indique dans le post comme étant les « solutions » que je connais et que je ne trouve pas glop…

Hors ligne

#4 06-05-2020 19:56:01

Beta-Pictoris
Membre
Lieu : Angers
Distrib. : Buster
Inscription : 11-08-2015

Re : Vim, espaces, tabulations et indentation.

Tu as juste à ajouter une ligne dans chaque fichier que tu édites.

Sur le wiki vim, il y a même un exemple de fonction, associée à un raccourci, pour ajouter cette ligne automatiquement: https://vim.fandom.com/wiki/Modeline_magic

Hors ligne

#5 06-05-2020 20:16:00

DarKou
Membre
Lieu : Bordeaux
Distrib. : Debian Buster
Noyau : stable de chez kernel.org
(G)UI : GNOME 3.30.2 / i3
Inscription : 06-04-2020
Site Web

Re : Vim, espaces, tabulations et indentation.

À titre perso le "Tu as juste à ajouter une ligne dans chaque fichier que tu édites." n'est pas envisageable.

Je bosse dans une boite de dev, chacun utilise l'IDE de son choix et pour chaque repo on a un fichier .prettierrc ou .editorconfig qui dicte les règles à appliquer sur le projet et ceux sans devoir modifier le moindre fichier du projet.

Rajouter une ligne en entête de chaque fichier n'est pas envisageable car :
- un projet que contenir plusieurs centaines de fichiers => donc rajouter 100 fois la ligne...
- un collègue créé le fichier mais ne mets pas la ligne (car il utilise un autre IDE), quand tu vas ouvrir ce fameux fichier il faudra qu'avant de faire quoi que ce soit tu rajoutes cette fameuse ligne...

Et du coup je viens de voir qu'il existe le plugin editorconfig pour vim : https://github.com/editorconfig/editorconfig-vim
Plus d'info sur editorconfig : https://editorconfig.org/

Dernière modification par DarKou (06-05-2020 20:16:21)

Hors ligne

#6 06-05-2020 20:29:28

vv222
Administrateur
Lieu : Bretagne
Distrib. : GNU/Linux Debian « Sid »
Noyau : Linux ≥ 5.7 (amd64)
(G)UI : Openbox
Inscription : 18-11-2013
Site Web

Re : Vim, espaces, tabulations et indentation.

DarKou a écrit :

Et du coup je viens de voir qu'il existe le plugin editorconfig pour vim : https://github.com/editorconfig/editorconfig-vim
Plus d'info sur editorconfig : https://editorconfig.org/


Greffon qui a le bon goût d’être fourni via les dépôts Debian : vim-editorconfig
Pour du boulot collaboratif, c’est ce que j’ai trouvé de mieux jusqu’ici.


Jouer sous Debian ? Facile !

Hors ligne

#7 06-05-2020 20:30:11

Beta-Pictoris
Membre
Lieu : Angers
Distrib. : Buster
Inscription : 11-08-2015

Re : Vim, espaces, tabulations et indentation.

Oui, mais quand il y a des tabulations dans un fichier, c'est la même chose pour tout le monde. smile

Cela tombe bien car le modeline permet d'adapter la configuration vim en fonction du fichier, pas en fonction de l'utilisateur.

Après, il y a une autre solution: Emacs remplace toutes les tabulations par des espaces. smile

Dernière modification par Beta-Pictoris (06-05-2020 20:34:43)

Hors ligne

#8 06-05-2020 21:04:12

Cauryl
Membre
Distrib. : Debian Buster
(G)UI : Xfce
Inscription : 12-02-2020

Re : Vim, espaces, tabulations et indentation.

Poussé par Elzen, voici ce que j'expliquais sur IRC wink :

La commande Vim autocmd est très puissante et permet de définir n'importe quel comportement pour n'importe quelle condition.

Dans le cas présent, pour définir l'indentation d'un projet :

autocmd BufRead,BufNewFile ~/MonSuperProjet/* set tabstop=2 shiftwidth=2 expandtab



La version multi-lignes propre :

augroup MonSuperProjet
  autocmd!
  autocmd BufRead,BufNewFile ~/MonSuperProjet/* set tabstop=2
  autocmd BufRead,BufNewFile ~/MonSuperProjet/* set shiftwidth=2
  autocmd BufRead,BufNewFile ~/MonSuperProjet/* set expandtab
augroup END

Dernière modification par Cauryl (06-05-2020 21:05:20)

Hors ligne

#9 06-05-2020 21:12:13

Elzen
Modérateur
Distrib. : Debian Sid GNU/Linux
Noyau : amd64 (à jour le vendredi)
(G)UI : Touhy
Inscription : 01-07-2014

Re : Vim, espaces, tabulations et indentation.

On a dit pas d'Emacs, j'ai poulpé tongue

Je rejoins DarKou sur le fait qu'avoir ce genre de directives directement dans le fichier à éditer me semble être la pire des trois solutions. Ou disons que, ça me semble une possible bonne idée en complément d'un truc du style editorconfig (un fichier global à chaque projet collaboratif, puis pour les quelques fichiers non-partagés qui traînent sur le disque, on prend ça en plus), mais que je restreindrais son usage aux options de config pour lesquelles il n'existe pas un comportement simple et évident à adopter.

Pour régler la taille d'une tabulation, par exemple (ou le nombre d'espaces correspondant si on est en mode espaces), il n'existe pas de comportement évident : ça dépend des préférences de chacun, et ce n'est pas à l'éditeur de choisir pour toi. Donc, à supposer qu'on n'utilise pas le même réglage dans tous les fichiers, ça paraît pertinent qu'il y ait une configuration spécifique partout où il y en a besoin.

Mais, pour le cas bien précis de l'auto-indentation, il existe bel et bien un comportement totalement évident et qui marche dans tous les cas de figure (et qui est même beaucoup plus simple à mettre en œuvre que ce que fait Vim avec son « autoindent »), qui est de simplement reprendre tous les caractères blancs de la ligne d'au-dessus et les recopier à l'identique, sans chercher à aller les modifier. Et donc ça me paraît totalement aberrant de devoir écrire de la conf' spécifique, où qu'elle soit placée, juste pour forcer Vim à ce que le résultat de sa tambouille interne bizarre donne le même résultat que ce qu'il aurait pu faire en se comportant de la façon la plus simple possible neutral

Edit : en fait, ce que j'ai du mal à voir à la base, c'est dans quel cas ça a pu sembler pertinent aux gens qui ont développé Vim de se dire « la ligne d'au dessus est indentée avec [une tabulation/quatre espaces/whaterver], faisons remplacer ça par autre chose pour débuter la nouvelle ligne ». À la limite, je comprends le comportement quand on a fait « :set expandtab » (on lui dit de ne pas mettre du tout de tabulation, il ne met pas du tout de tabulation, même si ça donne un truc débile, ça se tient). Mais la décision, sans consigne spécifique à ce niveau, de remplacer X espaces par le nombre correspondant de tabulations, je n'arrive juste pas à visualiser comment quelqu'un a pu se figurer que ça pouvait être une bonne idée…

Dernière modification par Elzen (06-05-2020 21:22:25)

Hors ligne

#10 06-05-2020 21:54:18

Beta-Pictoris
Membre
Lieu : Angers
Distrib. : Buster
Inscription : 11-08-2015

Re : Vim, espaces, tabulations et indentation.

Si tu ré indentes toutes les lignes du fichier (ggVG=) [édit modération: ou simplement gg=G], tu supprimes ou tu remets des tabulations en fonction de l'état de la variable expandtab.
Tu pourrais créer un raccourci qui fait ça.

Hors ligne

#11 07-05-2020 13:06:39

Elzen
Modérateur
Distrib. : Debian Sid GNU/Linux
Noyau : amd64 (à jour le vendredi)
(G)UI : Touhy
Inscription : 01-07-2014

Re : Vim, espaces, tabulations et indentation.

Comment dire… ?

Oui, ce que tu proposes pourrait être une bonne piste si on posait comme hypothèse de départ que la façon dont le fichier est indenté est mauvaise et qu'il faut la rectifier (et à condition, bien sûr, d'avoir toute la tonne de conf' spécifique dont on parlait plus haut pour décider si on :set expandtab ou pas). Sauf que mon hypothèse de départ, personnellement, c'était plutôt que l'encodage du fichier est comme il est et que ce que je voudrais, c'est que Vim s'y « adapte » (avec des grosses pincettes sur ce terme vu que s'« adapter » serait ici adopter un comportement largement plus simple que celui choisi par les devs de Vim) plutôt que de devoir adapter le fichier aux étrangetés de Vim.

En fait (et sans vouloir vexer personne, hein), il y a un truc que je trouve assez fascinant avec cette histoire, c'est que, chaque fois que j'en parle à un utilisateur de Vim plus ou moins avancé, « ah, oui, tiens, ce comportement de Vim est bizarre » a l'air d'être une réponse qui a énormément de mal à lui venir en tête, par contre il déborde toujours d'idées pour m'expliquer comment je pourrais modifier absolument tout le reste de mon système et de ma façon de bosser pour faire en fonction de ce comportement chelou.

…en fait, ça me rappelle assez fortement l'époque où, quand tu lançais le navigateur Opera sous KDE, tu avais droit à une petite pop-up qui s'ouvrait pour te dire que « attention, nous avons détecté que vous utilisiez KDE : certains des raccourcis clavier d'Opera ne vont pas fonctionner parce que KDE les a réservés. Mais pas de panique, vous pouvez aller modifier la configuration de KDE là-bas. » tongue

Hors ligne

#12 07-05-2020 13:56:21

vv222
Administrateur
Lieu : Bretagne
Distrib. : GNU/Linux Debian « Sid »
Noyau : Linux ≥ 5.7 (amd64)
(G)UI : Openbox
Inscription : 18-11-2013
Site Web

Re : Vim, espaces, tabulations et indentation.

De ce que je comprends de cet extrait de documentation : Vim documentation: options - autoindent, l’option "autoindent" devrait faire exactement ce que tu cherches :

Copy indent from current line when starting a new line (typing <CR>
in Insert mode or when using the "o" or "O" command).  If you do not
type anything on the new line except <BS> or CTRL-D and then type
<Esc>, CTRL-O or <CR>, the indent is deleted again.  Moving the cursor
to another line has the same effect, unless the 'I' flag is included
in 'cpoptions'.
When autoindent is on, formatting (with the "gq" command or when you
reach 'textwidth' in Insert mode) uses the indentation of the first
line.
When 'smartindent' or 'cindent' is on the indent is changed in
a different way.
The 'autoindent' option is reset when the 'paste' option is set.
{small difference from Vi: After the indent is deleted when typing
<Esc> or <CR>, the cursor position when moving up or down is after the
deleted indent; Vi puts the cursor somewhere in the deleted indent}.



Si tu n’as pas une autre option en train d’interférer, comme par exemple "smartindent" ou "filetype plugin indent on", mais que "autoindent" n’active pas ce comportement pour autant, il s’agit possiblement d’un bug.


Jouer sous Debian ? Facile !

Hors ligne

#13 07-05-2020 16:08:13

Elzen
Modérateur
Distrib. : Debian Sid GNU/Linux
Noyau : amd64 (à jour le vendredi)
(G)UI : Touhy
Inscription : 01-07-2014

Re : Vim, espaces, tabulations et indentation.

C'est aussi ce que je comprends en lisant l'explication. D'un autre côté, c'est aussi ce que je comprends par le concept d'« auto-indentation » d'une manière générale ^^'

Comme je l'ai dit, le souci que je soulève ici semble avoir lieu juste avec la conf' minimale sus-mentionnée (je n'ai aucun plug-in ni rien de ce genre), et pour le coup, ça n'a pas l'air spécifique à ma config comme quelques autres de mes bugs chelous, vu que je crois bien avoir vu ça sur tous les Vim que j'ai essayé.

J'imagine qu'il faudrait que je fasse un rapport de bug, mais vu la difficulté que j'ai à faire comprendre le souci en français à des gens dont c'est la langue natale, je n'ose imaginer les  difficultés que ça va entraîner en anglais ^^'

Hors ligne

#14 13-09-2020 16:37:18

Laërte
Membre
Lieu : Bretagne
Distrib. : Archlinux (parce que voilà)
Noyau : Linux 5.7.2-arch1-1 (mais ça change souvent)
(G)UI : sway
Inscription : 01-09-2013

Re : Vim, espaces, tabulations et indentation.

Je pense que vous comprenez mal la documentation de «autoindent». Telle que je la pige, «l’indentation de la première ligne» fait référence à la ligne en cours d’édition, quand soudainement on dépasses _textwidth_ et que vim coupe gentiment la ligne parce que les lignes longues c’est le mal. Dans ce cas, la seconde ligne (celle sur laquelle se poursuit l’édition) est indentée similairement à la ligne précédente.

Quand à «copier l’indentationde la ligne actuelle lors de la création d’une nouvelle ligne», il ne parle pas en terme de contenue de l’indentation (tabulations ou espaces) mais de longueur (ce qu’il fait à la perfection).

Hors ligne

Pied de page des forums