<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet title="XSL formatting" type="text/xsl" href="http://mirmodynamics.com/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>Mirmo Dynamics - howto</title>
  <link>http://mirmodynamics.com/</link>
  <atom:link href="http://mirmodynamics.com/feed/tag/howto/rss2" rel="self" type="application/rss+xml"/>
  <description>Rien de grand ne se fit jamais sans enthousiasme.</description>
  <language>en</language>
  <pubDate>Wed, 15 Oct 2008 21:10:32 +0200</pubDate>
  <copyright>2003-2008 &amp;copy; Geoffrey Bachelet</copyright>
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  <generator>Dotclear</generator>
  
    
  <item>
    <title>Débuter avec le Zend Framework</title>
    <link>http://mirmodynamics.com/post/2007/04/12/Debuter-avec-le-Zend-Framework</link>
    <guid isPermaLink="false">urn:md5:e1875eb76e5eb90ebb656be4b001833a</guid>
    <pubDate>Thu, 12 Apr 2007 00:31:00 +0200</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Coding</category>
        <category>doc</category><category>howto</category><category>php</category><category>traduction</category><category>tutorial</category><category>zend framework</category>    
    <description>    &lt;p&gt;&lt;a href=&quot;http://akrabat.com/2007/04/11/premiers-pas-avec-le-zend-framework/&quot;&gt;Pour&lt;/a&gt; &lt;a href=&quot;http://g-rossolini.developpez.com/tutoriels/php/zend-framework/debuter/?page=sommaire&quot;&gt;info&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;Je suis un peu triste parce que je voulais m'atteler à cette tâche, mais bon il faut croire que j'ai trop lambiné :)&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2007/04/12/Debuter-avec-le-Zend-Framework#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2007/04/12/Debuter-avec-le-Zend-Framework#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/756</wfw:commentRss>
      </item>
    
  <item>
    <title>Mini Howto: Serveur et Packages PEAR</title>
    <link>http://mirmodynamics.com/post/2007/03/02/Mini-Howto%3A-Serveur-et-Packages-PEAR</link>
    <guid isPermaLink="false">urn:md5:a4af0a22fcb4f4e307699e4207bc6406</guid>
    <pubDate>Fri, 02 Mar 2007 12:11:00 +0100</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Geekeries</category>
        <category>chiara</category><category>doc</category><category>howto</category><category>package</category><category>pear</category><category>php</category>    
    <description>    &lt;p&gt;Pour installer le serveur &lt;acronym&gt;PEAR&lt;/acronym&gt;, c'est simple:&lt;/p&gt;


&lt;pre&gt;pear channel-discover pear.chiaraquartet.net
pear install chiara/Chiara_PEAR_Server
pear run-scripts Chiara_PEAR_Server&lt;/pre&gt;


&lt;p&gt;Ensuite on répond aux question, et c'est automagique.&lt;/p&gt;


&lt;p&gt;Après, pour créer des packages, ça se corse. Tout d'abord, on a besoin de &lt;code&gt;PEAR_PackageFileManager&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;pear install PEAR_PackageFileManager&lt;/pre&gt;


&lt;p&gt;Ensuite, le but est de générer les &lt;code&gt;package.xml&lt;/code&gt; qui vont bien. Voilà comment j'ai procédé pour le package &lt;code&gt;Zend&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;mkdir -p ~/pear/zend/src &amp;amp;&amp;amp; cd ~/pear/zend
wget http://framework.zend.com/download/tgz -O - | tar xzC ~
mv ~/ZendFramework-0.8.0/library/Zend* src/
php ./mkpkg.php make
cd src &amp;amp;&amp;amp; pear package&lt;/pre&gt;


&lt;p&gt;Ceux qui ont bien suivi auront noté que &lt;code&gt;mkpkg.php&lt;/code&gt; est sorti un peu de l'espace :-) Vous trouverez son contenu à la fin du billet.&lt;/p&gt;


&lt;p&gt;Pour résumer, on créé un répertoire de travail (&lt;code&gt;~/pear/zend/&lt;/code&gt;), dans lequel on créé un répertoire &lt;code&gt;src&lt;/code&gt;, qui contiendra tous les fichiers du package, puis le script &lt;code&gt;mkpkg.php&lt;/code&gt; se charge 1) d'analyser le contenu de &lt;code&gt;src&lt;/code&gt;, et 2) de créer le &lt;code&gt;package.xml&lt;/code&gt; qui va bien, selon les instructions qui lui sont fournies.&lt;/p&gt;


&lt;p&gt;Nous disposons désormais  d'un package &lt;code&gt;Zend-0.8.0.tgz&lt;/code&gt; dans &lt;code&gt;~/pear/zend/src&lt;/code&gt;, que nous n'avons plus qu'a uploader via l'interface d'administration du serveur &lt;acronym&gt;PEAR&lt;/acronym&gt; précédemment installé :-)&lt;/p&gt;


&lt;p&gt;Le fichier &lt;code&gt;mkpkg.php&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;?php

require_once('PEAR/PackageFileManager2.php');

PEAR::setErrorHandling(PEAR_ERROR_DIE);

$packagexml = new PEAR_PackageFileManager2;

$e = $packagexml-&amp;gt;setOptions(array(
    'baseinstalldir' =&amp;gt; '/',
    'packagedirectory' =&amp;gt; dirname(__FILE__).'/src',
));

$packagexml-&amp;gt;setPackage('Zend');
$packagexml-&amp;gt;setSummary('Zend Framework');
$packagexml-&amp;gt;setDescription('The Zend\'s PHP Framework');
$packagexml-&amp;gt;setChannel('pear.phpmafia.net');
$packagexml-&amp;gt;setAPIVersion('0.8.0');
$packagexml-&amp;gt;setReleaseVersion('0.8.0');
$packagexml-&amp;gt;setReleaseStability('devel');
$packagexml-&amp;gt;setAPIStability('devel');
$packagexml-&amp;gt;setNotes(&amp;quot;Still a preview release&amp;quot;);
$packagexml-&amp;gt;setPackageType('php'); // this is a PEAR-style php script package
$packagexml-&amp;gt;addRelease(); // set up a release section
$packagexml-&amp;gt;setPhpDep('5.1.2');
$packagexml-&amp;gt;setPearinstallerDep('1.4.0a12');
$packagexml-&amp;gt;addMaintainer('lead', 'ash', 'Geoffrey Bachelet', 'geoffrey+pear@zubrowka.org');
$packagexml-&amp;gt;setLicense('New BSD License', 'http://framework.zend.com/license/new-bsd');
$packagexml-&amp;gt;generateContents(); // create the &amp;lt;contents&amp;gt; tag

$pkg = &amp;amp;$packagexml-&amp;gt;exportCompatiblePackageFile1(); // get a PEAR_PackageFile object

if (isset($_GET['make']) || (isset($_SERVER['argv']) &amp;amp;&amp;amp; @$_SERVER['argv'][1] == 'make')) {
    $pkg-&amp;gt;writePackageFile();
    $packagexml-&amp;gt;writePackageFile();
} else {
    $pkg-&amp;gt;debugPackageFile();
    $packagexml-&amp;gt;debugPackageFile();
}

?&amp;gt;
&lt;/pre&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2007/03/02/Mini-Howto%3A-Serveur-et-Packages-PEAR#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2007/03/02/Mini-Howto%3A-Serveur-et-Packages-PEAR#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/751</wfw:commentRss>
      </item>
    
  <item>
    <title>Remplacer un caractère par un &quot;Carriage Return&quot; dans vim</title>
    <link>http://mirmodynamics.com/post/2007/01/03/Remplacer-un-caractere-par-un-Carriage-Return-dans-vim</link>
    <guid isPermaLink="false">urn:md5:262aed0ad72a0fbf7adfd05d63caefe3</guid>
    <pubDate>Wed, 03 Jan 2007 11:04:00 +0100</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Geekeries</category>
        <category>howto</category><category>substitute</category><category>vim</category>    
    <description>    &lt;p&gt;Par exemple, imaginons qu'on récupère une query string, et qu'on veuille
l'exploser sur plusieurs lignes, on peut faire:&lt;/p&gt;
&lt;pre&gt;
:s/&amp;amp;/\=&amp;quot;\&amp;lt;CR&amp;gt;&amp;quot;/g
&lt;/pre&gt;
&lt;p&gt;le &lt;code&gt;\=&amp;quot;&amp;quot;&lt;/code&gt; annonce à &lt;acronym&gt;VIM&lt;/acronym&gt; que la chaine de
substitution sera une chaine a interpréter avant utilisation, et le
&lt;code&gt;\&amp;lt;CR&amp;gt;&lt;/code&gt; représente tout simplement le &lt;em&gt;Carriage
Return&lt;/em&gt;.&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2007/01/03/Remplacer-un-caractere-par-un-Carriage-Return-dans-vim#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2007/01/03/Remplacer-un-caractere-par-un-Carriage-Return-dans-vim#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/736</wfw:commentRss>
      </item>
    
  <item>
    <title>Annuler un changeset SVN</title>
    <link>http://mirmodynamics.com/post/2006/12/17/Annuler-un-changeset-SVN</link>
    <guid isPermaLink="false">urn:md5:6541ee25c7c01f781a28cdbe6b510d81</guid>
    <pubDate>Sun, 17 Dec 2006 16:43:00 +0100</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Coding</category>
        <category>cancel</category><category>howto</category><category>merge</category><category>svn</category>    
    <description>    &lt;p&gt;Méthode bourrin, je ne sais pas si il en existe une meilleure. Disons qu'on veut annuler la révision 329 (et que c'est la dernière en date):&lt;/p&gt;


&lt;pre&gt;$ svn update
$ svn merge -r 329:328 .
$ svn commit -m &amp;quot;cancel 329&amp;quot;&lt;/pre&gt;


&lt;p&gt;En tout cas chez moi ça a marché.&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/12/17/Annuler-un-changeset-SVN#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/12/17/Annuler-un-changeset-SVN#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/732</wfw:commentRss>
      </item>
    
  <item>
    <title>ViewHelper de génération d'urls</title>
    <link>http://mirmodynamics.com/post/2006/11/24/ViewHelper-de-generation-durls</link>
    <guid isPermaLink="false">urn:md5:c86ea8dd7be65bd1b6c3bd524fa962e3</guid>
    <pubDate>Fri, 24 Nov 2006 20:27:00 +0100</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Coding</category>
        <category>configuration</category><category>howto</category><category>i18n</category><category>organisation</category><category>php</category><category>zend framework</category>    
    <description>    &lt;p&gt;Pré-requis: &lt;a href=&quot;http://fashion.hosmoz.net/blog/post/2006/10/31/Howto%3A-Utiliser-Zend_Controller_RewriteRouter-avec-Zend_Config&quot;&gt;Zend_Controller_RewriteRouter&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;Nous allons voir aujourd'hui comment générer automagiquement des &lt;acronym&gt;URL&lt;/acronym&gt;s à partir des routes définies dans le &lt;em&gt;RewriteRouter&lt;/em&gt;, ainsi que les avantages que cela présente. Le &lt;code&gt;Helper&lt;/code&gt; que nous allons utiliser nécessite le stockage du routeur dans le registre:&lt;/p&gt;

&lt;pre&gt;
Zend::register('router', $router);
&lt;/pre&gt;


&lt;p&gt;Avant de voir le &lt;code&gt;Helper&lt;/code&gt; lui même, un petit &lt;em&gt;Use Case&lt;/em&gt;. Admettons que vous développiez une application de gestion de petites annonces, vous aurez à un moment ou un autre à créer un lien quelconque pour, par exemple, créer une annonce, et en voir les détails. Disons que vous ayez des routes route du genre (je zappe les &lt;code&gt;defaults&lt;/code&gt;):&lt;/p&gt;

&lt;pre&gt;
announceCreate.route = /announce/create
announceDetails.route = /announce/:id/details
&lt;/pre&gt;


&lt;p&gt;L'objectif est de pouvoir créer les liens grâce au code suivant (à partir de la view):&lt;/p&gt;

&lt;pre&gt;
&amp;lt;a href=&amp;quot;&amp;lt;?php echo $this-&amp;gt;href('announceCreate'); ?&amp;gt;&amp;quot;&amp;gt;Créer une annonce&amp;lt;/a&amp;gt;
&amp;lt;a href=&amp;quot;&amp;lt;?php echo $this-&amp;gt;href('announceDetails', array('id' =&amp;gt; $announce-&amp;gt;id)); ?&amp;gt;&amp;quot;&amp;gt;Voir l'annonce&amp;lt;/a&amp;gt;
&lt;/pre&gt;


&lt;p&gt;Et comme le &lt;a href=&quot;http://framework.zend.com/&quot;&gt;Zend Framework&lt;/a&gt; est bien fait, c'est très simple à réaliser sous forme de &lt;code&gt;ViewHelper&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;
class Zend_View_Helper_Href {
	
	/**
	 * Returns the href to a given route
	 *
	 * @param string $routeName
	 * @param array $args
	 * @return string
	 */
	
	public function href($routeName, $args = array()) {
		try {
			return Zend::registry('router')-&amp;gt;getRoute($routeName)-&amp;gt;assemble($args);
		} catch (Zend_Controller_Router_Exception $e) {
			return '#404';
		}
	}
}
&lt;/pre&gt;


&lt;p&gt;Tellement simple que pour combler un peu je vous offre le &lt;em&gt;docblock&lt;/em&gt; qui va avec ;-)&lt;/p&gt;


&lt;p&gt;Là où ça devient &lt;strong&gt;très&lt;/strong&gt; pratique, c'est quand on souhaite localiser les &lt;acronym&gt;URL&lt;/acronym&gt;s. Par exemple, imaginons que vous souhaitiez &lt;em&gt;françiser&lt;/em&gt; les &lt;acronym&gt;URL&lt;/acronym&gt;s pour, par exemple, améliorer votre référencement. Vous n'avez qu'a définir un jeu de routes &lt;em&gt;fr_FR&lt;/em&gt;, par exemple ainsi:&lt;/p&gt;

&lt;code class=&quot;routes_fr_FR&quot;&gt;announceCreate.route = /annonce/creer&lt;br /&gt;
announceDetails.route = /annonce/:id/details&lt;br /&gt;
&lt;br /&gt;
[routes_en_UK]&lt;br /&gt;
announceCreate.route = /announce/create&lt;br /&gt;
announceDetails.route = /announce/:id/details&lt;br /&gt;
&lt;br /&gt;
[routes:route_fr_FR]&lt;br /&gt;
announceCreate.defaults.controller = announce&lt;br /&gt;
announceCreate.defaults.action = create&lt;br /&gt;
&lt;br /&gt;
announceDetails.defaults.controller = announce&lt;br /&gt;
announceDetails.defaults.action = details&lt;/code&gt;


&lt;p&gt;L'utilisation de l'héritage géré par &lt;code&gt;Zend_Config&lt;/code&gt; nous permet ici d'éviter la redondance des &lt;code&gt;defaults&lt;/code&gt;.&lt;/p&gt;


&lt;p&gt;Elle est pas belle la vie ?&lt;/p&gt;


