David Madore's WebLog: 2008-09

This WebLog is bilingual, some entries are in English and others are in French. A few of them have a version in either language. Other than that, the French entries are not translations of the English ones or vice versa. Of course, if you understand only English, the English entries ought to be quite understandable without reading the French ones.

Ce WebLog est bilingue, certaines entrées sont en anglais et d'autres sont en français. Quelques-unes ont une version dans chaque langue. À part ça, les entrées en français ne sont pas des traductions de celles en anglais ou vice versa. Bien sûr, si vous ne comprenez que le français, les entrées en français devraient être assez compréhensibles sans lire celles en anglais.

Note that the first entry comes last! / Notez que la première entrée vient en dernier !

Index of all entries / Index de toutes les entréesXML (RSS 1.0) • Recent comments / Commentaires récents

Entries published in September 2008 / Entrées publiées en septembre 2008:

(Friday)

How to add a personal menu to Firefox

(I'm too busy to blog right now, so I'm just posting something I had written previously and was hoping to improve but didn't have the time to. I figured it was better to publish it as such—and rough at the edges—than to postpone indefinitely.)

Here's a quick HOWTO on how to add a personal menu to Firefox. The point, here, is not to publish a Firefox extension (there's already abundant doc on this subject) but, rather, to modify one's profile to personalize the menu system in a quick and (relatively) easy way. What follows should work on every operating system supported by Firefox, although I've only tested it on Unix; also, I will assume Firefox 3. I assume the reader has some basic knowledge of XML, and, of course, if you want to do anything useful in your menu you must know some JavaScript.

First, create a directory in which the menu files will reside. I suggest something like ~/firefox/mymenu/ and I will assume that name in what follows. It will be an easy thing to copy the content of this directory to other machines to distribute the menu extension on them; also, it will be relatively easy to turn this working directory into a bona fide (i.e., .xpi) Firefox extension, although I won't cover this here.

Next, create a file called install.rdf inside the menu's working directory (so, ~/firefox/mymenu/install.rdf). Model it as follows:

<?xml version="1.0" encoding="utf-8"?>
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
         xmlns:NS1="http://www.mozilla.org/2004/em-rdf#">
  <RDF:Description RDF:about="urn:mozilla:install-manifest">
    <NS1:id>mymenu@local</NS1:id>
    <NS1:name>My Local Menu Extension</NS1:name>
    <NS1:version>0.0.0.0.0.1</NS1:version>
    <NS1:creator>John Doe User</NS1:creator>
    <NS1:description>A local menu loaded with goodies!</NS1:description>
    <NS1:targetApplication>
      <RDF:Description>
        <NS1:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</NS1:id> <!-- firefox -->
        <NS1:minVersion>3.0</NS1:minVersion>
        <NS1:maxVersion>3.0.*</NS1:maxVersion>
      </RDF:Description>
    </NS1:targetApplication>
  </RDF:Description>
</RDF:RDF>

RDF is a bit arcane (see here if you want to learn more about it), but you don't need to understand it in order to write this: basically, what matters is that this files specifies a number of important properties of the extension we are defining (yes, we are defining a Firefox extension, albeit one which might remain purely local). The most important such property is NS1:id (actually the property's name is really http://www.mozilla.org/2004/em-rdf#id, but that doesn't matter here), which specifies a unique identifier for the extension: here I am calling it mymenu@local, which is fine if you don't expect it to ever become public—if you do, it's probably better to call it something like mymenu@mydomain.example.tld where mydomain.example.tld is some domain you own. Another possibility is to use a UUID such as {da0bfd29-39a2-44d5-8b58-8e9badbbec7a} (you can use the uuidgen program to create one; remember to enclose it in curly braces, as shown here), although UUIDs are obviously more difficult to type and remember. Other properties required in install.rdf are NS1:name (the human-readable name of the extension, as it will appear in the extension list) and NS1:version (the extension's version number; there are sophisticated rules to compare version numbers, but I suggest sticking to something very simple, i.e., a period-separated list of numbers which will be ordered component by component). The NS1:creator (creator's name) and NS1:description (one-line description of the extension) properties are optional, but I suggest filling them in anyway. Finally, NS1:targetApplication indicates which programs the extension is made to work with: here, {ec8030f7-c20a-464f-9b0e-13a3a9e97384} means Firefox, and the NS1:minVersion and NS1:maxVersion specify the minimal and maximal accepted versions of Firefox, here anything in the form 3.0 or 3.0.something will match (I suggest leaving it as such, and increasing NS1:maxVersion after testing with 3.1 when it comes out). If you mean to make your menu also work for Thunderbird, add another NS1:targetApplication block (don't reuse the previous one!) and specify {3550f703-e582-4d05-9a08-453d09bdfdc6} as NS1:id. For more information about what can go in the install.rdf file, see here on developer.mozilla.org and here on mozillazine.org.

