<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet title="XSL formatting" type="text/xsl" href="http://blog.mymind.fr/feed/rss2/xslt" ?><rss version="2.0"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
  <title>Mind... - Tag - zsh</title>
  <link>http://blog.mymind.fr/</link>
  <atom:link href="http://blog.mymind.fr/feed/tag/zsh/rss2" rel="self" type="application/rss+xml"/>
  <description></description>
  <language>fr</language>
  <pubDate>Thu, 01 Dec 2011 21:43:54 +0100</pubDate>
  <copyright>© 2007-2008 Florent Bruneau</copyright>
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  <generator>Dotclear</generator>
  
    
  <item>
    <title>Encodage et terminal</title>
    <link>http://blog.mymind.fr/post/2008/03/02/Encodage-et-terminal</link>
    <guid isPermaLink="false">urn:md5:c2d036586a265e02fe63ee0dfeeeb17a</guid>
    <pubDate>Sun, 02 Mar 2008 11:57:00 +0100</pubDate>
    <dc:creator>Florent Bruneau</dc:creator>
        <category>Général</category>
        <category>encodage</category><category>shell</category><category>terminal</category><category>zsh</category>    
    <description>&lt;p&gt;Beaucoup de personnes avec qui je discute sur IRC ont des problèmes avec l'encodage de leur terminal, de leur shell, de leur irssi, ou de tout autre logiciel en &quot;ligne de commande&quot;. Comme j'en ai un peu marre d'expliquer la même chose toutes les semaines, voici une petite mise au point sur les réglages à faire pour travailler efficacement en ligne de commande.&lt;/p&gt;    &lt;h3&gt;Introduction&lt;/h3&gt;


&lt;p&gt;Le point le plus important à mémoriser est que pour avoir une console avec un encodage spécifique il faut que plusieurs couches de logiciels utilisent le même encodage. Prenons le cas simple où nous avons un shell dans un terminal.&lt;/p&gt;


&lt;p&gt;Le terminal est un logiciel qui ne fait que convertir les entrées de l'utilisateur vers des entrées compréhensibles par le logiciel qu'il fait tourner, et qui interprète la sortie de ce logiciel pour qu'elle soit lisible par l'utilisateur. Donc pour que le terminal affiche correctement ce qu'indique le shell, il faut qu'il utilise le même encodage que celui-ci. Si par exemple mon shell écrit de l'UTF-8 alors que mon terminal attend du latin1, les caractères multi-octets de l'UTF-8 seront mal interprétés et afficheront un caractère par octet. Ainsi un &quot;é&quot; en utf8 s'affiche comme un &quot;Ã©&quot; en latin1.&lt;/p&gt;


&lt;p&gt;Pour l'entrée de l'utilisateur, c'est la même chose. Si mon terminal est en latin1 et mon shell en utf8, si j'entre un &quot;é&quot; dans mon terminal, celui-ci sera passé à mon terminal comme un seul octet (de valeur 0xE9). Or mon shell attend de l'utf8 et lorsqu'il reçoit un 0xE9, il considère que je viens d'entrer un octet d'un caractère multi-octets... les prochains caractères que j'entrerais seront donc ajoutés à mon 0xE9 jusqu'à ce que mon shell considère que j'ai entré un caractère... assez embêtant.&lt;/p&gt;