&lt;p&gt;Note: cette fonctionnalitée est prévue pour être &lt;em&gt;builtin&lt;/em&gt; plus tard.&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/11/24/ViewHelper-de-generation-durls#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/11/24/ViewHelper-de-generation-durls#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/725</wfw:commentRss>
      </item>
    
  <item>
    <title>Zend Framework: Un plugin simple pour le Front Controller</title>
    <link>http://mirmodynamics.com/post/2006/11/19/Zend-Framework%3A-Un-plugin-simple-pour-le-Front-Controller</link>
    <guid isPermaLink="false">urn:md5:6c829cc8dbd18739b84ef7758d852a70</guid>
    <pubDate>Sun, 19 Nov 2006 21:30:00 +0100</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Coding</category>
        <category>bootstrap</category><category>howto</category><category>MVC</category><category>organisation</category><category>php</category><category>plugin</category><category>vues</category><category>zend framework</category>    
    <description>&lt;p&gt;L'implémentation du &lt;code&gt;Front Controller&lt;/code&gt; du &lt;a href=&quot;http://framework.zend.com/&quot;&gt;Zend Framework&lt;/a&gt; inclue un système bien pratique de plugins, qui va nous permettre de réaliser plus simplement et proprement &lt;a href=&quot;http://fashion.hosmoz.net/blog/post/2006/08/30/Automatisation-des-vues&quot;&gt;l'automatisation des vues&lt;/a&gt;, initialement embarquée dans une extension de &lt;code&gt;Zend_Controller_Action&lt;/code&gt; (ce qui pose quelques problèmes, nottament au lors de l'utilisation de &lt;code&gt;__forward()&lt;/code&gt; et &lt;code&gt;_redirect()&lt;/code&gt;).&lt;/p&gt;    &lt;p&gt;Techniquement, un plugin est une classe qui implémente l'interface des plugins (&lt;code&gt;Zend_Controller_Plugin_Interface&lt;/code&gt;). Dans la pratique, une classe abstraite est fournie pour simplifier la tache (&lt;code&gt;Zend_Controller_Plugin_Abstract&lt;/code&gt;). Notre premier plugin s'appellera &lt;code&gt;AutoView&lt;/code&gt; (&lt;code&gt;My_Controller_Plugin_AutoView&lt;/code&gt;, stocké dans &lt;code&gt;My/Controller/Plugin/AutoView.php&lt;/code&gt;).&lt;/p&gt;


&lt;p&gt;Un plugin est donc une classe dont les méthodes seront appelées a différents moments de la &lt;em&gt;dispatch loop&lt;/em&gt; du controlleur frontal, comme on peut le voir dans &lt;code&gt;Zend_Controller_Front::dispatch()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;routeStartup()&lt;/code&gt;, à la mise en route du routeur&lt;/li&gt;
&lt;li&gt;&lt;code&gt;routeShutdown($action)&lt;/code&gt;, à l'arrêt du routeur&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dispatchLoopStartup($action)&lt;/code&gt;, avant la &lt;em&gt;dispatch loop&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;preDispatch($action)&lt;/code&gt;, avant d'executer une action&lt;/li&gt;
&lt;li&gt;&lt;code&gt;postDispatch($action)&lt;/code&gt;, après avoir executé une action&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dispatchLoopShutdown()&lt;/code&gt;, pour finir.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A chaud, on pourrait se dire que &lt;code&gt;postDispatch&lt;/code&gt; est exactement ce dont on n'a besoin, et on se tromperait. Ce qu'il faut savoir, c'est que l'argument &lt;code&gt;$action&lt;/code&gt; passé à &lt;code&gt;postDispatch&lt;/code&gt; contient l'action qui suit celle qui vient d'être executé. Dans la majorité des cas, n'ayant qu'une seule action à executer, &lt;code&gt;$action&lt;/code&gt; sera vide, et on se retrouve l'air un peu con.&lt;/p&gt;


&lt;p&gt;Bon donc, on va user d'un stratagème: notre plugin va stocker les actions qui passent dans &lt;code&gt;preDispatch&lt;/code&gt;, pour s'occuper de la dernière à être passée dans &lt;code&gt;dispatchLoopShutdown&lt;/code&gt;. Dernier détail, notre plugin s'occupera lui même de gérer son instance de &lt;code&gt;Zend_View&lt;/code&gt;. Et sans plus attendre, le code, qui n'a finalement rien de compliqué:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;?php

require_once 'Zend/Controller/Plugin/Abstract.php';

class My_Controller_Plugin_AutoView extends Zend_Controller_Plugin_Abstract {

	private $_lastAction;

	public function __construct() {
		$view = new Zend_View;
		$view-&amp;gt;setScriptPath(APP_ROOT.'/views/');
		Zend::register('view', $view);
	}

	public function preDispatch($action) {
		$this-&amp;gt;_lastAction = clone($action);
		return $action;
	}

	public function dispatchLoopShutdown() {
		if (!is_null($this-&amp;gt;_lastAction)) {
			$viewPath = sprintf('%s/%s.php', $this-&amp;gt;_lastAction-&amp;gt;getControllerName(), $this-&amp;gt;_lastAction-&amp;gt;getActionName());
			echo Zend::registry('view')-&amp;gt;render($viewPath);
		}
	}
}

?&amp;gt;
&lt;/pre&gt;


&lt;p&gt;Bien, notre plugin vaillament codé, il nous faut désormais expliquer au controlleur frontal qu'on aimerai bien qu'il en tienne compte. Cela se passe fort logiquement dans le &lt;em&gt;bootstrap&lt;/em&gt;, via la méthode &lt;code&gt;registerPlugin&lt;/code&gt; du sus-cité controlleur frontal, qui prend en argument une instance d'un objet implémentant &lt;code&gt;Zend_Controller_Plugin_Interface&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;
$controller = Zend_Controller_Front::getInstance();
$controller-&amp;gt;registerPlugin(new My_Controller_Plugin_AutoView);
&lt;/pre&gt;


&lt;p&gt;And viola !&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/11/19/Zend-Framework%3A-Un-plugin-simple-pour-le-Front-Controller#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/11/19/Zend-Framework%3A-Un-plugin-simple-pour-le-Front-Controller#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/720</wfw:commentRss>
      </item>
    
  <item>
    <title>Migrer un dépot subversion</title>
    <link>http://mirmodynamics.com/post/2006/11/09/Migrer-un-depot-subversion</link>
    <guid isPermaLink="false">urn:md5:84c41cd08be4b33fce92f3f42254d080</guid>
    <pubDate>Thu, 09 Nov 2006 17:25:00 +0100</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Geekeries</category>
        <category>doc</category><category>howto</category><category>svn</category><category>unix</category>    
    <description>    &lt;p&gt;Imaginons que vous souhaitiez déplacer votre dépôt subversion &lt;em&gt;myproject&lt;/em&gt; d'une machine &lt;em&gt;old-server&lt;/em&gt; à une machine &lt;em&gt;new-server&lt;/em&gt;. Vite fait, bien fait:&lt;/p&gt;


&lt;pre&gt;old-server# svnadmin dump /var/lib/subversion/myproject &amp;gt; ~/myproject.svndump
old-server# scp ~/myproject.svndump new-server:
new-server# svnadmin create /var/lib/subversion/myproject
new-server# svnadmin load /var/lib/subversion/myproject &amp;lt; ~/myproject.svndump&lt;/pre&gt;


&lt;p&gt;&lt;strong&gt;Attention&lt;/strong&gt;, il vous faut par contre migrer vos éventuelles &lt;em&gt;hooks&lt;/em&gt; à la main, ils ne sont effectivement pas gérés par &lt;code&gt;svndump&lt;/code&gt;. Une autre méthode, incluant les &lt;em&gt;hooks&lt;/em&gt; celle-ci, serait d'utiliser &lt;code&gt;svnadmin hotcopy&lt;/code&gt;, mais je n'ai pas testé.&lt;/p&gt;


&lt;p&gt;Plus d'infos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://svnbook.red-bean.com/nightly/en/svn.ref.svnadmin.c.dump.html&quot;&gt;svnadmin help dump&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://svnbook.red-bean.com/nightly/en/svn.ref.svnadmin.c.load.html&quot;&gt;svnadmin help load&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://svnbook.red-bean.com/nightly/en/svn.ref.svnadmin.c.hotcopy.html&quot;&gt;svnadmin help hotcopy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/11/09/Migrer-un-depot-subversion#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/11/09/Migrer-un-depot-subversion#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/716</wfw:commentRss>
      </item>
    
  <item>
    <title>Howto: Utiliser Zend_Controller_RewriteRouter avec Zend_Config</title>
    <link>http://mirmodynamics.com/post/2006/10/31/Howto%3A-Utiliser-Zend_Controller_RewriteRouter-avec-Zend_Config</link>
    <guid isPermaLink="false">urn:md5:58ec785aef55507ca8784ce7b8d798b3</guid>
    <pubDate>Tue, 31 Oct 2006 20:26:00 +0100</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Coding</category>
        <category>bootstrap</category><category>configuration</category><category>controlleurs</category><category>doc</category><category>howto</category><category>ini</category><category>MVC</category><category>php</category><category>zend framework</category>    
    <description>&lt;p&gt;Comme je le disais plus bas, le Zend Framework Preview 0.2.0 est dans les bacs ! Cette nouvelle mouture apporte son lot de nouveautés, et nous allons nous pencher sur une des plus interressantes: le &lt;em&gt;RewriteRouter&lt;/em&gt;. Le &lt;em&gt;RewriteRouter&lt;/em&gt; est un routeur pour le composant &lt;acronym&gt;MVC&lt;/acronym&gt; du Zend Framework qui va nous permettre de configurer nos &lt;acronym&gt;URL&lt;/acronym&gt; comme dans Ruby on Rails, c'est à dire (en gros), via un fichier de configuration, et c'est là que &lt;em&gt;Zend_Config&lt;/em&gt; entre en jeu.&lt;/p&gt;    &lt;h3&gt;Mettre en place le routeur&lt;/h3&gt;


&lt;p&gt;C'est bien beau tout ça, mais pour l'utiliser, il faut déjà en informer le controlleur. Pour cela, rien de plus simple, on utilise la méthode &lt;code&gt;addRouter&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;$router = new Zend_Controller_RewriteRouter;
$controller = Zend_Controller_Front::getInstance();
$controller-&amp;gt;setRouter($router);&lt;/pre&gt;


&lt;p&gt;Le &lt;em&gt;RewriteRouter&lt;/em&gt; est pré-configuré avec deux routes qui permettent d'assurer la compatibilité descendante avec l'ancien routeur, donc jusque là, tout va bien.&lt;/p&gt;


&lt;h3&gt;Déclarer les routes&lt;/h3&gt;


&lt;p&gt;Nous utiliserons un fichier de configuration dédié aux routes, que nous appellerons sobrement &lt;em&gt;routes.ini&lt;/em&gt;, et que nous placerons dans &lt;code&gt;app/&lt;/code&gt;, à coté de son compagnon &lt;em&gt;config.ini&lt;/em&gt;. Ce fichier de configuration contiendra une unique section &lt;code&gt;[routes]&lt;/code&gt;, qui contiendra à son tour les multiples définitions de routes que nous souhaitons y caser. Une route se compose de 5 éléments principaux:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;L'identifiant de la route. C'est un identifiant interne utilisé par le &lt;code&gt;RewriteRouter&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;l'&lt;acronym&gt;URL&lt;/acronym&gt; de la route, c'est ce qui permet au routeur de reconnaitre la route à utiliser,&lt;/li&gt;
&lt;li&gt;les valeurs par défauts des variables,&lt;/li&gt;
&lt;li&gt;les requirements de la route, qui permettent de déterminer si une route est bien formée ou non.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sans plus attendre, un petit exemple: la route qui &lt;em&gt;pourrait&lt;/em&gt; permettre d'accéder à un billet dans dotclear 2:&lt;/p&gt;


&lt;pre&gt;post.route = post/:year/:month/:day/:title
post.reqs.year = &amp;quot;\d+&amp;quot;
post.reqs.month = &amp;quot;\d+&amp;quot;
post.reqs.day = &amp;quot;\d+&amp;quot;
post.reqs.title = &amp;quot;[a-zA-Z0-9_:-]&amp;quot;+
post.defaults.controller = post
post.defaults.action = view
post.defaults.title =&lt;/pre&gt;


&lt;p&gt;Elle &lt;em&gt;pourrait&lt;/em&gt; seulement, car en fait, la regexp du &lt;code&gt;title&lt;/code&gt; est trop restrictive (une &lt;acronym&gt;URL&lt;/acronym&gt; peut contenir d'autres caractères que ceux là), et de plus, les &lt;acronym&gt;URL&lt;/acronym&gt; stockées par dotclear 2 en base de données comprennent tout ce qui se trouve après &lt;code&gt;post/&lt;/code&gt; (par exemple le champs &lt;code&gt;post_url&lt;/code&gt; de ce billet contient: &lt;code&gt;2006/10/31/Howto:-Utiliser-Zend_Controller_RewriteRouter-avec-Zend_Config&lt;/code&gt;).&lt;/p&gt;


&lt;p&gt;Cela étant dit, la route que nous venons de décrire s'appliquera aux &lt;acronym&gt;URL&lt;/acronym&gt;s suivantes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/post/2006/30/10/ZendFramework&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/post/42/2006/56/Foobar&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/post/2006/30/10/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mais pas à:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/post/2006/Foobar&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/post/Foobar/2006/30/01&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On note donc d'ores et déjà:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;que la validation des composants d'une route se fait par expression régulière&lt;/li&gt;
&lt;li&gt;qu'on peut ommettre le dernier composant d'une route si il possède une valeur par défaut (récursivement)&lt;/li&gt;
&lt;li&gt;qu'on ne peut pas modifier l'ordre des composants d'une route&lt;/li&gt;
&lt;li&gt;qu'on doit spécifier manuellement le nom du controlleur et de l'action à utiliser&lt;/li&gt;
&lt;li&gt;et c'est déjà pas mal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Décortiquons maintenant une &lt;acronym&gt;URL&lt;/acronym&gt;: &lt;code&gt;/post/2006/30/10/ZendFramework&lt;/code&gt;. Le routeur va diviser cette &lt;acronym&gt;URL&lt;/acronym&gt; ainsi:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Controller: &lt;code&gt;post&lt;/code&gt; (d'après les &lt;em&gt;defaults&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Action: &lt;code&gt;view&lt;/code&gt; (d'après les &lt;em&gt;defaults&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Paramètres: &lt;code&gt;year&lt;/code&gt;: 2006, &lt;code&gt;month&lt;/code&gt;: 30, &lt;code&gt;day&lt;/code&gt;: 10, &lt;code&gt;title&lt;/code&gt;: ZendFramework (d'après l'&lt;acronym&gt;URL&lt;/acronym&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Les paramètres ainsi détectés seront disponibles via la méthode &lt;code&gt;$this-&amp;gt;_getParam($name);&lt;/code&gt; a l'intérieur du controlleur.&lt;/p&gt;


&lt;p&gt;Dernier point de ce chapitre, une déclaration de route peut comporter deux variables spéciales: &lt;code&gt;:controller&lt;/code&gt; et &lt;code&gt;:action&lt;/code&gt;, qui servent respectivement à détecter le controller et l'action à utiliser dans l'url. Par exemple, la route &lt;em&gt;builtin&lt;/em&gt; &lt;code&gt;compat&lt;/code&gt; chargé d'assurer la compatibilité descendante se déclare ainsi:&lt;/p&gt;


&lt;pre&gt;compat.route = :controller/:action
compat.defaults.controller = index
compat.defaults.action = index&lt;/pre&gt;


&lt;h3&gt;Assembler le tout&lt;/h3&gt;


&lt;p&gt;Dernière étape, transférer directement toutes ces déclarations dans le Routeur: n'y allons pas par quatre chemin:&lt;/p&gt;


&lt;pre&gt;$router-&amp;gt;addConfig(new Zend_Config_Ini('/path/to/routes.ini', null), 'routes');&lt;/pre&gt;


&lt;p&gt;C'est aussi simple que ça. Ce qui nous donne, en prenant en compte le morceau de code du début de l'article:&lt;/p&gt;


&lt;pre&gt;$router = new Zend_Controller_RewriteRouter;
$router-&amp;gt;addConfig(new Zend_Config_Ini($routes_path, null), 'routes');
$controller = Zend_Controller_Front::getInstance();
$controller-&amp;gt;setRouter($router);&lt;/pre&gt;


&lt;p&gt;And voilà. Je ne saurais que vous conseiller la lecture du &lt;a href=&quot;http://framework.zend.com/manual/en/zend.controller.rewriterouter.html&quot;&gt;manuel&lt;/a&gt; pour plus d'informations (sachant qu'en fait, &lt;code&gt;addRoute&lt;/code&gt; attend en deuxième argument une instance de &lt;code&gt;Zend_Controller_Router_Route&lt;/code&gt;, mais qui s'instancie avec les paramètres qu'ils passent à &lt;code&gt;addRoute&lt;/code&gt;, petite coquille du manuel :p).&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/10/31/Howto%3A-Utiliser-Zend_Controller_RewriteRouter-avec-Zend_Config#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/10/31/Howto%3A-Utiliser-Zend_Controller_RewriteRouter-avec-Zend_Config#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/710</wfw:commentRss>
      </item>
    
  <item>
    <title>Mettre en place un SSO avec Invision Power Board</title>
    <link>http://mirmodynamics.com/post/2006/10/24/Mettre-en-place-un-SSO-avec-Invision-Power-Board</link>
    <guid isPermaLink="false">urn:md5:e31ee19b3caa179f39e785cafe1ae2d1</guid>
    <pubDate>Wed, 25 Oct 2006 23:02:00 +0200</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Coding</category>
        <category>configuration</category><category>hack</category><category>howto</category><category>ip.board</category><category>php</category><category>sso</category><category>work</category>    
    <description>&lt;p&gt;Rien de plus simple, tout est déjà prévu. Après l'installation de votre forum &lt;acronym&gt;IPB&lt;/acronym&gt;, nous allons enregistrer une nouvelle méthode de login. Pour se faire, dans le panneau d'administration, nous nous dirigeons vers &lt;em&gt;Tools and Settings&lt;/em&gt;, puis dans &lt;em&gt;Create New Log In&lt;/em&gt; du menu &lt;em&gt;Log In Manager&lt;/em&gt;. On se retrouve devant un formulaire (assez explicite) que je vous laisse le soin de remplir. On dira juste que nous appellerons cette méthode de login &lt;em&gt;Mon SSO&lt;/em&gt; (&lt;em&gt;Log In Title&lt;/em&gt;) et qu'il vivra dans le répertoire &lt;code&gt;mon_sso&lt;/code&gt; (&lt;em&gt;Log In Files Folder Name&lt;/em&gt;). Pour que votre méthode de login soit active, vous devez cocher &lt;em&gt;Log In Enabled&lt;/em&gt;, et il est toujours bon de passer en mode &lt;em&gt;On-Fail&lt;/em&gt;, ainsi que d'autoriser la création d'utilisateurs (&lt;em&gt;Log In Allow Member Creation&lt;/em&gt;), qui créera automagiquement les utilisateurs dans la base locale d'&lt;acronym&gt;IPB&lt;/acronym&gt;.&lt;/p&gt;    &lt;p&gt;Ensuite on met les mains dans le camboui. Dans le répertoire &lt;code&gt;sources/loginauth/&lt;/code&gt; de votre installation, il doit exister un repertoire &lt;code&gt;external/&lt;/code&gt;, qui nous servira de base. On commence donc par le dupliquer:&lt;/p&gt;


&lt;pre&gt;cp -r external mon_sso&lt;/pre&gt;


&lt;p&gt;Puis on regarde un peu ce qu'il y a dedans:&lt;/p&gt;


&lt;pre&gt;mon_sso/
	auth.php
	conf.php
	index.html&lt;/pre&gt;


&lt;p&gt;Le fichier &lt;code&gt;index.html&lt;/code&gt; n'est qu'un empécheur de tourner en rond pour les gens qui explorent un peu trop les arbos web. Le premier fichier qui nous interresse est &lt;code&gt;conf.php&lt;/code&gt;, il contient les informations relatives à la base de données distantes. Là encore, c'est assez explicite et bien commenté. Le seul petit truc à savoir est que l'utilisateur qui se connectera à la base a besoin des droits &lt;em&gt;SELECT&lt;/em&gt; sur &lt;strong&gt;toute&lt;/strong&gt; la table, pas seulement sur les champs login / pass.&lt;/p&gt;


&lt;p&gt;Dans le meilleur des cas, votre &lt;acronym&gt;SSO&lt;/acronym&gt; est prêt :p Le fichier &lt;code&gt;auth.php&lt;/code&gt; contient les méthodes appelées par le gestionnaire d'identification. Vous pouvez avoir besoin de modifier &lt;code&gt;__compare_password&lt;/code&gt;, pour la vérification du mot de passe (j'ai par exemple changé la méthode de cryptage qui est md5 par défaut).&lt;/p&gt;


&lt;p&gt;A ce stade, vos utilisateurs peuvent s'identifier, mais le forum leur demande quand même leur mail et quelques infos que j'ai oublié. Il est bien évidemment possible d'éviter ça :-)
Dans la méthode &lt;code&gt;authenticate&lt;/code&gt;, vers la fin, quand un utilisateur local est créé, la main est passée à la méthode &lt;code&gt;create_local_member&lt;/code&gt;, qui redirige ensuite vers l'écran de complétion du compte. C'est là que nous intervenons. La méthode &lt;code&gt;create_local_member&lt;/code&gt; n'est pas implémenté dans &lt;code&gt;login_method&lt;/code&gt;, mais dans &lt;code&gt;login_core&lt;/code&gt;, qui se trouve dans le fichier &lt;code&gt;sources/loginauth/login_core.php&lt;/code&gt;, nous commençons par la copier/coller dans notre &lt;code&gt;login_method&lt;/code&gt;, puis nous modifions sa déclaration pour lui permettre de recevoir &lt;code&gt;$remote_member&lt;/code&gt; en paramètre:&lt;/p&gt;


&lt;pre&gt;function create_local_member( $remote_member )
{&lt;/pre&gt;


&lt;p&gt;Cette méthode permet de piocher dans les informations récupérées dans la base distante. Dans la partie &lt;em&gt;Populate member table(s)&lt;/em&gt;, par défaut, un faux mail est créé:&lt;/p&gt;


&lt;pre&gt;$email_tmp = $username.'@'.$timenow;&lt;/pre&gt;


&lt;p&gt;Qu'on peut remplacer par le mail qu'on a déjà potentiellement dans la base distante (disons que le champs s'appelle &lt;code&gt;mail&lt;/code&gt;):&lt;/p&gt;


&lt;pre&gt;$email_tmp = $remote_member['mail'];&lt;/pre&gt;


&lt;p&gt;On peut ensuite récupérer les champs que l'on veut pour les ajouter au membre local, par exemple dans mon cas, le &lt;code&gt;display_name&lt;/code&gt; (&lt;code&gt;nickname&lt;/code&gt; chez moi):&lt;/p&gt;


&lt;pre&gt;$display_name = $remote_member['nickname'];&lt;/pre&gt;


&lt;p&gt;en les rajoutant dans le tableau &lt;code&gt;$member&lt;/code&gt;.&lt;/p&gt;


&lt;p&gt;Les deux derniers appels de méthode dans &lt;code&gt;create_local_member&lt;/code&gt;, &lt;code&gt;$this-&amp;gt;ipsclass-&amp;gt;DB-&amp;gt;do_insert&lt;/code&gt; et &lt;code&gt;$this-&amp;gt;ipsclass-&amp;gt;print-&amp;gt;redirect_screen&lt;/code&gt; sont à commenter, et on rajouter avant le bout de code suivant:&lt;/p&gt;


&lt;pre&gt;$this-&amp;gt;return_code = 'SUCCESS';
return;&lt;/pre&gt;


&lt;p&gt;Retour dans &lt;code&gt;authenticate&lt;/code&gt;, dans la partie &lt;em&gt;Got no member - but auth passed - create?&lt;/em&gt;, on modifie la première partie du &lt;code&gt;if&lt;/code&gt; ainsi:&lt;/p&gt;


&lt;pre&gt;if ( $this-&amp;gt;allow_create )
{
	$this-&amp;gt;create_local_member( $remote_member );
	$this-&amp;gt;_load_member($username);

	if ( $this-&amp;gt;member['id'] )
	{
		$this-&amp;gt;return_code = 'SUCCESS';
	}
	else
	{
		$this-&amp;gt;return_code = 'NO_USER';
	}
	return;
}&lt;/pre&gt;


&lt;p&gt;And voilà, nos utilisateurs peuvent désormais s'identifier sans avoir a re-entrer des informations que l'on possède déjà :-)&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/10/24/Mettre-en-place-un-SSO-avec-Invision-Power-Board#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/10/24/Mettre-en-place-un-SSO-avec-Invision-Power-Board#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/693</wfw:commentRss>
      </item>
    
  <item>
    <title>Relayer un stream audio avec icecast2</title>
    <link>http://mirmodynamics.com/post/2006/10/20/Relayer-un-stream-audio-avec-icecast2</link>
    <guid isPermaLink="false">urn:md5:0df1adaf1cd213b3a277c6eb891f838d</guid>
    <pubDate>Fri, 20 Oct 2006 22:05:00 +0200</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Geekeries</category>
        <category>bidouille</category><category>configuration</category><category>doc</category><category>howto</category><category>optimisation</category><category>rigolo</category><category>ubuntu</category><category>unix</category><category>way of life</category><category>work</category>    
    <description>    &lt;p&gt;Pour économiser la bande passante au boulot, j'ai décidé de relayer le stream &lt;em&gt;Club !&lt;/em&gt; de &lt;a href=&quot;http://1.fm/&quot;&gt;1.fm&lt;/a&gt; sur le &lt;acronym&gt;LAN&lt;/acronym&gt;. Après avoir vainement tenté d'utiliser streamripper (on verra plus tard pourquoi vainement), j'ai sorti l'artillerie lourde: &lt;a href=&quot;http://www.icecast.org/&quot;&gt;icecast2&lt;/a&gt;:&lt;/p&gt;


&lt;pre&gt;sudo apt-get install icecast2&lt;/pre&gt;


&lt;p&gt;Si on sait un peu lire, le script de post-configuration nous incite à aller fourrer notre nez dans &lt;code&gt;/etc/default/icecast2&lt;/code&gt;, où l'on apprend (vers la fin) que icecast est désactivé par défaut à cause de la directive &lt;code&gt;ENABLED=false&lt;/code&gt;. C'est en fait une feinte pour nous pousser à configurer le bousin (de toute façon si on le configure pas, il marchera pas). Direction &lt;code&gt;/etc/icecast2/icecast.xml&lt;/code&gt; donc, pour un brin de configuration (les explications qui suivent se basent sur le fichier par défaut d'une installation sur une ubuntu).&lt;/p&gt;


&lt;p&gt;La première partie qui nous interresse s'intitule &lt;code&gt;authentication&lt;/code&gt; (vers la ligne 23). Elle contient les informations d'authentification pour les clients qui se connectent en tant que source (&lt;code&gt;source-password&lt;/code&gt;), les serveurs qui se connectent en tant que slave (&lt;code&gt;relay-password&lt;/code&gt;, en fait je ne suis pas sur à 100%, c'est une déduction) et pour l'interface d'administration (&lt;code&gt;admin-user&lt;/code&gt; et &lt;code&gt;admin-password&lt;/code&gt;). Une fois ces informations modifiées, direction la directive &lt;code&gt;hostname&lt;/code&gt;, qu'on remplira avec au choix, le nom de la machine, son ip, etc. J'ai personellement mis l'ip privée de ma machine (&lt;code&gt;172.16.x.y&lt;/code&gt;), pour que ça correspondent à la prochaine directive qui nous interresse: &lt;code&gt;listen-socket&lt;/code&gt;. Ici on définit le port et l'ip sur laquelle icecast va écouter. En gros, si vous spécifier &lt;code&gt;127.0.0.1&lt;/code&gt;, votre serveur de streaming ne sera accessible qu'en local. On y met donc en général la même chose que dans &lt;code&gt;hostname&lt;/code&gt; (&lt;code&gt;172.16.x.y&lt;/code&gt; par exemple), avec un port qui va bien, libre de préférence (&lt;code&gt;8000&lt;/code&gt; par défaut).&lt;/p&gt;


&lt;p&gt;Maintenant on passe a la partie qui nous interresse vraiment, la section &lt;code&gt;relay&lt;/code&gt;. Rien de bien compliqué ici. Le stream que je souhaite relayer se trouve là: http://64.62.253.223:8060/, or icecast nous demande un &lt;code&gt;server&lt;/code&gt;, un &lt;code&gt;port&lt;/code&gt;, un &lt;em&gt;point de montage&lt;/em&gt; (&lt;code&gt;mount&lt;/code&gt;) et un &lt;em&gt;point de montage local&lt;/em&gt; (&lt;code&gt;local-mount&lt;/code&gt;). Vous avez déjà compris qu'on arrive a cette configuration:&lt;/p&gt;


&lt;pre&gt;   &amp;lt;relay&amp;gt;
       &amp;lt;server&amp;gt;64.62.253.223&amp;lt;/server&amp;gt;
       &amp;lt;port&amp;gt;8060&amp;lt;/port&amp;gt;
       &amp;lt;mount&amp;gt;/&amp;lt;/mount&amp;gt;
       &amp;lt;local-mount&amp;gt;/1.fm&amp;lt;/local-mount&amp;gt;
       &amp;lt;on-demand&amp;gt;0&amp;lt;/on-demand&amp;gt;
       &amp;lt;relay-shoutcast-metadata&amp;gt;1&amp;lt;/relay-shoutcast-metadata&amp;gt;
   &amp;lt;/relay&amp;gt;&lt;/pre&gt;


&lt;p&gt;Ainsi parés, il ne nous reste plus qu'a lancer modifier la directive &lt;code&gt;ENABLED=false&lt;/code&gt; en &lt;code&gt;ENABLED=true&lt;/code&gt; dans &lt;code&gt;/etc/default/icecast2&lt;/code&gt; et à lancer icecast:&lt;/p&gt;


&lt;pre&gt;sudo /etc/init.d/icecast2 start&lt;/pre&gt;


&lt;p&gt;Si vous avez bien tout fait, vous devriez pouvoir streamer depuis &lt;code&gt;http://172.16.x.y:8000/1.fm&lt;/code&gt;, et vos collègues également ! Vous pouvez avoir une vue d'ensemble du serveur ainsi que quelques options d'administration en vous rendant sur l'interface d'admin: http://172.16.x.y:8000/ et en utilisant &lt;code&gt;admin-user&lt;/code&gt; et &lt;code&gt;admin-password&lt;/code&gt; pour vous authentifier.&lt;/p&gt;


&lt;p&gt;A cela on peut ajouter un petit &lt;code&gt;streamripper&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;streamripper http://172.16.x.y:8000/1.fm -d ~/streamripped&lt;/pre&gt;


&lt;p&gt;Pour enregistrer. En parlant de streamripper, j'avais tenté au début de relayer avec &lt;code&gt;streamripper -r&lt;/code&gt;, mais malgrès les apparences du &lt;code&gt;netstat -pl&lt;/code&gt; (&lt;code&gt;*:8000 LISTEN&lt;/code&gt;), il ne bind qu'en local, donc impossible d'en faire profiter les collègues :-)&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/10/20/Relayer-un-stream-audio-avec-icecast2#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/10/20/Relayer-un-stream-audio-avec-icecast2#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/692</wfw:commentRss>
      </item>
    
  <item>
    <title>Vous prendrez bien un peu de ssh avec votre tunnel ?</title>
    <link>http://mirmodynamics.com/post/2006/10/20/Vous-prendrez-bien-un-peu-de-ssh-avec-votre-tunnel</link>
    <guid isPermaLink="false">urn:md5:0114979e945f69f9eb437f87337a6c0e</guid>
    <pubDate>Fri, 20 Oct 2006 20:06:00 +0200</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Geekeries</category>
        <category>howto</category><category>rigolo</category><category>ssh</category><category>sécurité</category><category>unix</category>    
    <description>    &lt;p&gt;Il arrive des fois où on aimerait pouvoir relier directment deux machines appartenant a deux réseaux distincts. C'est par exemple mon cas quand j'ai besoin (envie on va dire) d'accéder à ma machine du boulot depuis une machine non connectée au &lt;acronym&gt;VPN&lt;/acronym&gt;. Dans ce genre de cas, il existe en général une machine qui possède des interfaces susceptibles d'accéder à chacune des machines (le concentrateur &lt;acronym&gt;VPN&lt;/acronym&gt; par exemple). Nous appellerons cette machine &lt;code&gt;relay&lt;/code&gt;, car elle servira de relai au tunnel. Pour éviter les sempiternelles appellations &lt;code&gt;A&lt;/code&gt; et &lt;code&gt;B&lt;/code&gt; qui embrouillent plus qu'autre chose, les machines s'appelleront &lt;code&gt;startpoint&lt;/code&gt; pour la machine sur laquelle on a la main et &lt;code&gt;endpoint&lt;/code&gt; pour la machine à laquelle on souhaite accéder.&lt;/p&gt;


&lt;p&gt;Postulats de base:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;relay&lt;/code&gt; possède un serveur &lt;acronym&gt;SSH&lt;/acronym&gt; qui tourne&lt;/li&gt;
&lt;li&gt;&lt;code&gt;startpoint&lt;/code&gt; possède un client &lt;acronym&gt;SSH&lt;/acronym&gt; capable de créer un tunnel (&lt;code&gt;ssh&lt;/code&gt;, par exemple)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;relay&lt;/code&gt; est accessible depuis &lt;code&gt;startpoint&lt;/code&gt; et peut se connecter à &lt;code&gt;endpoint&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bien, allons y franchement, la commande, à executer depuis &lt;code&gt;startpoint&lt;/code&gt;, permettant de créer un tunnel &lt;acronym&gt;SSH&lt;/acronym&gt; entre &lt;code&gt;startpoint&lt;/code&gt; et &lt;code&gt;endpoint&lt;/code&gt; est la suivante:&lt;/p&gt;


&lt;pre&gt;ssh -L 2222:endpoint:22 relay&lt;/pre&gt;


&lt;p&gt;Qu'avons nous fait là ? L'option &lt;code&gt;-L&lt;/code&gt; de &lt;acronym&gt;SSH&lt;/acronym&gt; sert à &lt;em&gt;binder&lt;/em&gt; un port de la machine locale (&lt;code&gt;startpoint&lt;/code&gt; donc), à un autre port (ou le même) de la machine distante (&lt;code&gt;endpoint&lt;/code&gt;). Ici, on associe le port local 2222 (22 étant déjà pris par mon serveur &lt;acronym&gt;SSH&lt;/acronym&gt;, mais on pourrait utiliser le port 22 si aucun serveur ne tournait, à la différence près qu'il faudrait lancer la commande en root pour pouvoir &lt;em&gt;binder&lt;/em&gt; un port inférieur à 1024 (c'est comme ça)) au port 22 de &lt;code&gt;endpoint&lt;/code&gt;, c'est à dire le serveur &lt;acronym&gt;SSH&lt;/acronym&gt;. Il nous est dès lors possible d'ouvrir une connection &lt;acronym&gt;SSH&lt;/acronym&gt; sur &lt;code&gt;endpoint&lt;/code&gt; en se connectant au port 2222 de notre machine locale:&lt;/p&gt;


&lt;pre&gt;ssh -p 2222 localhost&lt;/pre&gt;


&lt;p&gt;Magique non ? Bien sur, il est possible de forwarder n'importe quel port au travers du tunnel:&lt;/p&gt;


&lt;pre&gt;ssh -L 8080:endpoint:80 relay&lt;/pre&gt;


&lt;p&gt;Faire pointer votre navigateur sur &lt;code&gt;http://localhost:8080/&lt;/code&gt; vous ammenera sur le serveur web de &lt;code&gt;endpoint&lt;/code&gt;.&lt;/p&gt;


&lt;p&gt;Mais un tunnel ne se limite pas à joindre deux machines d'un réseau différents. On peut également imaginer un tunnel entre deux machines dans l'unique but de sécuriser une transmission, par exemple, des échanges de mails. Imaginons que votre serveur mail preferré, &lt;code&gt;pop.example.com&lt;/code&gt;, ne propose pas de connection &lt;acronym&gt;POP&lt;/acronym&gt; sécurisée. Vous pouvez remédier à ce manque flagrant de confidentialité en créant un tunnel &lt;acronym&gt;SSH&lt;/acronym&gt;:&lt;/p&gt;


&lt;pre&gt;ssh -L 1100:localhost:110 pop.example.com&lt;/pre&gt;


&lt;p&gt;Bien sur, ce cas de figure nécessite d'avoir un compte permettant une connexion &lt;acronym&gt;SSH&lt;/acronym&gt; sur &lt;code&gt;pop.example.com&lt;/code&gt;, ce qui n'est pas forcément le cas. Pour remédier a ceci, deux solutions: utiliser un relay qui possède un serveur &lt;acronym&gt;SSH&lt;/acronym&gt;, ou installer un serveur &lt;acronym&gt;SSH&lt;/acronym&gt; sur &lt;code&gt;startpoint&lt;/code&gt; pour s'en servir comme relai (&lt;code&gt;sudo apt-get install openssh-server&lt;/code&gt; sur toute distribution debian-like qui se respecte):&lt;/p&gt;


&lt;pre&gt;ssh -L 1100:pop.example.com:110 localhost&lt;/pre&gt;


&lt;p&gt;And voila, il n'y a plus qu'a indiquer à notre client mail que le pop se situe sur &lt;code&gt;localhost&lt;/code&gt; au port 1100, et le tour est joué :-)&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/10/20/Vous-prendrez-bien-un-peu-de-ssh-avec-votre-tunnel#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/10/20/Vous-prendrez-bien-un-peu-de-ssh-avec-votre-tunnel#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/691</wfw:commentRss>
      </item>
    
  <item>
    <title>Bootstrap CLI</title>
    <link>http://mirmodynamics.com/post/2006/10/13/Bootstrap-CLI</link>
    <guid isPermaLink="false">urn:md5:1e9ff0bf3342af30f0bcc1b219d7f60a</guid>
    <pubDate>Fri, 13 Oct 2006 18:31:00 +0200</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Coding</category>
        <category>arborescence</category><category>bootstrap</category><category>CLI</category><category>howto</category><category>librairie</category><category>organisation</category><category>surclassage</category><category>zend framework</category>    
    <description>&lt;p&gt;Nous avons parcouru dernièrement la création du bootstrap &lt;acronym&gt;HTTP&lt;/acronym&gt; qui sert de socle à une application utilisant le Zend Framework. Le même principe peut s'appliquer aux scripts &lt;acronym&gt;CLI&lt;/acronym&gt;, mais comme les besoins sont fondamentalements différents, l'implémentation sera elle aussi complètement différente. Nous viserons les objectifs suivants:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ne pas être obligé d'executer le bootstrap en ligne de commande&lt;/li&gt;
&lt;li&gt;Simplifier au maximum l'écriture ultérieure des scripts &lt;acronym&gt;CLI&lt;/acronym&gt;&lt;/li&gt;
&lt;li&gt;Définir un jeu d'options de ligne de commande obligatoire&lt;/li&gt;
&lt;li&gt;Mettre en place un environnement d'execution&lt;/li&gt;
&lt;/ol&gt;    &lt;p&gt;La tentation serait de créer un système qui obligerait ce genre de commandes:&lt;/p&gt;


&lt;pre&gt;$ php batch/bootstrap.php monscript&lt;/pre&gt;


&lt;p&gt;Pour executer, par exemple, le script &lt;code&gt;batch/monscript.php&lt;/code&gt;. Cela simplifierait grandement les choses, mais c'est moche, et puis on peut faire autrement, donc on ne va pas se priver ! Nous utiliserons a cette fin la fonction magique &lt;code&gt;register_shutdown_function&lt;/code&gt;, qui s'occupera d'appeler une fonction qui executera les scripts &lt;em&gt;ad hoc&lt;/em&gt;.&lt;/p&gt;


&lt;p&gt;Avant d'aller plus loin, l'arborescence de fichiers que nous allons utiliser:&lt;/p&gt;


&lt;pre&gt;batch/
	monscript.php
	runtime.php
library/
	Zend.php
	My/
		Batch.php&lt;/pre&gt;


&lt;p&gt;&lt;code&gt;runtime.php&lt;/code&gt; sera le fichier à inclure dans chaque script, tandis que &lt;code&gt;My/Batch.php&lt;/code&gt; contiendra la classe d'abstraction &lt;code&gt;My_Batch&lt;/code&gt;, qui définira les comportements par défaut de nos scripts.&lt;/p&gt;


&lt;p&gt;Voici donc la première partie de notre bootstrap, &lt;code&gt;batch/runtime.php&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;ini_set('include_path', get_include_path().PATH_SEPARATOR.realpath(dirname(__FILE__).'/../library/'));

require_once 'Zend.php';
require_once 'My/Batch.php';

register_shutdown_function(array('My_Batch', 'runAll'));&lt;/pre&gt;


&lt;p&gt;Bien sur, cette méthode nous oblige à définir un format à respecter pour les fonctions à executer par la suite, nous partirons donc sur les bases suivantes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chaque batch doit être constitué d'une classe dont le nom commence par &lt;code&gt;My_Batch_&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Chaque batch doit posséder une méthode executable &lt;code&gt;run&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ce qui nous donne donc:&lt;/p&gt;


&lt;pre&gt;abstract class My_Batch {
	static public function runAll() {
		$classes = get_declared_classes();
		foreach($classes as $className) {
			if (preg_match('/^My_Batch_(.+)$/', $className, $matches) &amp;amp;&amp;amp; method_exists($className, 'run')) {
				try {
					$batch = new $className;
					$batch-&amp;gt;run();
				} catch (Exception $e) {
					die(sprintf(&amp;quot;%s: %s\n&amp;quot;, $matches[1], $e-&amp;gt;getMessage()));
				}
			}
		}
	}
	
	abstract public function run();
}&lt;/pre&gt;


&lt;p&gt;On en profite pour catcher toute Exception indésirable pour la transformer en un &lt;code&gt;die&lt;/code&gt;, bien plus lisible dans un terminal qu'une backtrace :-)&lt;/p&gt;


&lt;p&gt;Maintenant que nous avons résolu les points 1 et 2, attaquons nous à la suite. Le problème principal que j'ai rencontré lors de l'établissement d'un environnement d'execution, c'est que la gestion de la configuration repose en grande partie sur la valeur de &lt;code&gt;$_SERVER['HTTP_HOST']&lt;/code&gt;, qui n'est bien évidemment pas disponible en &lt;acronym&gt;CLI&lt;/acronym&gt; :-) Il me faut donc forcer le passage en argument du nom de la configuration à utiliser. C'est très simple à faire, grace a la méthode que nous avons employé: il suffit de vérifier la présence de cet argument dans le constructeur de &lt;code&gt;My_Batch&lt;/code&gt; :-)&lt;/p&gt;


&lt;pre&gt;public function __construct() {
	foreach($GLOBALS['argv'] as $i =&amp;gt; $arg) {
		switch ($arg) {
			case '--configname':
			case '-c':
				$this-&amp;gt;_args['configname'] = $GLOBALS['argv'][$i+1];
			break;
		}
	}
	if (!isset($this-&amp;gt;_args['configname'])) {
		throw new Exception('-c or --configname is mandatory');
	}
}&lt;/pre&gt;


&lt;p&gt;Voilà, le gros du travail est fait. Pour le reste, c'est la routine, mise en place d'un environnement avec &lt;code&gt;Zend_Config&lt;/code&gt; et &lt;code&gt;Zend_Db&lt;/code&gt;, a la suite dans le constructeur:&lt;/p&gt;


&lt;pre&gt;	$this-&amp;gt;_config = new Zend_Config(
		Zend_Config_Ini::load(
			dirname(__FILE__).'/../../app/config.ini',
			$this-&amp;gt;_args['configname']
		)
	);
	
	$this-&amp;gt;_db = Zend_Db::factory(
		$this-&amp;gt;_config-&amp;gt;db-&amp;gt;adapter,
		$this-&amp;gt;_config-&amp;gt;db-&amp;gt;config-&amp;gt;asArray()
	);
	
	Zend_Db_Table::setDefaultAdapter($this-&amp;gt;_db);&lt;/pre&gt;


&lt;p&gt;Enfin, voila un exemple de script utilisant ce bootstrap:&lt;/p&gt;


&lt;pre&gt;require_once 'path/to/runtime.php';

class My_Batch_MonScript extends My_Batch {
	public function run() {
		// le code ici
	}
}&lt;/pre&gt;


&lt;p&gt;And voila !&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/10/13/Bootstrap-CLI#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/10/13/Bootstrap-CLI#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/666</wfw:commentRss>
      </item>
    
  <item>
    <title>L'environnement d'execution</title>
    <link>http://mirmodynamics.com/post/2006/09/28/Lenvironnement-dexecution</link>
    <guid isPermaLink="false">urn:md5:e76eb4e24c2dc5797a4c4b451158f001</guid>
    <pubDate>Thu, 12 Oct 2006 21:51:00 +0200</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Coding</category>
        <category>bootstrap</category><category>environnement</category><category>howto</category><category>organisation</category><category>zend framework</category>    
    <description>&lt;p&gt;Voilà un article que j'avais déjà proposé sur un site a caractère privé, un peu remis au gout du jour et étoffé de quelques informations et ressources non négligeables. Nous verrons ici comment mettre en place un environement d'execution standard du Zend Framework, également appelé &lt;em&gt;bootstrap&lt;/em&gt; de l'autre coté de l'atlantique.&lt;/p&gt;    &lt;p&gt;Un petit dessin valant mieux qu'un long discours, entrons dans le vif du sujet. On assume ici un environnement préinstallé: Apache / PHP5 / MySQL, avec une copie du Zend Framework dans &lt;code&gt;/usr/share/zend/&lt;/code&gt;, ainsi que le &lt;code&gt;.htaccess&lt;/code&gt; suivant à la racine de votre site (il semblerait que cette dépendance à &lt;code&gt;mod_rewrite&lt;/code&gt; soit sur la liste des choses à éliminer avant la release):&lt;/p&gt;


&lt;pre&gt;RewriteEnfine On
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php&lt;/pre&gt;


&lt;p&gt;On peut également utiliser les règles suivantes, qui comportent l'avantage d'une plus grande simplicité pour intégrer des éléments d'application externe:&lt;/p&gt;


&lt;pre&gt;RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php&lt;/pre&gt;


&lt;h2&gt;L'environnement&lt;/h2&gt;


&lt;p&gt;Les plus perspicaces d'entre vous l'auront surement déjà deviné, le fichier &lt;code&gt;www/index.php&lt;/code&gt; servira de &lt;em&gt;bootstrap&lt;/em&gt;, c'est à dire de point d'entrée unique pour toute l'application. Le Zend Framework se chargera lui même de décortiquer l'&lt;acronym&gt;URL&lt;/acronym&gt; pour tenter de deviner ce à quoi l'utilisateur pouvait bien penser quand il a cliqué !&lt;/p&gt;


&lt;p&gt;Pour ce qui est de l'arborescence de fichiers conseillée, &lt;a href=&quot;http://fashion.hosmoz.net/blog/post/2006/09/16/Debuter-un-projet%3A-un-brin-dorganisation&quot;&gt;un peu d'organisation est recommandée&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;Pour utiliser le Zend Framework en toute quiétude, il nous faut nous assurer qu'il pourra accéder à ses propres composants. La première chose à faire est donc de modifier l'&lt;code&gt;include_path&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;set_include_path(get_include_path().PATH_SEPARATOR.realpath(dirname(__FILE__).'/../library/'));&lt;/pre&gt;


&lt;p&gt;Il n'est pas inutile également de prendre quelques précautions d'usage:&lt;/p&gt;


&lt;pre&gt;ini_set('error_reporting', E_ALL); # | E_STRICT);

if (get_magic_quotes_gpc()) {
	die('&amp;lt;strong&amp;gt;E_NOOB_ERROR&amp;lt;/strong&amp;gt;: magic_quotes_gpc must be turned off.');
}

set_magic_quotes_runtime(false);&lt;/pre&gt;


&lt;p&gt;&lt;em&gt;Last but not least&lt;/em&gt;, on charge la librairie &lt;code&gt;Zend&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;require_once 'Zend.php';&lt;/pre&gt;


&lt;p&gt;Ainsi préparés, nous pouvons nous plonger en toute quiétude dans la mise en place de quelques objets qui nous serons bien utiles tout au long du développement de notre application.&lt;/p&gt;


&lt;h2&gt;Les objets&lt;/h2&gt;


&lt;p&gt;La mise en place des objets est on ne peut plus claire. On configure le front controller (&lt;code&gt;Zend_Controller_Front&lt;/code&gt;) pour lui dire où trouver les &lt;em&gt;controllers&lt;/em&gt;, puis on configure les vues (&lt;code&gt;Zend_View&lt;/code&gt;) pour leur dire où trouver... les vues :-) On enregistre ensuite l'objet &lt;code&gt;$view&lt;/code&gt; dans le registre, qui n'est rien de plus qu'un endroit pratique où stocker des objets/données pour y avoir accès plus tard (&lt;code&gt;Zend::register($name, $value)&lt;/code&gt; et &lt;code&gt;$var = Zend::registry($name);&lt;/code&gt;).&lt;/p&gt;


&lt;p&gt;Une petite liste (non exhaustive) d'objets interressants à stocker dans le registre:&lt;/p&gt;


&lt;h3&gt;Zend_Db&lt;/h3&gt;


&lt;pre&gt;Zend::loadClass('Zend_Db');
Zend::loadClass('Zend_Db_Table');

$params = array(
	'host' =&amp;gt; 'localhost',
	'username' =&amp;gt; 'someobscureusername',
	'password' =&amp;gt; 'someobscurepassword',
	'dbname' =&amp;gt; 'yourdbname'
);

$db = Zend_Db::factory('PDO_MYSQL',$params);
Zend_Db_Table::setDefaultAdapter($db);

Zend::register('db', $db);&lt;/pre&gt;


&lt;h3&gt;Zend_Config&lt;/h3&gt;


&lt;p&gt;Je vous renvois à mon article sur la &lt;a href=&quot;http://fashion.hosmoz.net/blog/post/2006/09/04/Gestion-de-la-configuration&quot;&gt;gestion de la configuration&lt;/a&gt; :-)&lt;/p&gt;


&lt;h3&gt;Zend_View&lt;/h3&gt;


&lt;pre&gt;Zend::loadClass('Zend_View');

$view = new Zend_View;
$view-&amp;gt;setScriptPath(realpath(dirname(__FILE__).'/../app/views/'));

Zend::register('view', $view);&lt;/pre&gt;


&lt;h2&gt;Le Dispatch&lt;/h2&gt;


&lt;p&gt;Dernière étape, le dispatch, qui utilise les objets &lt;code&gt;Zend_Controller_Router&lt;/code&gt; et &lt;code&gt;Zend_Controller_Dispatcher&lt;/code&gt;. Ces deux objets sont au coeur du processus de sélection du controller à executer. Le Router va déterminer, à partir de l'environnement (en général l'URL, via $_SERVER['REQUEST_URI'] par exemple) quelle action executer et dans quel controller, tandis que le Dispatcher va s'occuper lui de les trouver (par exemple dire FooController::bar(), dans controllers/FooController.php).&lt;/p&gt;