After you've written the install.rdf file, the other important file which needs to be created is chrome.manifest (details about it here). Create it in the same directory (so ~/firefox/mymenu/chrome.manifest) and model it as follows:

content mymenu chrome/content/
overlay chrome://browser/content/browser.xul chrome://mymenu/content/mymenu.xul

What we're saying here is:

Now we need to create the ~/firefox/mymenu/chrome/content/mymenu.xul file with the actual menu. Here is a template for it:

<?xml version="1.0" encoding="utf-8"?>
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         xmlns:html="http://www.w3.org/1999/xhtml">
<script type="application/javascript">
// <![CDATA[
function StupidAlert() {
    alert("This is a stupid alert!");
}
// ]]>
</script>
<menubar id="main-menubar">
  <menu id="mymenu-menu" label="My Menu" accesskey="M">
    <menupopup>
      <menuitem label="Nop" accesskey="N" />
      <menuitem label="Stupid alert" accesskey="S" oncommand="StupidAlert()" />
    </menupopup>
  </menu>
</menubar>
</overlay>

This is, of course, an utterly stupid example, merely intended to demonstrate how the file can be written: here, we overlay the Firefox main menubar (the main-menubar is the key, here) with a new menu which is labeled My Menu (the first ‘M’ will be underlined and will serve as access key), which pops up with two items: the first is labeled Nop and does absolutely nothing, and the second is labeled Stupid alert and runs the JavaScript function StupidAlert() defined above (this is contrary to Mozilla good practice which demands that JavaScript code be separated from the XUL structure, and also that user-readable labels be separated so they can be i13zed, but when defining a personal menu one typically does not care about such practices).

The language in which this file is written is an instance of XML called XUL: to learn more about XUL you can start with this excellent tutorial, but you can also learn it the quick-and-dirty way by trying to imitate the Firefox XUL itself, which you can find in a file called browser.jar (you can extract it with unzip) somewhere in your Firefox installation directories (a typical directory under Linux would be /usr/share/firefox/chrome/browser.jar, but YMMV). Similarly, if you want your menu to do something useful, you need some JavaScript, and, more probably, you need some Mozilla-specific JavaScript: you'll find many examples of that here (you might also find this page useful if you need to access Firefox windows or their content).

