Home sweet Home en 3 étapes

Introduction

Je suis un utilisateur Linux depuis plus de 10 ans. Je fis mes premiers pas avec une distribution Slackware, à une époque ou les gestionnaires de fenêtres étaient encore hésitants. Après un retour sous Windows XP pendant 2 ans, je changeai a nouveau pour Fedora Core (devenu Fedora), puis Mandriva. Enfin, je passai à Ubuntu depuis mon arrivée au Japon, que j'utilise toujours à ce jour. Malgré multiple essais, je n'ai jamais vraiment réussi à utiliser Windows ou Mac OS pour le développement.

Que ce soit dans le cadre privé ou professionnel, l'installation est toujours l'étape laborieuse et répétitive; réinstallation des mêmes logiciels, réédition des mêmes fichiers de configuration sous /home/<user> ... Le besoin de centralisation se faisant sentir de plus en plus, la sortie du service de cloud storage Canonical, "Ubuntu One", fut l'occasion pour moi de m'atteler à cette tâche. Je vais donc présenter ici la façon dont je configure une installation tout fraîche en 3 étapes.

Je maintiens un répertoire home-env à la racine de mon compte Ubuntu One en dessous duquel je place tous les fichiers nécessaires.

I ) Installation de vim et des plugins

D'une manière générale, je suis partisan du minimalisme, que ce soit mon gestionnaire de fenêtre (bureau vierge, nombre d'icones de raccourcis réduit à 3-4 applications) ou les langages de programmation (Scheme & Python); il en va de même pour le choix de l'IDE. Excepté le développement pour Android, j'utilise exclusivement vim. Il est donc tout naturel que l'une des premières commandes soit :

$ sudo apt-get install vim

J'installe également certains plugins vi sur toutes mes machines servant au développement. Tous les plugins sont disponibles sur internet très facilement, mais pour ceux que j'installe systématiquement, je les ai sauvegardés sur Ubuntu One sous home-env, en gardant la même hiérarchie système :

$ home-env/vim/plugin , home-env/vim/doc , home-env/vim/after/ftplugin

Les plugins que je garde toujours sous le coude sont les suivants :

  • fugitive [1] : intégration de git dans vim
  • camelcasemotion [2] : Support de commandes permettant d'effacer/changer une partie du mot écrit en camel case, utilisant la majuscule comme séparateur.
  • pydiction [3] : auto completion pour Python.

II ) Création des fichiers de configuration vi , git et bash

Ja garde chaque fichier de configuration sous un nom différent du nom système, sous la forme conf-file.<username> (sans le [.] au début du fichier). E.g., .vimrc devient vimrc.<username>

Selon le type de fichier de conf., je rajoute une commande permettant d'exécuter les .<username> dans le fichier de conf. correspondant :

.vimrc

$ echo "source ~/Ubuntu\ One/home-env/vimrc.<username>" >> .vimrc

.bashrc

$ echo ". ~/Ubuntu\ One/home-env/bashrc.<username>" >> ~/.bashrc

.gitconfig

La version actuelle de git (1.7.9.x sur mon Ubuntu 12.04) ne permet malheureusement pas l'inclusion de fichiers de configuration externes via une syntaxe particulière. La solution que j'utilise actuellement est de créer un lien symbolique :

$ ln -s ~/Ubuntu\ One/home-env/gitconfig.<username> ~/.gitconfig

Note: 1.7.10 [4] devrait permettre ce type d'inclusion externe avec une définition du type :

[include]
    path = <path>/gitconfig.<username>

En procédant de cette manière, lorsque j'apporte une modification dans un fichier de configuration sur une machine, les changements sont automatiquement uploadés, puis mis à jour sur mes autres machines.

Voici le contenu de mes fichiers de configuration :

vimrc.<username>

syntax on
set sm
set nu
set sc
set is
set hlsearch
set nosi
set bs=2
set ts=4
set winminheight=0

let mapleader = ","
filetype plugin on

imap <Nul> <Space>
map  <Nul> <Nop>
vmap <Nul> <Nop>
cmap <Nul> <Nop>
nmap <Nul> <Nop>

highlight Error ctermbg=red
highlight LeadingTabs ctermfg=lightgrey ctermbg=darkgrey
highlight TrailingWS ctermbg=lightgrey ctermfg=darkgrey

autocmd BufNewFile,BufRead *.sql set filetype=mysql
autocmd BufNewFile,BufRead *.html set filetype=php
autocmd FileType php set et ts=4 sw=4
autocmd FileType python set setlocal expandtab tabstop=4 shiftwidth=4
autocmd BufNewFile,BufRead * let m=matchadd('LeadingTabs', '^\t\+', -1)
autocmd BufNewFile,BufRead * let m2=matchadd('Error', '\%>120v', -1)
autocmd InsertEnter * match TrailingWS /\s\+\%#\@<!$/
autocmd InsertLeave * match TrailingWS /\s\+$/

map <silent> W <Plug>CamelCaseMotion_w
map <silent> B <Plug>CamelCaseMotion_b
map <silent> E <Plug>CamelCaseMotion_e