&lt;p&gt;Le Zend Framework gère en natif les friendly urls, et ça c'est chouette. Par exemple: les urls suivantes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;http://example.com/foo/bar&lt;/li&gt;
&lt;li&gt;http://example.com/foo&lt;/li&gt;
&lt;li&gt;http://example.com/&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Seront analysées comme suit par le Routeur par défaut:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;controller: foo, action: bar&lt;/li&gt;
&lt;li&gt;controller: foo, action: index&lt;/li&gt;
&lt;li&gt;controller: index, action: index&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dernières choses à savoir sur la théorie:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;quand le controlleur est défini par l'url mais non trouvé par le &lt;code&gt;Dispatcher&lt;/code&gt;, celui ci execute &lt;code&gt;index/noRoute&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;les controllers sont des classes qui étendent &lt;code&gt;Zend_Controller_Action&lt;/code&gt; (ou une classe qui elle même l'étend)&lt;/li&gt;
&lt;li&gt;le Dispatcher par défaut va executer(en supposant une url type &lt;code&gt;http://example.org/foo/bar&lt;/code&gt;) &lt;code&gt;FooController::barAction&lt;/code&gt; dans &lt;code&gt;FooController.php&lt;/code&gt; (modulo le path déterminé avec &lt;code&gt;Zend_Controller_Front::setControllerPath&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Les vues&lt;/h2&gt;


&lt;p&gt;Dernier point de cette brève excursion dans le Zend Framework, les vues. Pas grand chose à en dire pour le moment, si ce n'est que par défaut l'objet Zend_View se contente d'include() les fichiers templates. Il parait que l'intégration avec des moteurs de template (Smarty par exemple) est très aisée, mais comme je ne suis pas fan de ce genre de choses, ce ne sera pas couvert ici :-)&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/09/28/Lenvironnement-dexecution#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/09/28/Lenvironnement-dexecution#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/626</wfw:commentRss>
      </item>
    
  <item>
    <title>Ma première impression sur XGL</title>
    <link>http://mirmodynamics.com/post/2006/10/03/Ma-premiere-impression-sur-XGL</link>
    <guid isPermaLink="false">urn:md5:60e3ea8cf9e08590e0213f9595acc399</guid>
    <pubDate>Tue, 03 Oct 2006 17:08:00 +0200</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Geekeries</category>
        <category>howto</category><category>interfaces utilisateurs</category><category>ubuntu</category>    
    <description>    &lt;p&gt;Bon voilà, je viens de suivre &lt;a href=&quot;http://wiki.beryl-project.org/index.php/Install/Ubuntu/Edgy/XGL&quot;&gt;ce howto&lt;/a&gt;, et ça marche très bien. Passé le stade &lt;em&gt;mais où sont mes efferalgans ?&lt;/em&gt;, on arrive rapidement au stade &lt;em&gt;mais où mon smecta ?&lt;/em&gt;, tellement c'est gerbant de fluidité. Bref, le desktop mappé sur un cube, c'est sympa, mais on lui preferrera de loin les effets moins psychédéliques tels que la &lt;em&gt;vraie&lt;/em&gt; transparence et les animations des fenetres (et encore).&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/10/03/Ma-premiere-impression-sur-XGL#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/10/03/Ma-premiere-impression-sur-XGL#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/640</wfw:commentRss>
      </item>
    
  <item>
    <title>Empecher la sauvegarde d'un mot de passe</title>
    <link>http://mirmodynamics.com/post/2006/09/24/Empecher-la-sauvegarde-dun-mot-de-passe</link>
    <guid isPermaLink="false">urn:md5:dad0b3837f014953dab7e916fc904221</guid>
    <pubDate>Sun, 24 Sep 2006 22:22:00 +0200</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Coding</category>
        <category>firefox</category><category>formulaires</category><category>howto</category><category>interfaces utilisateurs</category><category>optimisation</category>    
    <description>    &lt;p&gt;Le titre n'est pas très explicite, malheureusement, j'ai du mal a réfléchir ce soir. Nous parlons ici de la sauvegarde d'un mot de passe par Firefox quand on valide un formulaire contenant un champs &lt;code&gt;password&lt;/code&gt;. Je ne connais pas exactement les règles qui régissent ce comportement, mais quand on à un formulaire d'enregistrement, en général, cette &lt;em&gt;fonctionnalitée&lt;/em&gt; est plus une gène qu'autre chose. Pour la désactiver, il suffit donc d'affecter un attribut &lt;em&gt;autocomplete&lt;/em&gt; de valeur &lt;em&gt;off&lt;/em&gt; à votre champs:&lt;/p&gt;