But before you start coding away, there is one last thing that needs to be done: now that a basic menu has been created in ~/firefox/mymenu/, you still need to tell Firefox about its existence! To do that, stop all running Firefoxen, then go in the extensions/ subdirectory inside your profile directory (on Unix, that would typically be ~/.mozilla/firefox/*.default/extensions/), and create a file called mymenu@local (use the same name as the NS1:id of your extension, even if that means using curly braces around a UUID) which just contains one line:

~/firefox/mymenu

i.e., name of the directory in which your extension (and importantly, the install.rdf and chrome.manifest files) resides. When Firefox is next launched, it should tell you that a new extension has been installed and the menu should be visible. After that, whenever you modify something in the ~/firefox/mymenu/ directory, increment the version number in install.rdf and restart Firefox (while this is not always strictly necessary, it is definitely good practice to avoid confusion).

(vendredi)

Péripéties médicales avec une Klebsiella

Acte I

Mercredi matin il y a neuf jours (le 2008-08-27, donc), alors que j'étais de passage chez mes parents à Orsay, je me suis réveillé tôt avec un mal au ventre, qui n'a cessé d'empirer, évoluant vers une sensation de brûlure à l'estomac, accompagnée de nausées, puis de vomissements (si ce n'est que je n'avais pas grand-chose à vomir). J'ai passé la journée, une bouillotte sur le ventre, à me shooter au paracétamol. Le soir j'ai cru que j'allais un peu mieux et j'ai pris un léger bouillon et un fruit, mais mon état s'est de nouveau détériorié, mes vomissements se sont intensifiés, j'ai fait de la fièvre (38.6°C malgré le paracétamol) avec des frissons, et j'ai eu un énorme mal de tête (comme l'impression que ma tête était une grosse cloche et que mon pouls donnait des coups dedans à 100 battements par minute).

Je suis tout sauf héroïque face à la douleur (on le sait déjà), donc j'ai persuadé mon père de me conduire — vers 2h du matin le 28 — aux urgences de l'hôpital d'Orsay (je voulais initialement appeler SOS médecins, mais apparemment ça n'existe pas aussi loin qu'Orsay). Là j'ai été très bien reçu par une infirmière et un externe pas trop débordés et très gentils, on m'a mis sous perfusion pour me réhydrater et m'injecter du Primpéran et plus de paracétamol (et encore autre chose que j'oublie) et on a lancé quelques analyses. Les premiers résultats étaient normaux et je me sentais mieux, donc on m'a fait sortir vers 4h30 et je suis rentré chez moi avec une ordonnance symptomatique (sans antibiotiques, car a priori il se semblait agir d'une gastro-entérite virale). J'ai passé encore une journée peu agréable jeudi, et j'ai pu manger un peu le soir ; vendredi j'étais toujours un peu barbouillé, mais rapidement je me suis estimé guéri (et je suis rentré chez moi à Paris).

Acte II

Lundi 1er dans l'après-midi (alors que j'allais désormais parfaitement bien, et c'est toujours le cas) je reçois un coup de fil du service des urgences d'Orsay où je m'étais présenté, m'avertissant qu'une des hémocultures qu'on m'avait faites (c'est-à-dire des prélèvements sanguins qu'on met en culture pour détecter des bactéries) était retournée positive : on m'a trouvé une bactérie du genre Klebsiella dans le sang. (Enfin, je donne le nom, mais pour réussir à décoder ce que j'ai entendu par téléphone, il m'a fallu du temps à Googlifier des choses comme clef de ciel.) On me demande donc de revenir à l'hôpital pour analyses complémentaires — et éventuellement pour être mis sous antibiotiques. J'explique que je vais bien et que je n'ai pas vraiment envie de revenir à Orsay pour ça : on me suggère alors de me présenter aux urgences de l'hôpital le plus proche de chez moi, auquel ils faxeront le dossier.

Les urgences de la Pitié, vers 18h, si on n'est pas in articulo mortis, ça doit vouloir dire trois heures d'attente au bas mot avant d'avoir la moindre chance de voir un médecin. Je me suis donc dit que, pour épargner mon temps comme celui du personnel, je pourrais y revenir à une heure plus creuse : je m'y suis donc pointé à 3h du matin (le mardi 2 septembre, si vous suivez bien), et effectivement il n'y avait plus personne. Là, on m'a fait savoir, en gros, que je n'avais rien à y faire : que mon cas n'était pas urgent puisque visiblement je n'étais pas malade, qu'on ne pouvait rien pour moi sans les résultats des analyses, que ce n'était pas à eux de demander celles-ci à l'hôpital d'Orsay et que d'ailleurs à 3h du matin ce serait impossible (j'ai rétorqué que c'était un service d'urgences et qu'il tournait 24h/24h, labo compris, mais on ne m'a pas écouté), bref, que je n'avais pas à être là. J'ai répondu que, d'accord, j'étais désolé de faire perdre du temps à tout le monde parce qu'on m'avait expressément recommandé d'aller aux urgences de l'hôpital le plus proche, et que je voulais bien, moi, me présenter en médecine de ville ou bien à un autre service de l'hôpital, juste qu'on me dise quoi faire. On m'a alors renvoyé sur le service des maladies infectieuses (…parasitaires, tropicales et de santé publique), service du professeur Bricaire, dans le même hôpital.

Le lendemain (enfin, toujours le mardi 2), j'ai pris rendez-vous auprès du service en question : le plus tôt possible étant le vendredi 5 au matin — soit. Je demande le numéro de fax du service, qui fut apparemment difficile à retrouver, mais que j'ai obtenu. J'ai ensuite appelé l'hôpital d'Orsay pour leur demander d'envoyer les résultats des analyses au service des maladies infectieuses de la Pitié, à l'attention du médecin dont on m'avait donné le nom pour le rendez-vous.

Acte III

Ce matin j'arrive au rendez-vous (pile à l'heure) et voilà, évidemment, que personne n'a entendu parler de moi au service des maladies infectieuses. J'imagine que ce qui s'est passé est que la difficulté à trouver le numéro de fax a fait oublier le rendez-vous lui-même à la personne qui devait l'inscrire dans les registres, ou quelque chose comme ça. J'offre comme indice de ma bonne foi le fait que je connaisse le nom du médecin qui devait me recevoir. On finit par ajouter mon nom sur les listes et par me faire patienter. Heureusement, les fax de l'hôpital d'Orsay, eux, étaient bien arrivés.

Le médecin que j'ai enfin pu voir, et à laquelle j'ai fait subir le récit de mes aventures jusqu'à présent, m'a concédé que c'était une drôle d'histoire. D'après elle, normalement, une infection bactérienne de ce genre ne se guérit pas toute seule, donc il est bizarre que j'aille bien. J'ai demandé si un faux positif était possible, mais elle ne semblait pas y croire. Et elle prétend que l'hôpital d'Orsay n'aurait pas dû me laisser sortir. Bref, elle m'a mis sous antibiotiques : comme j'ai déjà fait par le passé une allergie à l'amoxicilline, elle m'a prescrit de la ciprofloxacine (j'ai de la chance, d'après l'antibiogramme réalisé à Orsay, la bactérie est sensible à tous les antibiotiques testés), à des doses néanmoins diminuées puisque je n'ai pas de symptômes. Et je dois reprendre rendez-vous une fois le traitement fini pour faire des nouvelles analyses (y compris pour contrôler la glycémie, qui était apparemment trop élevée dans les premières analyses, même si je n'étais pas vraiment à jeun), puis une troisième fois pour l'analyse des résultats.

À suivre, donc…

Continue to older entries. / Continuer à lire les entrées plus anciennes.


Entries by month / Entrées par mois:

2017 Jan 2017 Feb 2017 Mar 2017 Apr 2017 May 2017 Jun 2017 Jul 2017 Aug 2017 Sep 2017 Oct 2017 Nov 2017
2016 Jan 2016 Feb 2016 Mar 2016 Apr 2016 May 2016 Jun 2016 Jul 2016 Aug 2016 Sep 2016 Oct 2016 Nov 2016 Dec 2016
2015 Jan 2015 Feb 2015 Mar 2015 Apr 2015 May 2015 Jun 2015 Jul 2015 Aug 2015 Sep 2015 Oct 2015 Nov 2015 Dec 2015
2014 Jan 2014 Feb 2014 Mar 2014 Apr 2014 May 2014 Jun 2014 Jul 2014 Aug 2014 Sep 2014 Oct 2014 Nov 2014 Dec 2014
2013 Jan 2013 Feb 2013 Mar 2013 Apr 2013 May 2013 Jun 2013 Jul 2013 Aug 2013 Sep 2013 Oct 2013 Nov 2013 Dec 2013
2012 Jan 2012 Feb 2012 Mar 2012 Apr 2012 May 2012 Jun 2012 Jul 2012 Aug 2012 Sep 2012 Oct 2012 Nov 2012 Dec 2012
2011 Jan 2011 Feb 2011 Mar 2011 Apr 2011 May 2011 Jun 2011 Jul 2011 Aug 2011 Sep 2011 Oct 2011 Nov 2011 Dec 2011
2010 Jan 2010 Feb 2010 Mar 2010 Apr 2010 May 2010 Jun 2010 Jul 2010 Aug 2010 Sep 2010 Oct 2010 Nov 2010 Dec 2010
2009 Jan 2009 Feb 2009 Mar 2009 Apr 2009 May 2009 Jun 2009 Jul 2009 Aug 2009 Sep 2009 Oct 2009 Nov 2009 Dec 2009
2008 Jan 2008 Feb 2008 Mar 2008 Apr 2008 May 2008 Jun 2008 Jul 2008 Aug 2008 Sep 2008 Oct 2008 Nov 2008 Dec 2008
2007 Jan 2007 Feb 2007 Mar 2007 Apr 2007 May 2007 Jun 2007 Jul 2007 Aug 2007 Sep 2007 Oct 2007 Nov 2007 Dec 2007
2006 Jan 2006 Feb 2006 Mar 2006 Apr 2006 May 2006 Jun 2006 Jul 2006 Aug 2006 Sep 2006 Oct 2006 Nov 2006 Dec 2006
2005 Jan 2005 Feb 2005 Mar 2005 Apr 2005 May 2005 Jun 2005 Jul 2005 Aug 2005 Sep 2005 Oct 2005 Nov 2005 Dec 2005
2004 Jan 2004 Feb 2004 Mar 2004 Apr 2004 May 2004 Jun 2004 Jul 2004 Aug 2004 Sep 2004 Oct 2004 Nov 2004 Dec 2004
2003 May 2003 Jun 2003 Jul 2003 Aug 2003 Sep 2003 Oct 2003 Nov 2003 Dec 2003