&lt;p&gt;Il faut donc faire extrêmement attention à choisir un encodage unique compatible avec son shell et son terminal (et les logiciels qu'on compte utiliser).&lt;/p&gt;



&lt;h3&gt;Terminal&lt;/h3&gt;


&lt;p&gt;Le réglage du terminal dépend exclusivement du logiciel en question. Certains terminaux permettent de choisir son encodage, d'autres non. Cela peut donc être un bon critère pour choisir son logiciel. Pour utiliser l'UTF-8, vous pouvez prendre Konsole, urxvt, le Terminal de Mac OS X...&lt;/p&gt;



&lt;h3&gt;Shell&lt;/h3&gt;


&lt;p&gt;Le réglage du shell se fait par des variables d'environnement qu'on appelle couramment les &quot;locales&quot;. Le réglage courant est accessible en tapant &quot;locale&quot; dans le shell. Un certain nombre de variables sont concernées&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;gestion de la langue du shell (et des programmes liés)&lt;/li&gt;
&lt;li&gt;gestion des formats (dates, monnaies, virgules...)&lt;/li&gt;
&lt;li&gt;LC_ALL est un &quot;fallback&quot; (l'encodage par défaut si aucun autre n'a été défini pour une variable donnée).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Chaque variable est de la forme xx_YY.ZZ. xx_YY défini la zone géographique et la langue (fr_FR pour le français, en_US pour l'anglais-US). ZZ défini l'encodage. Il est important que toutes les variables utilisent le même encodage (mais elles peuvent avoir des langues différentes). Pour faire de l'UTF-8 pur, un bon choix est d'exporter LC_ALL=&quot;en_US.UTF-8&quot; dans la configuration du shell (ou fr_FR.UTF-8 pour ceux qui veulent un shell en français).&lt;/p&gt;


&lt;p&gt;Il faut par contre faire attention, l'UTF-8 n'est pas supporté par tous les shells (à partir de 4.3 pour zsh par exemple).&lt;/p&gt;



&lt;h3&gt;Irssi&lt;/h3&gt;


&lt;p&gt;Pour irssi, il y a un point supplémentaire à prendre en compte&amp;nbsp;: l'encodage du réseau. Ainsi si j'ai un channel en latin1 à afficher en utf8 (et sur lequel je veux poster). Il faut donc que irssi fasse de transcodage à la volée... et bien sûr il faut lui dire ce qu'il faut faire.&lt;/p&gt;


&lt;p&gt;Tout d'abord il faut lui indiquer l'encodage du terminal. Pour ceci il y a la variable term_charset&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
settings = {
  &amp;quot;fe-common/core&amp;quot; = {
    term_charset = &amp;quot;UTF-8&amp;quot;;
  };
};
&lt;/pre&gt;


&lt;p&gt;Ensuite, il faut indiquer pour chaque réseau (ou channel) l'encodage du réseau. Ce n'est en fait nécessaire que si l'encodage est différent de celui du terminal, mais ça ne coûte rien de le spécifier pour chaque réseau. Ainsi je suis sur RezoSup (qui est en latin1) et sur FreeNode (qui est en utf8), il me suffit d'ajouter&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
settings = {
  core = {
    recode = &amp;quot;yes&amp;quot;;
  };
};
conversions = { 
  FreeNode = &amp;quot;UTF-8&amp;quot;;
  Rezosup = &amp;quot;ISO-8859-1&amp;quot;;
};
&lt;/pre&gt;


&lt;p&gt;Les entrées &quot;FreeNode&quot; et &quot;Rezosup&quot; doivent reprendre le nom du chatnet donné dans la section &quot;servers&quot; de la configuration. Pour spécifier l'encodage spécifique à un channel, il suffit de mettre &lt;code&gt;&quot;Chatnet/#channel&quot; = &quot;encoding&quot;;&lt;/code&gt;&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.mymind.fr/post/2008/03/02/Encodage-et-terminal#comment-form</comments>
      <wfw:comment>http://blog.mymind.fr/post/2008/03/02/Encodage-et-terminal#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.mymind.fr/feed/atom/comments/38</wfw:commentRss>
      </item>
    
  <item>
    <title>Compter les fichiers</title>
    <link>http://blog.mymind.fr/post/2007/08/30/Compter-les-fichiers</link>
    <guid isPermaLink="false">urn:md5:a4d72e31c767c980a39751dea09efb0a</guid>
    <pubDate>Thu, 30 Aug 2007 23:12:00 +0200</pubDate>
    <dc:creator>Florent Bruneau</dc:creator>
        <category>GeekTime</category>
        <category>Devel</category><category>pratique</category><category>zsh</category>    
    <description>&lt;p&gt;C'est un peu la suite de mon post &quot;Outils pratiques&quot; où je donnais deux scripts permettant de rendre les commandes SVN plus conviviales. Encore une fois, je réinvente sans doute la roue (des outils équivalents doivent déjà exister... sans doute en mieux), mais je pense que chercher ce genre d'outils sur internet m'aurait pris plus de temps que ce qu'il m'a fallu pour le développer.&lt;/p&gt;


&lt;p&gt;En ce moment je manipule des fichiers, beaucoup de fichiers (et même, beaucoup de gros fichiers), que j'ouvre, rouvre, et ferme et puis referme. Et à force d'ouvrir, on oublie parfois de refermer, et là, c'est comme une fuite de mémoire, sauf que le nombre limite de fichiers ouverts est beaucoup plus rapidement atteinte que la limite de mémoire... dans la configuration de base sur un linux, un programme n'a le droit qu'à 1024 descripteurs de fichiers. D'où mon problème&amp;nbsp;: comment traquer les &quot;file-handle leaks&quot;&amp;nbsp;?&lt;/p&gt;    &lt;p&gt;Pour le faire, je me suis fait rapidement un petit script qui permet d'analyser les données issues d'un &lt;code&gt;strace&lt;/code&gt;. &lt;code&gt;strace&lt;/code&gt; est, pour ceux qui ne le savent pas, un programme très pratique qui permet de lister les appels systèmes. Dans mon cas présents, surveiller les ouvertures fermetures de fichiers revient à traquer les commandes &lt;code&gt;open&lt;/code&gt; (ouverture d'un fichier), et les commandes &lt;code&gt;close&lt;/code&gt;. Donc, je récupère simplement la liste des appels à &lt;code&gt;open&lt;/code&gt; et &lt;code&gt;close&lt;/code&gt;&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
[bash]
strace -f -e trace=open,close mon programme 2&amp;gt; /quelque/part
&lt;/pre&gt;


&lt;p&gt;Et ainsi, le fichier &lt;code&gt;/quelque/part&lt;/code&gt; contient la liste complète des appels à &lt;code&gt;open&lt;/code&gt; et &lt;code&gt;close&lt;/code&gt; effectués par mon programme (et ses processus fils). Il ne reste plus alors qu'à analyser le contenu de &lt;code&gt;/quelque/part&lt;/code&gt;. Pour ceci, il suffit de peu de lignes de code (en perl pour ma part, mais d'autres auraient fait la même chose en shell, python... ou n'importe quel langage de scripting)&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
[perl]
#!/usr/bin/perl 
 
my %files; 
my %modes; 
my %lines; 
 
my $lineNb = 0; 
my $maxOpened = 0; 
my $currentOpened = 0; 
my $totalOpened = 0; 
 
for $line (&amp;lt;STDIN&amp;gt;) { 
  if ($line =~ /open\\(&amp;quot;([^&amp;quot;&amp;quot;]+)&amp;quot;, ([^\\)]+)\\)\\s*=\\s*(\\d+)/) { 
    $files{$3} = $1; 
    $modes{$3} = $2; 
    $lines{$3} = $lineNb; 
    $totalOpened++; 
    $currentOpened++; 
    if ($currentOpened &amp;gt; $maxOpened) { 
      $maxOpened = $currentOpened; 
    } 
  } 
  if ($line =~ /close\\((\\d+)\\)/ &amp;amp;&amp;amp; $files{$1} ne '') { 
    $files{$1} = ''; 
    $currentOpened--; 
  } 
  $lineNb++; 
} 
 
print &amp;quot;$totalOpened files opened, max. $maxOpened at the same time
&amp;quot;; 
print &amp;quot;$currentOpened files not closed
&amp;quot;; 
for $id (keys %files) { 
  local $file = $files{$id}; 
  local $mode = $modes{$id}; 
  local $line = $lines{$id}; 
 
  if ($file ne '') { 
    print &amp;quot;[line $line] id=$id, open $file with mode $mode
&amp;quot;; 
  } 
} 
&lt;/pre&gt;


&lt;p&gt;Pour simplifier le tout, on rajoute une fonction dans le &lt;code&gt;zshrc&lt;/code&gt; pour wrapper tout ça, et ça donne (attention, ceci ne fonctionne que sous linux, &lt;code&gt;mktemp&lt;/code&gt; n'a pas la même syntaxe sur MacOS, et surtout, &lt;code&gt;strace&lt;/code&gt; n'est pas disponible sur Mac&lt;/p&gt;

&lt;pre&gt;
[bash]
function checkFiles() { 
  TEMPFILE=`mktemp` 
  strace -f -e trace=open,close $* 2&amp;gt; $TEMPFILE 
  cat $TEMPFILE | ~/.zsh/trackFiles.pl 
  rm $TEMPFILE 
} 
&lt;/pre&gt;


&lt;p&gt;Avec, ça, il ne me répond&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
% checkFiles cp test test2
12 files opened, max. 2 at the same time
0 files not closed
&lt;/pre&gt;


&lt;p&gt;Si maintenant, je fais un programme minimaliste qui oublie de fermer un fichier&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
[c]
#include &amp;lt;stdio.h&amp;gt; 
 
int main() { 
  FILE* file = fopen(&amp;quot;test&amp;quot;, &amp;quot;r&amp;quot;); 
  return file != NULL ? 0 : 1; 
} 
&lt;/pre&gt;

&lt;pre&gt;
% gcc test.c -o tester
% checkFiles ./tester
3 files opened, max. 1 at the same time
1 files not closed
[line 4] id=3, open test with mode O_RDONLY
&lt;/pre&gt;


&lt;p&gt;Voilà, maintenant je sais que mon programme oublie de fermer un fichier, que ce fichier s'appelle &quot;test&quot;, et qu'il est ouvert en read-only. La ligne &quot;4&quot; est la ligne dans la sortie de &lt;code&gt;strace&lt;/code&gt;, et n'a aucun rapport avec la ligne 4 du fichier source (contrairement aux apparences).&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.mymind.fr/post/2007/08/30/Compter-les-fichiers#comment-form</comments>
      <wfw:comment>http://blog.mymind.fr/post/2007/08/30/Compter-les-fichiers#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.mymind.fr/feed/atom/comments/35</wfw:commentRss>
      </item>
    
  <item>
    <title>Outils pratiques</title>
    <link>http://blog.mymind.fr/post/2007/03/13/Outils-pratiques</link>
    <guid isPermaLink="false">urn:md5:9493e53484f0ab915a8ca15e826de2fc</guid>
    <pubDate>Tue, 13 Mar 2007 19:21:00 +0100</pubDate>
    <dc:creator>Florent Bruneau</dc:creator>
        <category>GeekTime</category>
        <category>Devel</category><category>pratique</category><category>SVN</category><category>zsh</category>    
    <description>&lt;p&gt;Etant donné que je travaille énormément avec &lt;a href=&quot;http://subversion.tigris.org&quot;&gt;SVN&lt;/a&gt;. C'est un outils très addictif... à tel point que je l'utilise dès que je travaille sur un projet (seul ou à plusieurs), je crée un reposoire pour le projet (c'est un excellent moyen de ne pas perdre son travail suite à une fausse manoeuvre). Comme en plus je ne supporte pas les front-end pour SVN, je travaille toujours en ligne de commandes...&lt;/p&gt;    &lt;p&gt;Pour pouvoir améliorer la sortie des commandes SVN dans mes consoles, j'ai fait surchargé la commande &lt;code&gt;svn&lt;/code&gt; par une fonction &lt;code&gt;zsh&lt;/code&gt;&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
[bash]
function svn() {
    if [[ $1 == &amp;quot;ci&amp;quot; || $1 == &amp;quot;commit&amp;quot; || $1 == &amp;quot;propedit&amp;quot; || $1 == &amp;quot;propset&amp;quot; || $1 == &amp;quot;help&amp;quot; ]]; then
        /usr/local/bin/svn $*
    elif [[ $1 == &amp;quot;preci&amp;quot; || $1 == &amp;quot;precommit&amp;quot; ]]; then
        /usr/local/bin/svn status | grep -v '?' | ~/.zsh/zshcolorsvn
    else
        /usr/local/bin/svn $* | ~/.zsh/zshcolorsvn
    fi
}
&lt;/pre&gt;


&lt;p&gt;Cette fonction est donc très simple&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;si la commande nécessite un interaction de l'utilisateur, on appel directement le programme &lt;code&gt;svn&lt;/code&gt; (le cas de &lt;code&gt;help&lt;/code&gt; permet de ne pas casser la tab-completion de &lt;code&gt;zsh&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;sinon on envoi la sortie de svn dans &lt;a href=&quot;http://blog.mymind.fr/mind/public/misc/zshcolorsvn&quot;&gt;un script&lt;/a&gt; qui réalise sa coloration syntaxique&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ceci donne un résultat de la forme suivante&amp;nbsp;:&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;http://blog.mymind.fr/public/screenshots/svn-diff.jpg&quot;&gt;&lt;img src=&quot;http://blog.mymind.fr/public/screenshots/.svn-diff_m.jpg&quot; alt=&quot;Exemple de svn diff&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;http://blog.mymind.fr/public/screenshots/svn-update.jpg&quot;&gt;&lt;img src=&quot;http://blog.mymind.fr/public/screenshots/.svn-update_s.jpg&quot; alt=&quot;Exemple de svn update&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://blog.mymind.fr/public/screenshots/svn-status.jpg&quot;&gt;&lt;img src=&quot;http://blog.mymind.fr/public/screenshots/.svn-status_s.jpg&quot; alt=&quot;Exemple de svn status&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;C'est donc extrêmement pratique&amp;nbsp;; ça permet de distinguer facilement les modifications, ça permet aussi de voir d'un seul coup d'oeil les conflits et la liste des fichiers modifiés. En plus ça fonctionne également avec des commandes comme &lt;code&gt;cvs&lt;/code&gt; ou &lt;code&gt;diff&lt;/code&gt;&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
[bash]
# SVN
function svn() {
    if [[ $1 == &amp;quot;ci&amp;quot; || $1 == &amp;quot;commit&amp;quot; || $1 == &amp;quot;propedit&amp;quot; || $1 == &amp;quot;propset&amp;quot; || $1 == &amp;quot;help&amp;quot; ]]; then
        /usr/local/bin/svn $*
    elif [[ $1 == &amp;quot;preci&amp;quot; || $1 == &amp;quot;precommit&amp;quot; ]]; then
        /usr/local/bin/svn status | grep -v '?' | ~/.zsh/zshcolorsvn
    else
        /usr/local/bin/svn $* | ~/.zsh/zshcolorsvn
    fi; fi
}

# SVN avec conversion de la sortie en latin1
function svn_utf8() {
    if [[ $1 == &amp;quot;ci&amp;quot; || $1 == &amp;quot;commit&amp;quot; ]]; then
        svn $*
    else
        svn $* | iconv -f utf8 -t iso-8859-1
    fi
}

function cvs() {
    if [[ $1 == &amp;quot;diff&amp;quot; ]]; then
        shift 1
        /usr/bin/cvs diff -ubN $* 2&amp;gt; /dev/null | ~/.zsh/zshcolorsvn
    elif [[ $1 == &amp;quot;ci&amp;quot; || $1 == &amp;quot;commit&amp;quot; || $1 == &amp;quot;propedit&amp;quot; || $1 == &amp;quot;propset&amp;quot; || $1 == &amp;quot;help&amp;quot; ]]; then
        /usr/bin/cvs $*
    else
        /usr/bin/cvs $* 2&amp;gt; /dev/null | ~/.zsh/zshcolorsvn
    fi;
}

function diff() { /usr/bin/diff -u $* | ~/.zsh/zshcolordiff }
&lt;/pre&gt;


&lt;p&gt;Les scripts nécessaires sont disponibles&amp;nbsp;: &lt;a href=&quot;http://blog.mymind.fr/public/misc/zshcolorsvn&quot;&gt;zshcolorsvn&lt;/a&gt; et &lt;a href=&quot;http://blog.mymind.fr/public/misc/zshcolordiff&quot;&gt;zshcolordiff&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;Seul défaut&amp;nbsp;: pour pouvoir utiliser les commandes sans coloration... il faut taper chemin complet.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.mymind.fr/post/2007/03/13/Outils-pratiques#comment-form</comments>
      <wfw:comment>http://blog.mymind.fr/post/2007/03/13/Outils-pratiques#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.mymind.fr/feed/atom/comments/12</wfw:commentRss>
      </item>
    
</channel>
</rss>