&lt;pre&gt;&amp;lt;input type=&amp;quot;password&amp;quot; name=&amp;quot;password&amp;quot; id=&amp;quot;password&amp;quot; autocomplete=&amp;quot;off&amp;quot; /&amp;gt;&lt;/pre&gt;


&lt;p&gt;Je sais, ça fait beaucoup de password.&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/09/24/Empecher-la-sauvegarde-dun-mot-de-passe#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/09/24/Empecher-la-sauvegarde-dun-mot-de-passe#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/625</wfw:commentRss>
      </item>
    
  <item>
    <title>Automatisation des vues</title>
    <link>http://mirmodynamics.com/post/2006/08/30/Automatisation-des-vues</link>
    <guid isPermaLink="false">urn:md5:1d9d59b981f8ce7f914908cf7957d4da</guid>
    <pubDate>Wed, 30 Aug 2006 13:17:00 +0200</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Coding</category>
        <category>howto</category><category>MVC</category><category>php</category><category>zend framework</category>    
    <description>    &lt;p&gt;Le rebutement principal que j'ai eu au début avec le Zend Framework était l'impossibilité (a priori) d'automatiser le rendu des vues en fonction du controlleur et de l'action appelés. Mes pérénigrations webesques m'ont finalement fait entrevoir &lt;a href=&quot;http://svn.akrabat.com/svnvi.pl?file=Action.php&amp;amp;repos=AkCom&amp;amp;path=/trunk/library/AkCom/Controller&quot;&gt;la solution&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;EDIT&lt;/strong&gt;: mes nouvelles pérégrinations dans les sources du Zend Framework m'ont fait entrevoir &lt;a href=&quot;http://fashion.hosmoz.net/blog/post/2006/11/18/Howto%3A-Un-plugin-simple-pour-le-controller&quot;&gt;une meilleure solution&lt;/a&gt; :-)&lt;/p&gt;