"clearing highlighted search
nmap <silent> <leader>/ :nohlsearch<CR>

" visual shifting (does not exit Visual mode)
vnoremap < <gv
vnoremap > >gv

let g:pydiction_location = '~/.vim/after/ftplugin/.dict/complete-dict'
let g:pydiction_menu_height = 10

" Opening file only
match TrailingWS /\s\+$/

" backup to /tmp
set backup
set backupdir=~/tmp/vim/bak
set backupskip=~/tmp/vim/bak/*
set directory=~/tmp/vim/swap
set writebackup

set laststatus=2

" Broken down into easily includeable segments
set statusline=%<%f\   " Filename
set statusline+=%w%h%m%r " Options
set statusline+=%{fugitive#statusline()} "  Git Hotness
set statusline+=\ [%{&ff}/%Y]            " filetype
set statusline+=\ [%{getcwd()}]          " current dir
set statusline+=\ [A=\%03.3b/H=\%02.2B] " ASCII / Hexadecimal value of char
set statusline+=%=%-14.(%l,%c%V%)\ %p%%  " Right aligned file nav info

Quelques détails :

  • Je surbrille en gris les tabulations. Que ce soit PHP, Python ou n'importe quel autre langage, j'utilise toujours l'espace pour l'indentation. Cela me permet de déceler les endroits où mon code ne respecte pas cette convention. Cela permet accessoirement de détecter les lignes vides composées uniquement de tabulations.

      highlight LeadingTabs ctermfg=lightgrey ctermbg=darkgrey
      autocmd BufNewFile,BufRead * let m=matchadd('LeadingTabs', '^\t\+', -1)
    
  • Je colore en rouge toute ligne dépassant 120 caractères (j'avais mis 80 jusqu'à peu mais je me suis dit qu'on n'était plus en 1970). Bien qu'on ne soit plus à l'époque des cartes perforées, origine de la limite à 80 colonnes (et accessoirement une contrainte forte en Cobol), j'estime qu'il est préférable de limiter la longueur de chaque ligne de code afin de le garder lisible. Au pire, je divise le code en plusieurs lignes. Voici la commande associée :

      highlight Error ctermbg=red
      autocmd BufNewFile,BufRead * let m2=matchadd('Error', '\%>120v', -1)
    
  • Je surbrille en gris les espaces (ou tabulations) en fin de ligne; ceci est une raison purement esthétique et aussi pour garder une cohérence dans le code source. Je n'active la coloration qu'en sortant du mode édition ou après un retour à la ligne pour éviter que la subrillance aparaisse après chaque insertion d'un espace dans une ligne en cours d'édition :

      highlight TrailingWS ctermbg=lightgrey ctermfg=darkgrey
      autocmd InsertEnter * match TrailingWS /\s\+\%#\@<!$/
      autocmd InsertLeave * match TrailingWS /\s\+$/
    

Pour illustrer le tout, voici un échantillon d'un programme Python que j'ai délibérément modifié :

vim.png

  • La recherche d'un texte sous vim est très facile et puissante, mais en utilisant l'option hl on (highlightsearch on), les résultats de recherche sont surlignés en jaune, qui reste active jusqu'à la recherche suivante, ce qui peut devenir gênant. Avant, j'annulais la recherche en cours avec la commande plutôt maladroite

      /\\\\\\\\\\\\\\\\\\
    

    Ce qui, au lieu d'annuler le surlignage, effectue une nouvelle recherche sur le texte \\\\\\\\\, qui donc indirectement supprime le surlignage. J'ai récemment ajouté la macro suivante :

      let mapleader = ","
      nmap <silent> <leader>/ :nohlsearch<CR>
    

    Ce qui me permet dorénavant de réellement supprimer le surlignage automatique en utilisant la commande ",/", ce qui est plus propre et rapide.

  • Par défaut, vim crée un fichier .swap dans le même répertoire que le fichier en cours d'édition. En cas de plantage de la console, ou pour diverses raisons, il arrive que le fichier swap ne soit pas effacé ce qui génère un warning lors de la réouverture du fichier sous vim. Tracer ces fichiers .swap est fastidieux; de plus, ils encombrent inutilement les répertoires projets. Je préfère une centralisation :

      set backup
      set backupdir=~/tmp/vim/bak
      set backupskip=~/tmp/vim/bak/*
      set directory=~/tmp/vim/swap
      set writebackup
    

    J'utilise un répertoire tmp local a home afin de ne pas créer de conflits avec un autre utilisateur. Plus embêtant (mais utile) sont les fichiers de backup que vim crée, avecun tilde (~) rajouté à la fin du nom de fichier (e.g. foofoo~, foo.phpfoo.php~). Embêtant car ces fichiers se retrouvent parfois malencontreusement archivés sous git ou svn, n'étant pas cachés par Linux faute de "." en début de fichier. Je ne veux pas désactiver la création des fichiers de backup, c'est pourquoi ces derniers sont aussi centralisés a l'instar des fichiers swap.

bashrc.<username>

GIT_PS1_SHOWDIRTYSTATE=true
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[31m\]$(__git_ps1)\[\033[00m\]\$ '

Ces deux commandes permettent simplement d'activer l'intégration de git au sein de la console. Le prompt affiche la branche active du projet, et son état (clean, dirty...) si le répertoire actuel pwd est inclus dans un repository git.

gitconfig.<username>

[color]
  branch = auto
  diff = auto
  status = auto

[color "branch"]
  current = yellow reverse
  local = yellow
  remote = green

[color "diff"]
  meta = yellow bold
  frag = magenta bold
  old = red bold
  new = green bold

[color "status"]
  added = yellow
  changed = green
  untracked = cyan

[alias]
  ci = commit
  st = status -sb
  co = checkout
  b = branch
  l = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative --decorate
  lc = log ORIG_HEAD.. --stat --no-merges
  undo = reset --hard

[core]
  editor = vim

En grosse partie, configure les couleurs lors de l'affichage dans la console, et les alias pour les commandes fréquemment utilisées. Pour git status et git log -alias st et l- je privilégie un affichage compact à celui par défaut :

$ git st
## dev
A  foo/src/main.py
 M foo/src/utils.py
?? foo/src/libs/rfc3339.py
?? bar/
^^__ Modifié mais non ajouté au stage
|___ Ajouté au stage (ce qui sera envoyé au prochain commit)

Affichage proche de celui de svn, à la sauce git.

Pour git log, voici un extrait d'un projet Android utilisant git en interne, et git-svn pour l'intégration avec svn :

$ git l
(...)
| *   0774882 - Merge branch 'build_03_01' of origin.local:myproject into build_03_01 (4 months ago) <Y M>
| |\
| | * af2188f - Updated demo samples (4 months ago) <Y M>
| | * 116ef0e - Fixed layout of sound tab header (4 months ago) <Y M>
| | * 317856f - Keep screen on (4 months ago) <Y M>
| | * 5fefbb8 - (PROTO_02_14, origin/dev, dev) Added ant build properties file Fixed fast tab switching issue! (try..catch) (4 months ago) <Y M>
| | * 02ee652 - Put car overlay over spot/traffic overlays (4 months ago) <Y M>
* | | f012bad - Updated R.java (4 months ago) <Y M>
* | | 7e63ae9 - Updated demo samples (4 months ago) <Y M>
* | | 91087cb - Fixed layout of sound tab header (4 months ago) <Y M>
* | | e1c2f8b - Focus on first spot/traffic during RadioAutomaton instead of Next Removed commented code from BottombannerAreaFragment (4 months ago) <Y M>
* | | bc2ef04 - Traffic level labels array resource used where needed. => Needed custom Application to allow Application Resources access from TrafficInfo (4 months ago)
* | | 8fb3e51 - Fixed merge (4 months ago) <Y M>
* | | 2fc921a - Tried to improve the fragment tab switching. Removing dependency on executePendingCommits(). Added delayed operations (4 months ago) <Y M>
|/ /
(...)

Cet affichage en plus d'être beaucoup plus compact que celui par défaut, rajoute en plus des informations visuelles sur les différents merge qui ont eu lieu et les branches qui en résultent.

III ) Import de mes clés GPG

J'utilise deux jeux de clés PGP : pour usage personnel et usage professionel. Note : Je ne met PAS mes clés sur mon compte UOne pour des raisons évidentes de sécurité!

J'utilise ma clé PGP pour encrypter les informations de connexion sur les divers serveurs utilisés pour les projets. Il s'agit d'un simple fichier texte qui est encrypté en utilisant l'option ascii-armored :

$ gpg --recipient xxx@yyy -a --encrypt server_info

Un fichier server_info.asc contenant le contenu encrypté. j'efface ensuite le fichier original :

$ rm server_info

Et je peux vérifier le contenu du fichier server_info.asc en fournissant mon passphrase :

$ gpg --decrypt -a server_info.asc

Afin de pouvoir décrypter les fichiers précédemment encryptés en cas de nouvelle installation, j'exporte ma clé privée GPG avant de réinstaller :

$ gpg --export-secret-key -a > my_private_key

Puis je la réimporte :

$ gpg --import my_private_key

J'utilise deux subkeys : une pour le cryptage, une pour la signature.

Au passage, idéalement j'aimerais avoir ma clé publique inscrite quelque part sur ma carte de visite :

Fingerprint : 0D67 DA34 9989 2211 7EE0  8FFF A7BA 11BA 7A0E A2B8

Conclusion

Je n'inclus pas dans ces étapes l'installation des logiciels restants (php, python, mysql, apache, nginx ...), mais la configuration nécessaire afin de retrouver son petit chez soi en lançant le terminal est facilement automatisable et par conséquent mérite de l'être.

A propos du blogway 777

Cet article fait partie du blog-relai instauré par Kayac pour l'événement "777" relatif au festival Tanabata (七夕). D'ici le 7 Juillet, nous vous invitons à suivre les 4 blogs (ingénieur, designer, directeur, ingénieur front-end), mis à jour quotidiennement sous la forme d'un relai. Le thème est "Les 3 outils sacrés de la création" (San'shu no shin'gi - 三種の神器).

Pour le prochain article, je passe la main au blog designer.