&lt;p&gt;Tout se passe dans le destructeur du controlleur, et nous allons voir ici une version édulcorée de celle disponible dans le lien sus-cité. L'astuce qui sauve, c'est de savoir que l'objet &lt;code&gt;Controller&lt;/code&gt; possède un membre &lt;code&gt;_action&lt;/code&gt;, qui lui même propose (entre autres) deux méthodes bien utiles: &lt;code&gt;getControllerName&lt;/code&gt; et &lt;code&gt;getActionName&lt;/code&gt;. Il suffit donc de récupérer ces informations pour construire dynamiquement le chemin de la vue à utiliser pour un controlleur donné:&lt;/p&gt;


&lt;pre&gt;abstract class My_Controller_Action extends Zend_Controller_Action {
	public function __destruct() {
		$view = Zend::registry('view');
		$controller = $this-&amp;gt;_action-&amp;gt;getControllerName();
		$action = $this-&amp;gt;_action-&amp;gt;getActionName();
		$viewPath = sprintf('%s/%s.php', $controller, $action);
		try {
			echo $view-&amp;gt;render($viewPath);
		} catch (Exception $e) {
			trigger_error('Unable to render view: ' . $e-&amp;gt;getMessage(), E_USER_ERROR);
		}
	}
}&lt;/pre&gt;


&lt;p&gt;&lt;a href=&quot;http://fashion.hosmoz.net/public/sources/577.phps&quot;&gt;Fichier source&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;Ce controlleur requiert que vous ayez instancié, configuré et enregistré &lt;code&gt;Zend_View&lt;/code&gt; au préalable. Il ira, lors de sa destruction, chercher la vue dont le nom correspond à &lt;code&gt;controller/action.php&lt;/code&gt;, c'est à dire:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pour une URL du type &lt;code&gt;http://example.com/foo/bar/&lt;/code&gt;, &lt;code&gt;foo/bar.php&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;pour &lt;code&gt;http://example.com/&lt;/code&gt;, &lt;code&gt;index/index.php&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;pour &lt;code&gt;http://example.com/foo/&lt;/code&gt;, &lt;code&gt;foo/index.php&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pour une raison obscure, on ne peut pas laisser trainer l'éventuelle exception générée par &lt;code&gt;Zend_View&lt;/code&gt; dans le cas d'une vue inexistante. Cela entre en conflit avec une autre Exception qui traine, j'essayerai de tirer ça au clair :-)&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/08/30/Automatisation-des-vues#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/08/30/Automatisation-des-vues#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/577</wfw:commentRss>
      </item>
    
  <item>
    <title>Zend Framework et les sessions</title>
    <link>http://mirmodynamics.com/post/2006/08/12/Zend-Framework-et-les-sessions</link>
    <guid isPermaLink="false">urn:md5:a2cd430d79098a5196160a3a1f1bcc7c</guid>
    <pubDate>Sat, 12 Aug 2006 20:31:00 +0200</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Coding</category>
        <category>howto</category><category>php</category><category>session</category><category>zend framework</category>    
    <description>    &lt;p&gt;Bon voilà, j'ai commencé le développement d'un projet, et j'ai décidé d'utiliser le &lt;a href=&quot;http://framework.zend.com/&quot;&gt;Zend Framework&lt;/a&gt; (pour des raisons que je détaillerais dans un autre billet si ça vous interresse). Après mise en application du &lt;a href=&quot;http://www.phparch.com/zftut/&quot; hreflang=&quot;en&quot;&gt;tutoriel de Chris&lt;/a&gt;, Un premier problème s'est posé à moi: l'intégration des sessions. Après quelques recherches, on peut trouver &lt;a href=&quot;http://www.alexatnet.com/Blog/Index/2006-06-06/blog-cms-with-php-zend-framework-and-sqlite&quot;&gt;un blog développé avec ZF&lt;/a&gt;. Me ruant sur la partie d'admin, je découvre a ma grande stupeur des &lt;code&gt;session_start()&lt;/code&gt; incrustés a chaque méthode du controlleur, un peu comme ça:&lt;/p&gt;


&lt;pre&gt;class AdminController extends Zend_Controller_Action {
	function indexAction() {
		session_start();
	}
	function postAction() {
		session_start();
	}
}&lt;/pre&gt;


&lt;p&gt;Ce n'est évidemment pas une solution acceptable. J'ai opté pour ma part pour une surcharge de la classe &lt;code&gt;Zend_Controller_Action&lt;/code&gt;, avec un appel à &lt;code&gt;session_start()&lt;/code&gt; dans le constructeur:&lt;/p&gt;


&lt;pre&gt;abstract class My_Controller_Action extends Zend_Controller_Action {
	public function __construct() {
		session_start();
	}
}

class AdminController extends My_Controller_Action {
	function indexAction() {
		// code
	}
}&lt;/pre&gt;


&lt;p&gt;Bon là, la problèmatique de base est déjà résolue, mais on peut aller plus loin, et ajouter un destructeur:&lt;/p&gt;


&lt;pre&gt;abstract class My_Controller_Action extends Zend_Controller_Action {
	public function __construct() {
		session_start();
	}

	public function __destruct() {
		$session_id = session_id();
		if (!empty($session_id)) {
			session_write_close();
		}
	}
}&lt;/pre&gt;


&lt;p&gt;Voilà c'est tout pour aujourd'hui, la prochaine fois, on parlera de l'utilisation des &lt;code&gt;Views&lt;/code&gt;, et nottament, comment éviter un appel rébarbatif à &lt;code&gt;Zend::registry()&lt;/code&gt; dans chaque controlleur.&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/08/12/Zend-Framework-et-les-sessions#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/08/12/Zend-Framework-et-les-sessions#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/573</wfw:commentRss>
      </item>
    
  <item>
    <title>Faire du CLI en PHP</title>
    <link>http://mirmodynamics.com/post/2005/03/05/325-faire-du-cli-en-php</link>
    <guid isPermaLink="false">urn:md5:1325b5a09c1e84802f8f787b0c0c867f</guid>
    <pubDate>Sat, 05 Mar 2005 13:02:47 +0000</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Geekeries</category>
        <category>cli</category><category>howto</category><category>php</category>    
    <description>&lt;p&gt;Souvent les gens ne voient &lt;acronym&gt;PHP&lt;/acronym&gt; que comme un langage de script orienté web. Même si il est vrai que c'est son but premier, ce n'est pas la seule &lt;a href=&quot;http://fr.php.net/manual/en/intro-whatcando.php&quot; hreflang=&quot;en&quot;&gt;chose que &lt;acronym&gt;PHP&lt;/acronym&gt; peut faire&lt;/a&gt;. Penchons nous un peu sur l'utilisation de PHP en &lt;acronym title=&quot;Command Line Interface&quot;&gt;CLI&lt;/acronym&gt;, qui permet d'utiliser &lt;acronym&gt;PHP&lt;/acronym&gt; comme un langage de script &lt;em&gt;classique&lt;/em&gt;. Nous utiliserons pour se faire un système linux (ubuntu pour être précis) avec un binaire php-cli déjà installé.&lt;/p&gt;    &lt;h5&gt;Au commencement...&lt;/h5&gt;


&lt;p&gt;Au commencement est le &lt;em&gt;shebang&lt;/em&gt;. Qu'est-ce que c'est donc que ça&amp;nbsp;? C'est simplement la première ligne d'un script shell, celle qui indique au shell quel interpréteur utiliser pour executer le script. Elle début obligatoirement par les caractères &lt;code&gt;#!&lt;/code&gt; (qu'on appelle &lt;em&gt;shebang&lt;/em&gt;), suivis du chemin absolu de l'interpréteur. Dans la plupart des cas, l'intérpréteur &lt;acronym&gt;PHP&lt;/acronym&gt; se situe dans &lt;code&gt;/usr/bin&lt;/code&gt; et s'appelle &lt;code&gt;php&lt;/code&gt;, tout simplement. Ce qui nous donne donc:&lt;/p&gt;


&lt;pre&gt;#!/usr/bin/php&lt;/pre&gt;


&lt;p&gt;Bien sur, il est possible que votre interpréteur se situe ailleurs, &lt;code&gt;/usr/local/bin/php&lt;/code&gt; par exemple. Pour le trouve, vous pouvez utiliser la commande &lt;code&gt;which&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;ash@sushi:~$ which php
/usr/bin/php&lt;/pre&gt;


&lt;p&gt;Si cette commande ne retourne rien, c'est que php-cli n'est pas installé, et là ça dépasse le cadre de cet article :)&lt;/p&gt;


&lt;h5&gt;Un petit détour par la doc&lt;/h5&gt;


&lt;p&gt;A ce stade, il est bon d'aller voir ce que la doc a a nous dire sur &lt;a href=&quot;http://fr.php.net/manual/en/features.commandline.php&quot; hreflang=&quot;en&quot;&gt;l'utilisation de &lt;acronym&gt;PHP&lt;/acronym&gt; en ligne de commande&lt;/a&gt;. On y apprend toutes sortes de choses, a commencer par la compilation de &lt;acronym&gt;PHP&lt;/acronym&gt; en &lt;acronym&gt;CLI&lt;/acronym&gt;. On y apprend également que certaines valeurs du &lt;code&gt;php.ini&lt;/code&gt; sont différentes de celles de &lt;acronym&gt;PHP&lt;/acronym&gt; utilisé avec un server web, et nottement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;html_errors&lt;/code&gt;, pour ne pas afficher de &lt;acronym&gt;HTML&lt;/acronym&gt; dans les erreurs&lt;/li&gt;
&lt;li&gt;&lt;code&gt;max_execution_time&lt;/code&gt;, pour autoriser un temps d'execution infini&lt;/li&gt;
&lt;li&gt;&lt;code&gt;register_argc_argv&lt;/code&gt;, pour peupler les variables $argc et $argv, sur lesquelles nous reviendrons plus tard&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On y apprend aussi que php-cli enregistre automatiquement de nouvelles constantes telles que:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;STDIN&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;STDOUT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;STDERR&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Qui représentent respectivement l'entrée standard, la sortie standard, et la sortie d'erreur standard. Nous reviendronts sur ces constantes et leur utilisation plus tard.&lt;/p&gt;


&lt;p&gt;La dernière chose que nous retiendrons de cette page est que php-cli ne modifie pas le repertoire courant a l'execution d'un script. C'est à dire que si vous vous trouvez dans le répertoire &lt;code&gt;/tmp&lt;/code&gt;, et que vous executez &lt;code&gt;php /home/ash/foo.php&lt;/code&gt;, la fonction &lt;code&gt;&lt;a href=&quot;http://fr.php.net/getcwd&quot; hreflang=&quot;en&quot;&gt;getcwd&lt;/a&gt;&lt;/code&gt; (GET Current Working Directory) retournera &lt;code&gt;/tmp&lt;/code&gt;, et pas &lt;code&gt;/home/ash&lt;/code&gt;.&lt;/p&gt;


&lt;h5&gt;Notre premier script en &lt;acronym&gt;CLI&lt;/acronym&gt;&lt;/h5&gt;


&lt;p&gt;Il est grand temps d'entrer dans le vif du sujet et de faire notre premier script. Soyons originaux, créons un &lt;code&gt;hello_world.php&lt;/code&gt;, avec le code suivant:&lt;/p&gt;

&lt;pre&gt;&lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;#!/usr/bin/php&lt;/span&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;?php&lt;/span&gt; &lt;a href=&quot;http://www.php.net/print&quot;&gt;&lt;span style=&quot;color: #000066;&quot;&gt;print&lt;/span&gt;&lt;/a&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&quot;hello world !&quot;&lt;/span&gt;; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;/pre&gt;


&lt;p&gt;Une fois le fichier créé, nous avons deux possibilités pour l'executer. Soit lancer directement l'interpréteur &lt;acronym&gt;PHP&lt;/acronym&gt; en lui précisant le script a executer:&lt;/p&gt;


&lt;pre&gt;$ /usr/bin/php ./hello_world.php&lt;/pre&gt;


&lt;p&gt;Soit rendre le script executable et l'executer directement:&lt;/p&gt;


&lt;pre&gt;$ chmod +x ./hello_world.php
$ ./hello_world.php&lt;/pre&gt;


&lt;p&gt;Dans tous les cas, le résultat est le même:&lt;/p&gt;


&lt;pre&gt;hello world !&lt;/pre&gt;


&lt;p&gt;Facile non&amp;nbsp;? Notez bien que si vous décidez de rendre le script executable, vous n'aurez a executer la commande &lt;code&gt;chmod&lt;/code&gt; qu'une seule fois.&lt;/p&gt;


&lt;p&gt;Vous remarquerez surement que votre &lt;em&gt;prompt&lt;/em&gt; s'affiche directement après le &lt;em&gt;!&lt;/em&gt;, c'est normal, nous n'avons pas inclus de caractère de nouvelle ligne (&lt;code&gt;
&lt;/code&gt;) dans notre &lt;code&gt;print&lt;/code&gt;. Vous pouvez donc modifier le script ainsi:&lt;/p&gt;

&lt;pre&gt;&lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;#!/usr/bin/php&lt;/span&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;?php&lt;/span&gt; &lt;a href=&quot;http://www.php.net/print&quot;&gt;&lt;span style=&quot;color: #000066;&quot;&gt;print&lt;/span&gt;&lt;/a&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&quot;hello world !&lt;span style=&quot;color: #000099; font-weight: bold;&quot;&gt;
&lt;/span&gt;&quot;&lt;/span&gt;; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;/pre&gt;


&lt;p&gt;Et le tour est joué.&lt;/p&gt;


&lt;h5&gt;Utilisation de $argc et $argv&lt;/h5&gt;


&lt;p&gt;Tout ça c'est bien beau, mais un script c'est quand même mieux quand on peut lui passer des arguments. Et &lt;strong&gt;non&lt;/strong&gt;, executer &lt;code&gt;./hello_world.php?arg=value&lt;/code&gt; ne fonctionne pas :-) Comment faire alors&amp;nbsp;? Les variables &lt;code&gt;$argc&lt;/code&gt; et &lt;code&gt;$argv&lt;/code&gt; sont là pour ça.&lt;/p&gt;


&lt;p&gt;Pour passer des paramètres à un shell script, on utilise usuellement la syntaxe suivante:&lt;/p&gt;


&lt;pre&gt;$ ./script [arg [arg...]]&lt;/pre&gt;


&lt;p&gt;C'est comme cela que nous procéderons en PHP-CLI. La variable &lt;code&gt;$argc&lt;/code&gt; (ARGuments Count) contient le nombre de paramètres passés au script, tandis que la variable &lt;code&gt;$argv&lt;/code&gt; (ARGuments Values) est un &lt;code&gt;array&lt;/code&gt; contient les valeurs de ces arguments. Modifions donc notre script de tout à l'heure:&lt;/p&gt;

&lt;pre&gt;&lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;#!/usr/bin/php&lt;/span&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;a href=&quot;http://www.php.net/var_dump&quot;&gt;&lt;span style=&quot;color: #000066;&quot;&gt;var_dump&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;$argc&lt;/span&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;;
&lt;a href=&quot;http://www.php.net/print_r&quot;&gt;&lt;span style=&quot;color: #000066;&quot;&gt;print_r&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;$argv&lt;/span&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;/pre&gt;


&lt;p&gt;Et executons le en lui passant quelques paramètres:&lt;/p&gt;


&lt;pre&gt;$ ./hello_world.php foo bar&lt;/pre&gt;


&lt;p&gt;Voyons le résultat:&lt;/p&gt;


&lt;pre&gt;ash@sushi:~$ ./hello_world.php foo bar
int(3)
Array
(
    [0] =&amp;gt; ./hello_world.php
    [1] =&amp;gt; foo
    [2] =&amp;gt; bar
)&lt;/pre&gt;


&lt;p&gt;On remarque que le nom du script compte comme un argument.&lt;/p&gt;


&lt;h5&gt;Utilisation de STDIN&lt;/h5&gt;


&lt;p&gt;Ces constantes dont nous avons parlé plus tôt sont très importantes. Elles définissent les flux standards à votre disposition, mais nous ne nous interresserons qu'a &lt;code&gt;STDIN&lt;/code&gt; dans cet article.&lt;/p&gt;


&lt;p&gt;&lt;code&gt;STDIN&lt;/code&gt;  (STanDard INput) est l'entrée standard. C'est elle que vous devez utiliser que vous voulez interragir avec l'utilisateur. Par exemple pour lui faire entrer des données. Modifions encore une fois notre &lt;code&gt;hello_world.php&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;#!/usr/bin/php&lt;/span&gt;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;$name&lt;/span&gt; = &lt;a href=&quot;http://www.php.net/trim&quot;&gt;&lt;span style=&quot;color: #000066;&quot;&gt;trim&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;a href=&quot;http://www.php.net/fgets&quot;&gt;&lt;span style=&quot;color: #000066;&quot;&gt;fgets&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt;STDIN&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;;
&lt;a href=&quot;http://www.php.net/print&quot;&gt;&lt;span style=&quot;color: #000066;&quot;&gt;print&lt;/span&gt;&lt;/a&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&quot;hello $name !&lt;span style=&quot;color: #000099; font-weight: bold;&quot;&gt;
&lt;/span&gt;&quot;&lt;/span&gt;;
&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;/pre&gt;


&lt;p&gt;Et executons le:&lt;/p&gt;


&lt;pre&gt;ash@sushi:~$ ./hello_world.php 
geoffrey
hello geoffrey !&lt;/pre&gt;


&lt;p&gt;Le script a donc attendu que je tape quelque chose en terminant par un &lt;acronym&gt;CRLF&lt;/acronym&gt; (Cariage Return Line Feed, la touche Entrée quoi ;). J'ai donc tapé &lt;em&gt;geoffrey&lt;/em&gt;, et voilà. Notons l'utilisation de &lt;code&gt;&lt;a href=&quot;http://fr.php.net/trim&quot; hreflang=&quot;en&quot;&gt;trim&lt;/a&gt;&lt;/code&gt; pour supprimer le &lt;acronym&gt;CRLF&lt;/acronym&gt; en question.&lt;/p&gt;


&lt;h5&gt;Le mot de la fin&lt;/h5&gt;


&lt;p&gt;Voilà, avec ça, vous devriez avoir les bases nécessaire pour commencer a faire du PHP-CLI. Cela dit, cet article n'explore pas toutes les subtilités du &lt;acronym&gt;CLI&lt;/acronym&gt;, et une bonne lecture de documentation est fortement conseillée :)&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2005/03/05/325-faire-du-cli-en-php#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2005/03/05/325-faire-du-cli-en-php#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/323</wfw:commentRss>
      </item>
    
  <item>
    <title>L'édition efficace avec vim</title>
    <link>http://mirmodynamics.com/post/2004/05/08/150-ledition-efficace-avec-vim</link>
    <guid isPermaLink="false">urn:md5:04486fa67847b5722fa1f201113b4608</guid>
    <pubDate>Sat, 08 May 2004 23:20:02 +0000</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Ego</category>
        <category>howto</category><category>traduction</category><category>vim</category>    
    <description>&lt;p&gt;Encore une traduction d'un &lt;a href=&quot;http://jmcpherson.org/editing.html&quot; hreflang=&quot;en&quot;&gt;article&lt;/a&gt; de &lt;a href=&quot;http://jmcpherson.org&quot; hreflang=&quot;en&quot;&gt;Jonathan McPherson&lt;/a&gt;&amp;nbsp;! Cette fois l'article porte sur vim, l'éditeur de texte des décideurs pressés. Les remerciements vont cette fois à &lt;a href=&quot;http://socialz.org/&quot; hreflang=&quot;fr&quot;&gt;Grégoire Gilbert&lt;/a&gt; qui m'a traduit plus de la moitié de l'article quand même :)&lt;/p&gt;    &lt;blockquote&gt;&quot;To me, vi is Zen.&lt;br /&gt;
To use vi is to practice zen.&lt;br /&gt;
Every command is a koan.&lt;br /&gt;
Profound to the user,&lt;br /&gt;
unintelligible to the uninitiated.&lt;br /&gt;
You discover truth every time you use it.&quot;&lt;br /&gt;&lt;br /&gt;
--reddy@lion.austin.com&lt;/blockquote&gt;


&lt;p&gt;Ce tutoriel recquiert des connaissances de base de vim -- mode insertion, mode commande, charger et sauver des fichiers, etc. Il a pour but d'aider les novices à développer leurs compétences pour utiliser vi efficacement.&lt;/p&gt;


&lt;p&gt;Dans ce tutoriel, &amp;lt;C-X&amp;gt; signifie Ctrl-X -- c'est à dire, gardez la touche Ctrl enfoncée et appuyez sur X. Vous pouvez obtenir de l'aide sur la plupart des commandes utilisées en tapant &lt;em&gt;:help command&lt;/em&gt; dans vim, en remplaçant command par ce sur quoi vous voulez de l'aide.&lt;/p&gt;


&lt;h3&gt;Se déplacer efficacement&lt;/h3&gt;


&lt;h4&gt;Rester en dehors du mode insertion&lt;/h4&gt;


&lt;p&gt;En général, vous voulez passer le moins de temps possible dans le mode insertion de vim, car ce mode fait agir vim comme un stupide éditeur de texte. C'est pourquoi la plupart des novices passent tant de temps en mode insertion -- il rend vim facile à utiliser. Mais la vraie puissance de vim réside dans le mode commande&amp;nbsp;! Vous verrez que mieux vous connaitrez vim, moins vous passerez de temps en mode insertion.&lt;/p&gt;


&lt;h4&gt;Utilisez h, j, k et l&lt;/h4&gt;


&lt;p&gt;Le premier pas vers l'édition efficace avec vim est de vous sevrer des touches &lt;em&gt;flèches&lt;/em&gt;. Un des avantages du design de vim est que vous n'avez pas constamment besoin de bouger vos mains entre les touches &lt;em&gt;flèches&lt;/em&gt; et les touches &lt;em&gt;lettres&lt;/em&gt;; quand vous êtes en mode commande, les lettres h, j, k et l correspondent aux directions gauche, bas, haut et gauche respectivement. Cela nécessite un peu d'entraïnement pour s'y habituer, mais vous verrez la différence quand vous y serez habitué.&lt;/p&gt;


&lt;p&gt;Quand vous éditez un e-mail ou un autre texte formatté par paragraphes, vous remarquerez peut-être que les touches de direction sautent plus de lignes que vous ne le voudriez. C'est parceque vos paragraphes apparaissent comme une seule longue ligne dans vim. Tapez g avant h, j, k ou l pour bouger d'une ligne &lt;em&gt;écran&lt;/em&gt; plutôt que d'une ligne &lt;em&gt;virtuelle&lt;/em&gt;.&lt;/p&gt;


&lt;h4&gt;Utilisez les mouvements pour déplacer le curseur dans la ligne courante&lt;/h4&gt;


&lt;p&gt;La plupart des éditeurs n'ont que des commandes simples pour déplacer le curseur (gauche, haut, droite, bas, au début/à la fin de la ligne, etc). vim possède des commandes de déplacement très avancée; ces commandes sont appelées mouvements (&lt;acronym title=&quot;Note du Traducteur&quot;&gt;NdT&lt;/acronym&gt;: &lt;em&gt;motions&lt;/em&gt;). Quand le curseur bouge d'un point à un autre, le texte entre les points (points inclus) est considéré comme étant &lt;em&gt;parcouru&lt;/em&gt; (C'est important pour plus tard).&lt;/p&gt;


&lt;p&gt;Voici quelques uns des mouvements les plus utiles:&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;fx&lt;/dt&gt;
&lt;dd&gt;Déplace le curseur en avant jusqu'à la prochaine occurence du caractère x (bien entendu, x peut-être n'importe quel caractère). C'est une commande extèmement utile. Vous pouvez taper ; pour répéter la dernière commande f.&lt;/dd&gt;
&lt;dt&gt;tx&lt;/dt&gt;
&lt;dd&gt;Pareil que f, mais bouge le curseur juste avant le caractère, pas juste dessus (Très utile, vraiment).&lt;/dd&gt;
&lt;dt&gt;Fx&lt;/dt&gt;
&lt;dd&gt;Déplace le curseur en arrière jusqu'à la prochaine occurence de x sur la ligne courante.&lt;/dd&gt;
&lt;dt&gt;w&lt;/dt&gt;
&lt;dd&gt;Déplace le curseur en avant d'un mot.&lt;/dd&gt;
&lt;dt&gt;b&lt;/dt&gt;
&lt;dd&gt;Déplace le curseur en arrière d'un mot.&lt;/dd&gt;
&lt;dt&gt;0&lt;/dt&gt;
&lt;dd&gt;Déplace le curseur au début de la ligne courante.&lt;/dd&gt;
&lt;dt&gt;^&lt;/dt&gt;
&lt;dd&gt;Déplace le curseur sur le premier caractère de la ligne courante.&lt;/dd&gt;
&lt;dt&gt;$&lt;/dt&gt;
&lt;dd&gt;Déplace le curseur à la fin de la ligne courante.&lt;/dd&gt;
&lt;dt&gt;)&lt;/dt&gt;
&lt;dd&gt;Déplace le curseur en avant jusqu'à la prochaine phrase (Utile quand vous éditez un e-mail ou des documents textes).&lt;/dd&gt;
&lt;dt&gt;(&lt;/dt&gt;
&lt;dd&gt;Déplace le curseur en arrière jusqu'à la prochaine phrase.&lt;/dd&gt;
&lt;/dl&gt;

&lt;h4&gt;Se déplacer efficacement dans le fichier édité&lt;/h4&gt;


&lt;p&gt;vim possède de nombreuses commandes qui peuvent vous transporter où vous le souhaitez dans votre fichier -- il est rare que l'on ait à le parcourir manuellement. Les combinaisons de touches ci-dessous ne correspondent pas techniquement à des déplacements, si on considère qu'elles servent à se déplacer dans le fichier et non pas dans une ligne.&lt;/p&gt;


&lt;dl&gt;
&lt;dt&gt;&amp;lt;C-F&amp;gt;&lt;/dt&gt;
&lt;dd&gt;Fait avancer le curseur à l'écran de texte suivant.&lt;/dd&gt;
&lt;dt&gt;&amp;lt;C-B&amp;gt;&lt;/dt&gt;
&lt;dd&gt;Fait reculer le curseur à l'écran de texte précédent.&lt;/dd&gt;
&lt;dt&gt;numG&lt;/dt&gt;
&lt;dd&gt;Place le curseur à la ligne num.  (Par exemple, &lt;em&gt;10G&lt;/em&gt; déplace à la ligne 10.)&lt;/dd&gt;
&lt;dt&gt;gg&lt;/dt&gt;
&lt;dd&gt;Déplace le curseur au début du fichier.&lt;/dd&gt;
&lt;dt&gt;G&lt;/dt&gt;
&lt;dd&gt;Déplace le curseur à la fin du fichier.&lt;/dd&gt;
&lt;dt&gt;H&lt;/dt&gt;
&lt;dd&gt;Déplace le curseur en haut de l'écran.&lt;/dd&gt;
&lt;dt&gt;M&lt;/dt&gt;
&lt;dd&gt;Déplace le curseur au milieu de l'écran.&lt;/dd&gt;
&lt;dt&gt;L&lt;/dt&gt;
&lt;dd&gt;Déplace le curseur en bas de l'écran.&lt;/dd&gt;
&lt;dt&gt;*&lt;/dt&gt;
&lt;dd&gt;Lis la chaîne de caractères sous le curseur et déplace ce dernier à l'endroit suivant où elle apparait de nouveau. (Par exemple, si votre curseur se trouvait sur le mot &lt;em&gt;bob&lt;/em&gt;, le curseur se déplacerait jusqu'à la prochaine occurence de &lt;em&gt;bob&lt;/em&gt; dans votre fichier.)&lt;/dd&gt;
&lt;dt&gt;#&lt;/dt&gt;
&lt;dd&gt;Même chose que ci-dessus, sauf qu'il déplace le curseur sur l'occurence précédente.&lt;/dd&gt;
&lt;dt&gt;/text&lt;/dt&gt;
&lt;dd&gt;A partir de la position du curseur, trouve l'occurence suivante de la chaîne de caractères &lt;em&gt;text&lt;/em&gt; et s'y rend. Vous devrez presser la touche &lt;em&gt;Entrée&lt;/em&gt; pour exécuter la recherche. Pour ré-exécuter votre dernière recherche, tapez &lt;em&gt;n&lt;/em&gt; (pour &lt;em&gt;next occurance&lt;/em&gt; (&lt;acronym&gt;NdT&lt;/acronym&gt;: occurence suivante).)&lt;/dd&gt;
&lt;dt&gt;?text&lt;/dt&gt;
&lt;dd&gt;Même chose que /, mais cherche dans la direction opposée.&lt;/dd&gt;
&lt;dt&gt;ma&lt;/dt&gt;
&lt;dd&gt;Crée un signet nommé &quot;a&quot; référant à la position actuelle du curseur. Un signet peut être nommé par nimporte quelle lettre en minuscule. Vous ne voyez pas le signet, mais il est là&amp;nbsp;!&lt;/dd&gt;
&lt;dt&gt;`a&lt;/dt&gt;
&lt;dd&gt;Aller au signet &lt;em&gt;a&lt;/em&gt;. &lt;strong&gt;Important&lt;/strong&gt;: c'est une backquote et non pas une quote simple. La touche backquote s'obtient à l'aide de la combinaison de touches alt+7 (pavé principal) sur un clavier azerty.&lt;/dd&gt;
&lt;dt&gt;`.&lt;/dt&gt;
&lt;dd&gt;Aller à la dernière ligne que vous avez éditée. Cette fonction est très utile&amp;nbsp;! Si vous avez besoin de parcourir le fichier pour regarder quelque chose, vous pouvez revenir à l'endroit où vous vous trouviez sans avoir à utiliser de signet, en utilisant `.&lt;/dd&gt;
&lt;/dl&gt;

&lt;h3&gt;Saisir efficacement&lt;/h3&gt;


&lt;h4&gt;Utiliser la complétion de mots&lt;/h4&gt;


&lt;p&gt;vim a un système de complétion de mots très pratique. Cela signifie que vous pouvez ne taper qu'une partie d'un long mot, presser une touche, et vim fini de l'écrire pour vous. Par exemple, si vous avez une variable nommée &lt;em&gt;JeSuisUneVariableAvecUnNomImbuvable&lt;/em&gt; quelque part dans votre code, vous ne voudrez probablement pas taper son nom en entier à chaque fois que vous souhaitez l'utiliser.&lt;/p&gt;


&lt;p&gt;Pour utiliser la complétion de mots, tapez simplement les quelques premières lettres de la chaîne (pour notre exemple: JeSuisUn) et pressez &amp;lt;C-N&amp;gt; (cela signifie que vous devez maintenir enfoncé &lt;acronym title=&quot;Control&quot;&gt;Ctrl&lt;/acronym&gt; et taper N) ou &amp;lt;C-P&amp;gt;. Si vim ne vous donne pas le mot que vous souhaitez du premier coup, continuez d'essayer -- vim vous proposera toutes les complétions possibles qu'il trouvera.&lt;/p&gt;


&lt;h4&gt;Entrez intelligemment dans le mode d'insertion&lt;/h4&gt;


&lt;p&gt;La plupart des nouveaux utilisateurs de vim, entrent dans le mode d'insertion en tapant &lt;em&gt;i&lt;/em&gt;. Ca marche, mais c'est souvent inefficace car vi a un jeu de commandes permettant de basculer l'éditeur en mode d'insertion. Voici quelqu'unes des plus populaires:&lt;/p&gt;


&lt;dl&gt;
&lt;dt&gt;i&lt;/dt&gt;
&lt;dd&gt;Insère du texte à gauche du caractère courant.&lt;/dd&gt;
&lt;dt&gt;I&lt;/dt&gt;
&lt;dd&gt;Insère du texte au début de la ligne courante.&lt;/dd&gt;
&lt;dt&gt;a&lt;/dt&gt;
&lt;dd&gt;Insère du texte à droite du caractère courant.&lt;/dd&gt;
&lt;dt&gt;A&lt;/dt&gt;
&lt;dd&gt;Insère du texte à la fin de la ligne courante.&lt;/dd&gt;
&lt;dt&gt;o&lt;/dt&gt;
&lt;dd&gt;Crée une nouvelle ligne sous la ligne courante et y insère du texte.&lt;/dd&gt;
&lt;dt&gt;O&lt;/dt&gt;
&lt;dd&gt;Crée une nouvelle ligne au dessus de la ligne courante et y insère du texte.&lt;/dd&gt;
&lt;dt&gt;c{déplacement}&lt;/dt&gt;
&lt;dd&gt;Efface (change) le texte parcouru par le {déplacement} et insère du texte pour le remplacer. Par exemple, &lt;em&gt;c$&lt;/em&gt; effacera le texte du curseur à la fin de la ligne et entrera en mode d'insertion. &lt;em&gt;ct!&lt;/em&gt; effacera le texte à partir du curseur jusqu'au point d'exclamation suivant (sans l'inclure) et entrera en mode d'insertion. Le texte effacé est copié dans le presse-papier et peut être collé.&lt;/dd&gt;
&lt;dt&gt;d{motion}&lt;/dt&gt;
&lt;dd&gt;Efface le texte parcouru par le {déplacement} -- comme c{déplacement}, mais n'entre pas en mode d'insertion.&lt;/dd&gt;
&lt;/dl&gt;


&lt;h3&gt;Déplacer efficacement des blocs de texte&lt;/h3&gt;


&lt;h4&gt;Utiliser la sélection visuelle et les modes de sélection appropriés&lt;/h4&gt;


&lt;p&gt;A la différence de l'original vi, vim vous laisse mettre en exergue du texte et y exécuter des opérations. Il y a trois modes de sélection visuelle principaux (ce sont les modes de mise en exergue). Ces modes sont les suivants:&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;v&lt;/dt&gt;
&lt;dd&gt;Sélection &lt;em&gt;par caractère&lt;/em&gt;. C'est le mode de sélection que la plupart des gens utilisent, donc entraînez-vous avec avant d'essayer les autres.&lt;/dd&gt;
&lt;dt&gt;V&lt;/dt&gt;
&lt;dd&gt;Sélection &lt;em&gt;par ligne&lt;/em&gt;. Sélectionnera toujours des lignes entières. Plus pratique que le mode &lt;em&gt;par caractère&lt;/em&gt; quand vous désirez copier ou déplacer un groupe de ligne.&lt;/dd&gt;
&lt;dt&gt;&amp;lt;C-V&amp;gt;&lt;/dt&gt;
&lt;dd&gt;Sélection &lt;em&gt;par bloc&lt;/em&gt;. Extrêmement puissant et disponible dans très peu d'éditeurs. Vous pouvez sélectionner un bloc rectangulaire et tout le texte se trouvant à l'intérieur sera mis en exergue.&lt;/dd&gt;
&lt;/dl&gt;


&lt;p&gt;Toutes les touches de mouvement habituelles peuvent être utilisées -- donc, par exemple, &lt;em&gt;vwww&lt;/em&gt; entrera dans le mode de sélection visuelle et mettra en exergue les trois mots suivants. &lt;em&gt;Vjj&lt;/em&gt; entrera dans le mode de sélection visuelle &lt;em&gt;par ligne&lt;/em&gt; et mettra en exergue la ligne courante et les deux sous cette dernière.&lt;/p&gt;


&lt;h4&gt;Couper et copier à partir de sélections visuelles&lt;/h4&gt;


&lt;p&gt;Une fois que vous avez une sélection mise en exergue, vous voulez probablement en faire quelque chose. Quelques-une des commandes les plus utiles que vous pouvez utiliser quand une partie d'un texte est mise en évidence:&lt;/p&gt;


&lt;dl&gt;
&lt;dt&gt;d&lt;/dt&gt;
&lt;dd&gt;Coupe (efface) le texte mis en exergue et le met dans le presse-papier.&lt;/dd&gt;
&lt;dt&gt;y&lt;/dt&gt;
&lt;dd&gt;Copie (ou &lt;em&gt;yank&lt;/em&gt; (&lt;acronym&gt;NdT&lt;/acronym&gt;: couper sec) qui est un terme vim-èsque pour &lt;em&gt;copier&lt;/em&gt;) le texte mis en exergue dans le presse-papier.&lt;/dd&gt;
&lt;dt&gt;c&lt;/dt&gt;
&lt;dd&gt;Coupe le texte mis en exergue et le met dans le presse-papier. Comme &lt;em&gt;d&lt;/em&gt;, à l'exception qu'il laisse l'éditeur en mode d'insertion.&lt;/dd&gt;
&lt;/dl&gt;


&lt;h4&gt;Couper et copier à partir de sélections non-visuelles&lt;/h4&gt;


&lt;p&gt;Si vous savez exactement ce que vous voulez copier ou couper, vous pouvez le faire sans entrer dans le mode visuel. Vous gagnerez du temps.&lt;/p&gt;


&lt;dl&gt;
&lt;dt&gt;d{déplacement}&lt;/dt&gt;
&lt;dd&gt;Coupe le texte parcouru par le {déplacement} vers le presse-papier. Par exemple, &lt;em&gt;dw&lt;/em&gt; coupera un mot et &lt;em&gt;dfS&lt;/em&gt; coupera du curseur jusqu'à (en l'incluant) la prochaine lettre &lt;em&gt;S&lt;/em&gt; en majuscule de la ligne courante.&lt;/dd&gt;
&lt;dt&gt;y{déplacement}&lt;/dt&gt;
&lt;dd&gt;Copie le texte parcouru par le {déplacement}.&lt;/dd&gt;
&lt;dt&gt;c{déplacement}&lt;/dt&gt;
&lt;dd&gt;Coupe le texte parcouru par le {déplacement} et laisse l'éditeur en mode d'insertion.&lt;/dd&gt;
&lt;dt&gt;dd&lt;/dt&gt;
&lt;dd&gt;Coupe la ligne courante.&lt;/dd&gt;
&lt;dt&gt;yy&lt;/dt&gt;
&lt;dd&gt;Copie la ligne courante.&lt;/dd&gt;
&lt;dt&gt;cc&lt;/dt&gt;
&lt;dd&gt;Coupe la ligne courante et laisse l'éditeur en mode d'insertion.&lt;/dd&gt;
&lt;dt&gt;D&lt;/dt&gt;
&lt;dd&gt;Coupe du curseur à la fin de la ligne courante.&lt;/dd&gt;
&lt;dt&gt;Y&lt;/dt&gt;
&lt;dd&gt;&lt;em&gt;Yank&lt;/em&gt; la ligne entière, comme &lt;em&gt;yy&lt;/em&gt;. (Oui, c'est contradictoire! Vous pouvez utiliser &lt;em&gt;y$&lt;/em&gt; pour faire ce que vous attendiez d' &lt;em&gt;Y&lt;/em&gt;.)&lt;/dd&gt;
&lt;dt&gt;C&lt;/dt&gt;
&lt;dd&gt;Coupe du curseur à la fin de la ligne courante et laisse l'éditeur en mode d'insertion.&lt;/dd&gt;
&lt;dt&gt;x&lt;/dt&gt;
&lt;dd&gt;Coupe le caractère courant. (C'est, en quelque sorte, la touche d'effacement arrière du &lt;em&gt;mode-commande&lt;/em&gt;.)&lt;/dd&gt;
&lt;dt&gt;s&lt;/dt&gt;
&lt;dd&gt;Coupe le caractère courant et laisse l'éditeur en mode d'insertion.&lt;/dd&gt;
&lt;/dl&gt;


&lt;h4&gt;Coller&lt;/h4&gt;


&lt;p&gt;Coller est une chose simple. Mettez le curseur à l'endroit où vous voulez coller du texte et tapez &lt;em&gt;p&lt;/em&gt;.&lt;/p&gt;


&lt;h4&gt;Utiliser plusieurs presses-papier.&lt;/h4&gt;


&lt;p&gt;La plupart des éditeurs ont un seul presse-papier. vim en a bien plus; les presse-papiers dans vim sont appellés registres. Vous pouvez lister tous les registres définis actuellement et leurs contenus en tapant &lt;em&gt;:reg&lt;/em&gt;. Typiquement, vous utiliserez des registres en lettres minuscules; les autres étant utilisés par vim en internes et ne sont que rarement utiles.&lt;/p&gt;


&lt;p&gt;Pour utiliser un registre spécifique pour une opération de type &lt;em&gt;copier/coller&lt;/em&gt;, tapez simplement &quot;a avant la commande, où a est le registre que vous voulez utiliser.&lt;/p&gt;


&lt;p&gt;Par exemple, pour copier la ligne courante dans le registre k, vous pouvez taper &quot;kyy. (Vous pouvez aussi taper V&quot;ky. Pourquoi pas ?). Cette ligne restera dans le registre k jusqu'a ce que vous copiez spécifiquement quelque chose d'autre dans ce registre. Vous pouvez maintenant utiliser &quot;kp pour coller le texte se trouvant dans le registre k.&lt;/p&gt;


&lt;h3&gt;Eviter les répétitions.&lt;/h3&gt;


&lt;h4&gt;La stupéfiante commande .&lt;/h4&gt;


&lt;p&gt;Sous vi, taper . (un point) répettera la derniere commande que vous avez executé. Par exemple, si votre dernière commande était &lt;em&gt;dw&lt;/em&gt; (effacement de mot (&lt;acronym title=&quot;Note du Traducteur&quot;&gt;NdT&lt;/acronym&gt;: delete word), vi effacera un autre mot.&lt;/p&gt;


&lt;h4&gt;Utiliser les compteurs&lt;/h4&gt;


&lt;p&gt;Les compteurs sont une des plus puissantes et économiques (en temps) fonctionnalités de vim. Nimporte quelle commande peut être précédée d'un nombre. Le nombre dira à vim combien de fois exécuter la commande. Voici quelques exemples:&lt;/p&gt;


&lt;p&gt;3j déplacera le curseur vers le bas, de trois lignes.
10dd effacera dix lignes.&lt;/p&gt;


&lt;p&gt;y3&amp;amp;quote; copiera (&lt;em&gt;yank&lt;/em&gt;) du curseur jusqu'à la troisième &lt;em&gt;quotation mark&lt;/em&gt; (NDT: je laisse l'expression originale pour que vous puissiez comprendre la commande, mais il s'agit de guillemets) après le curseur, sur la ligne courante. Les compteurs sont utiles pour augmenter l'étendu d'un déplacement.&lt;/p&gt;


&lt;h4&gt;Enregistrement de macros&lt;/h4&gt;


&lt;p&gt;Occasionnellement, vous vous retrouverez à faire la même chose encore et encore sur des blocs de texte de votre document. vim vous laisse enregistrer une macro ad-hoc pour exécuter l'opération.&lt;/p&gt;


&lt;dl&gt;
&lt;dt&gt;qregister&lt;/dt&gt;
&lt;dd&gt;Commence l'enregistrement de macro dans le registre nommé register. Par exemple, &lt;em&gt;qa&lt;/em&gt; commence l'enregistrement et met la macro dans le registre a.&lt;/dd&gt;
&lt;dt&gt;q&lt;/dt&gt;
&lt;dd&gt;Fin de l'enregistrement.&lt;/dd&gt;
&lt;dt&gt;@register&lt;/dt&gt;
&lt;dd&gt;Rejoue la macro stockée dans le registre register. Par exemple, @a rejoue la macro du registre a.&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;Gardez en tête que les macros enregistrent simplement vos pressions de touches pour les rejouer ensuite. Il n'y a rien de magique. Enregistrer des macros est presque une forme d'art car il y a tellement de commandes qui accomplissent une tâche donnée sous vim, et vous devez choisir avec attention les commandes que vous utilisez pendant que votre macro enregistre, afin qu'elles marchent aux endroits où vous avez prévu d'utiliser la-dite macro.&lt;/p&gt;


&lt;h4&gt;Ecrire du code sous vim&lt;/h4&gt;


&lt;p&gt;vim  est un excellent éditeur de code source car il a de nombreuses fonctionnalités qui ont été spécifiquement conçues pour aider les développeurs. Voici quelques-unes des plus utiles:&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;]p&lt;/dt&gt;
&lt;dd&gt;Comme pour &lt;em&gt;p&lt;/em&gt;, mais ajuste automatiquement l'indentation du code collé pour correspondre au code dans lequel vous avez inséré. Essayez!&lt;/dd&gt;
&lt;dt&gt;%&lt;/dt&gt;
&lt;dd&gt;Mettre le curseur sur une acolade, un crochet ou une parenthèse et presser % enverra le curseur à l'acolade, au crochet ou à la parenthèse correspondant(e). C'est très pratique pour résoudre les problèmes de parsing liés à de multiples blocs de code imbriqués.&lt;/dd&gt;
&lt;dt&gt;&amp;gt;&amp;gt;&lt;/dt&gt;
&lt;dd&gt;Indente le code mis en exergue. (Voir la section plus haut, concernant la séléction efficace de texte. Si il n'y a pas de texte sélectionné, la ligne courante est indentée.)&lt;/dd&gt;
&lt;dt&gt;&amp;lt;&amp;lt;&lt;/dt&gt;
&lt;dd&gt;Comme &amp;gt;&amp;gt;, mais dés-indente.&lt;/dd&gt;
&lt;dt&gt;gd&lt;/dt&gt;
&lt;dd&gt;Aller à la ligne de définition (ou de déclaration) d'une variable&lt;/dd&gt;
&lt;dt&gt;K&lt;/dt&gt;
&lt;dd&gt;Aller à la page de manuel pour le mot actuellement sous le curseur. (Par exemple, si votre curseur est sur le mot &lt;em&gt;sleep&lt;/em&gt;, vous verrez la page de documentation de &lt;em&gt;sleep&lt;/em&gt; s'afficher.)&lt;/dd&gt;
&lt;/dl&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2004/05/08/150-ledition-efficace-avec-vim#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2004/05/08/150-ledition-efficace-avec-vim#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/150</wfw:commentRss>
      </item>
    
  <item>
    <title>GNU Screen</title>
    <link>http://mirmodynamics.com/post/2004/04/01/121-gnu-screen</link>
    <guid isPermaLink="false">urn:md5:c7fc295191e4b695df8d5fac8ef6725f</guid>
    <pubDate>Thu, 01 Apr 2004 20:40:00 +0000</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Ego</category>
        <category>howto</category><category>traduction</category>    
    <description>&lt;p&gt;Ce billet est une traduction d'un &lt;a href=&quot;http://www.kuro5hin.org/story/2004/3/9/16838/14935&quot; hreflang=&quot;en&quot;&gt;article&lt;/a&gt; que j'ai trouvé sur &lt;a href=&quot;http://www.kuro5hin.org&quot; hreflang=&quot;en&quot;&gt;kuro5hin&lt;/a&gt;. Ayant trouvé l'article très interressant, et me disant que &lt;em&gt;putain faudrait que je mette du stuff utile sur digital fashion un jour&lt;/em&gt;, j'ai contacté l'&lt;a href=&quot;http://www.jmcpherson.org/&quot; hreflang=&quot;en&quot;&gt;auteur&lt;/a&gt; qui s'est empressé de me donner l'autorisation de traduire et publier son article sur mon blog, ainsi qu'une &lt;a href=&quot;http://www.jmcpherson.org/screen.html&quot; hreflang=&quot;en&quot;&gt;version plus actuelle&lt;/a&gt; de l'article sur son site. C'est cette version que je vous livre ici traduite. C'est ma première &lt;em&gt;vraie&lt;/em&gt; traduction, donc soyez indulgent merci :) si vous rencontrez des fautes d'orthographe, de style, ou de tournure n'hésitez pas à le signaler dans les commentaires, je corrigerais en conséquence.&lt;/p&gt;


&lt;p&gt;Je tiens à remercier l'auteur, &lt;a href=&quot;http://www.jmcpherson.com&quot; hreflang=&quot;en&quot;&gt;Jonathan McPherson&lt;/a&gt;, pour avoir publié un si bon article et pour m'avoir autorisé à le traduire et à le publier, ainsi que &lt;a href=&quot;http://www.mattlab.com&quot; hreflang=&quot;fr&quot;&gt;Renaud Littolff&lt;/a&gt;, pour la relecture.&lt;/p&gt;


&lt;p&gt;Voilà, bonne lecture.&lt;/p&gt;    &lt;p&gt;&lt;em&gt;Cet article est d'abord paru quand je l'ai écris pour &lt;a href=&quot;http://www.kuro5hin.org&quot; hreflang=&quot;en&quot;&gt;kuro5hin&lt;/a&gt;. Si vous voulez lire la version originale de l'article avec des commentaires contenant des astuces utiles sur Screen, &lt;a href=&quot;http://www.kuro5hin.org/story/2004/3/9/16838/14935&quot; hreflang=&quot;en&quot;&gt;il est ici&lt;/a&gt;, archivé sur Kuro5hin.&lt;/em&gt;&lt;/p&gt;


&lt;p&gt;La plupart des systèmes d'exploitations modernes basés sur Unix (par exemple Linux, MacOS X, et BSD) sont livrés avec un petit utilitaire en mode console appelé GNU Screen. C'est un outil puissant entre les mains d'un guerrier de la ligne de commande, un véritable couteau suisse de l'interaction homme-ordinateur en mode console.&lt;/p&gt;


&lt;p&gt;Cet utilitaire, bien que d'une utilité considérable, reste utilisé par très peu de personnes. Pourquoi ? Peu de gens en connaissent seulement l'existence, et ceux-là comprennent rarement les problèmes qu'il résoud. Dans cet article, j'expliquerais ce que screen fait pour vous, et fournirais un jeu de commandes pour accomplir des tâches basiques avec screen. Je m'adresse ici à ceux qui sont compétents avec la ligne de commande mais qui n'ont peu ou pas d'expérience avec screen lui même.&lt;/p&gt;


&lt;h5&gt;Ce que screen fait&lt;/h5&gt;


&lt;p&gt;Screen peut-être décrit comme un &lt;em&gt;multiplexeur de terminal&lt;/em&gt;. En l'utilisant, vous pouvez executer toutes les applications en mode console -- commandes de shell interactives, applications basées sur curses, éditeurs de textes, etc. -- que vous voulez dans un seul terminal. C'est cela qui accroche la plupart des utilisateurs de screen. J'avais l'habitude de lancer une demi-douzaine de terminaux quand je me connectais à ma machine: j'en voulais un pour lire mes e-mails, un pour éditer mon code, un pour compiler mon code, un pour mon lecteur de news, un pour un shell sur mon hébergeur, et ainsi de suite. Maintenant, je lance un terminal et execute screen à l'intérieur. Problème résolu.&lt;/p&gt;


&lt;p&gt;L'autre fonctionnalitée cool de screen est sa capacité à détacher le terminal des programmes executés. Cela signifie que vous pouvez utiliser screen pour laisser tourner les programmes après avoir fermé accidentellement le terminal, ou même après vous être déconnecté et, plus tard, reprendre là où vous en étiez. Cela signifie que le concept de &lt;em&gt;session&lt;/em&gt; dans laquelle vous executé des programmes est une entité flottant librement que vous pouvez attacher à n'importe quel terminal depuis n'importe où, ou aucun terminal si vous le voulez.&lt;/p&gt;


&lt;h5&gt;Débuter avec screen: lancer des programmes et permutage de fenêtres&lt;/h5&gt;


&lt;p&gt;Lancez screen en tapant &lt;strong&gt;screen&lt;/strong&gt; dans votre shell preferré. Vous serez probablement accueilli par un message de bienvenue. Quittez le message de bienvenue et vous obtiendrez un prompt shell, qui ressemble beaucoup à ce que vous aviez avant de lancer screen. Que s'est-il passé ?&lt;/p&gt;


&lt;p&gt;Chaque programme qui tourne dans screen s'execute dans une fenêtre, et chaque fenêtre est identifié par un numéro unique. Screen a créé une nouvelle fenêtre, l'a numérotée 0, et a lancé un shell a l'intérieur. Tapez quelque chose dans votre nouvelle fenêtre pour pouvoir la reconnaître quand vous y repasserez plus tard.&lt;/p&gt;


&lt;p&gt;Maintenant créez une nouvelle fenêtre; ce sera la fenêtre 1. Pour cela, tapez &lt;strong&gt;C-a c&lt;/strong&gt;; c'est à dire, tapez &lt;strong&gt;Ctrl-a&lt;/strong&gt; puis tapez &lt;strong&gt;c&lt;/strong&gt; (mnemotechnique:&lt;em&gt;Create&lt;/em&gt;)&lt;/p&gt;


&lt;p&gt;Maintenant que vous avez deux fenêtres, essayez de basculer de l'une à l'autre. Pour cela, tapez C-a C-a, ce qui vous fera basculer à la fenêtre que vous utilisez avant celle en cours. D'autres méthodes de basculement utiles dont vous aurez besoin si vous comptez lancer plus de deux programmes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Utilisez &lt;strong&gt;C-a n&lt;/strong&gt; et &lt;strong&gt;C-a p&lt;/strong&gt; pour basculer respectivement vers la fenêtre suivante et précédente, par numéro.&lt;/li&gt;
&lt;li&gt;Utilisez &lt;strong&gt;C-a N&lt;/strong&gt;, où N est un numéro de 0 à 9, pour basculer vers la fenêtre correspondante.&lt;/li&gt;
&lt;li&gt;Utilisez &lt;strong&gt;C-a &amp;quot;&lt;/strong&gt; pour avoir une liste des fenêtres. Vous pouvez naviguer dans cette liste avec les flèches (ou en style vi, avec j et k), et activer une fenêtre en la mettant en surbrillance et en pressant Entrée. &lt;strong&gt;C-a w&lt;/strong&gt; vous donnera une petite liste non interactive des fenêtres.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Détacher et réattacher: la magie du découplage de terminal&lt;/h5&gt;


&lt;p&gt;Si vous avez effectuer l'exercice ci-dessus, vous avez créer une session screen. Vous pouvez vous détacher de cette session en pressant &lt;strong&gt;C-a d&lt;/strong&gt;. Vous pouvez aussi vous détacher juste en fermant l'émulateur de terminal qui contient la session. Cependant, gardez à l'esprit qu'aucune de ces manipulations ne termine votre session. Tout ce qu'elles font, c'est de détacher votre session du terminal courant. Tous les programmes qui sont lancés sous screen tournent encore. Vraiment.&lt;/p&gt;


&lt;p&gt;Essayez: fermez l'émulateur de terminal que vous utilisiez pour l'exercice ci-dessus. Puis, si vous le désirez, déloguez vous et reloguez vous. Démarrez un nouvel émulateur de terminal, et tapez &lt;strong&gt;screen -r&lt;/strong&gt; (r pour &lt;em&gt;reattach&lt;/em&gt;). Vous serez exactement là vous en étiez quand vous avez détaché la session.&lt;/p&gt;


&lt;p&gt;Vous pouvez surement imaginer moultes utilisations interressantes à cela. Vous pouvez lancer tous vos programmes console preferrés une fois et les laisser tourner dans une session screen persistante. Certaines personnes ont des &lt;em&gt;uptime de screen&lt;/em&gt; de plusieurs mois.&lt;/p&gt;


&lt;p&gt;Un autre d'exemple d'utilisation est d'avoir un &lt;em&gt;bureau distant&lt;/em&gt;. Vous pouvez détacher une session au travail, vous vous connecter à la machine depuis chez vous et réattacher la session. Très très pratique. Avec un peu de pratique, vous pouvez même avoir plusieurs terminaux attachés à la même session, très utile pour le travail collaboratif et les rencontres.&lt;/p&gt;


&lt;h5&gt;Copier, coller, et remonter dans le buffer&lt;/h5&gt;


&lt;p&gt;Screen se souvient d'un nombre configurable de lignes de buffer, et vous en aurez besoin car vous ne pourrez pas utiliser les fonctionnalités de défilement de votre émulateur de terminal en utilisant screen. Vous pouvez accéder au buffer en vous mettant en &lt;em&gt;mode copie&lt;/em&gt; (Copy Mode), en tapant &lt;strong&gt;C-a [&lt;/strong&gt;. Vous pouvez marquer du texte n'importe où dans le buffer et le coller avec &lt;strong&gt;C-a ]&lt;/strong&gt;. Screen est aussi capable d'écrire des fichiers de log, mais ceci dépasse le cadre de ce tutoriel.&lt;/p&gt;


&lt;h5&gt;Surveiller le silence et l'activité&lt;/h5&gt;


&lt;p&gt;Un des désavantage de faire tourner plusieurs programmes dans screen est que vous ne pouvez pas garder un oeil sur tous en même temps, puisqu'en général vous ne pouvez en voir qu'un seul à la fois (En fait, vous pouvez découper l'écran et voir plusieurs programmes à la fois, mais c'est un sujet avancé qui dépasse le cadre de ce tutoriel).  Pour aider à atténuer ce problème, screen possède une fonctionnalité qui permet de surveiller le silence d'une fenêtre -- utile pour savoir quand une compilation est terminée par exemple -- ou son activité -- utile pour savoir quand quelqu'un parle finalement dans votre channel &lt;acronym title=&quot;Internet Relay Chat&quot;&gt;IRC&lt;/acronym&gt; preferré par exemple.&lt;/p&gt;


&lt;p&gt;Pour commencer ou arrêter de surveiller une fenêtre pour un silence de 30 secondes, tapez &lt;strong&gt;C-a &lt;/strong&gt;_; pour commencer ou arrêter de surveiller l'activité d'une fenêtre, tapez &lt;strong&gt;C-a M&lt;/strong&gt;.&lt;/p&gt;


&lt;h5&gt;Le faire partir&lt;/h5&gt;


&lt;p&gt;Comme vous l'avez vu dans la section sur le déttachement et le réattachement, screen n'est pas facile à tuer. Vous ne pouvez pas juste fermer le terminal qui le contient (En fait vous pouvez, mais tous les programmes tournent encore sur votre système, prêts a être réattachés).&lt;/p&gt;


&lt;p&gt;A ma connaissance, le seul moyen de quitter screen en douceur (cad sans envoyer de méchants signaux aux processus qui ne méritent pas ça) est de fermer chaque fenêtre de screen. Quittez tous les programmes ou shells qui tournent dans une fenêtre, et elle se fermera. Quand le dernier programme qui tourne dans screen est terminé, screen lui même se termine. Vous pouvez forcer l'arret de screen avec &lt;strong&gt;C-a C-&lt;/strong&gt;_, mais je ne vous le recommande pas.&lt;/p&gt;


&lt;h5&gt;Autres trucs&lt;/h5&gt;


&lt;p&gt;Screen est capable de bien plus que ce que j'ai décris ci-dessus, mais c'est assez pour que vous débutiez. Vous pouvez taper &lt;strong&gt;C-a ?&lt;/strong&gt; pour obtenir une liste laconique des commandes disponibles quand vous êtes sous screen. La page man de screen contient pas mal d'informations aussi. Et voilà quelques ressources web si vous avez des questions:&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;http://groups.yahoo.com/group/gnu-screen/&quot; hreflang=&quot;en&quot;&gt;Yahoo GNU Screen Group&lt;/a&gt;&lt;br /&gt;
Une mailing-list à traffic relativement élevé pour screen. Beaucoup de personnes expérimentées trainent dessus.&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;http://www.guckes.net/screen/&quot; hreflang=&quot;en&quot;&gt;La page screen de Sven Guckes&lt;/a&gt;&lt;br /&gt;
Une autre vue d'ensemble; un peu plus laconique que celle ci.&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;http://www.gnu.org/software/screen/screen.html&quot; hreflang=&quot;en&quot;&gt;La page officielle de screen&lt;/a&gt;&lt;br /&gt;
Pas besoin d'explications. Les détails sont étonnemment clairsemés.&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;http://www.cis.ohio-state.edu/cgi-bin/info/info/screen,Top&quot; hreflang=&quot;en&quot;&gt;La page de manuel de screen&lt;/a&gt;&lt;br /&gt;
Formattée agréablement et divisée en sections. Bonne référence. N'oubliez pas de voir les sections sur &lt;strong&gt;.screenrc&lt;/strong&gt; pour customiser screen.&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;http://www4.informatik.uni-erlangen.de/~jnweiger/screen-faq.html&quot; hreflang=&quot;en&quot;&gt;Screen FAQ&lt;/a&gt;&lt;br /&gt;
Pas pour débutant, mais une bonne ressource pour régler les problèmes.&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2004/04/01/121-gnu-screen#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2004/04/01/121-gnu-screen#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/rss2/comments/121</wfw:commentRss>
      </item>
    
</channel>
</rss>