Overblog Suivre ce blog
Administration Créer mon blog
2 mars 2016 3 02 /03 /mars /2016 19:14

Chatting with a friend one of the last few days, I realized that Dub is an unknown tool, whereas it is certainly one of the best arguments in favor of D these days. I had to repair this injustice.

Introducing Dub

Dub, the D package manager is a masterpiece in D tooling world. It is the D counterpart to tools like Cargo in Rust, Pip in Python or CPAN in Perl.

Dub is written by Sönke Ludwig, the author of Vibe.d. It can be downloaded on http://code.dlang.org. There are different packages for different Linux distros, as well as precompiled binaries for Windows and OSX.

Dub replaces make and integrates with IDEs such as MonoDevelop's Mono-D plugin. It can also generate Visual D projects if you want to use Visual studio build system on Windows.

Creating a project

Let's suppose we want to create an awesome TodoList project. Our project will use sqlite to store lists. Let's create a project

$ mkdir todolist
$ cd todolist
$ dub init

The dub init command creates an empty project file named dub.sdl and a source directory containing an app.d source file:

        ├── dub.sdl
        └── source
            └── app.d

The source directory will contain the source code of your project. The app.d file is the file containing the main() function. For now, it is barely more thar a hello world file.

The dub.sdl file contains the project description in the SDLang (http://sdlang.org) format. This file could also be written in JSON in you prefer the JSON format. For now, its content is minimal:

name "todolist"
description "A minimal D application."
copyright "Copyright © 2016, olivier"
authors "olivier"

Dub homepage also contains a list of packages. By browsing them, you discover the d2sqlite3 package which is a binding to the sqlite C API. Let's tell Dub you want to use it in your project by adding the following line at the end of the dub.sdl file.

dependency "d2sqlite3" version=">=0.9.7"

Version 0.9.7 is the latest package version available at the time I write this post. The greater than sign before it tells Dub I want to be able to upgrade it to newer versions when they will be released. Let's try to build and run our project:

$ dub
Fetching d2sqlite3 0.9.7 (getting selected version)...
Placing d2sqlite3 0.9.7 to /home/olivier/.dub/packages/...
Performing "debug" build using dmd for x86_64.
d2sqlite3 0.9.7: building configuration "with-lib"...
todolist ~master: building configuration "application"...
Running ./todolist
Edit source/app.d to start your project.

Let's explain what has just happened. Dub has downloaded the application dependency, the d2sqlite3 package. This package was put into a local dub registry and compiled. If this package also had other dependencies, they would had been fetched and compiled too. Fortunately, for the sake of our basic example, I selected package with no dependency. The application
was compiled with the DMD compiler in debug configuration. The last line shows the output of our program, telling us to edit source/app.d to start our project.

Editing the code

Let's listen to what dub says and edit the app.d file. First I will import the d2sqlite3 module.

import d2sqlite3;

Dub takes care of passing the path to the modules it downloaded to the compiler for us, so we don't have to bother rememebering where they are (they are put in my /home/olivier/.dub/packages directory). Let's create our database file.

private void createDatabase(string filename)
    auto db = Database(filename);
    scope (success) db.commit();
    scope (failure) db.rollback();

    // create our tables

This code makes use of D's transactional features (AKA scope statement) to make sure the database is either committed or rolled back, but never half-baked. Let's now create our tables:

private void createListTable(ref Database db)

private void createEntryTable(ref Database db)
            ENTRY_VALUE TEXT,

Again, nothing really complicated here, this is just plain SQL, as I don't want to distract you by introducing complex database bindings or ORMs. This code should be pretty straightfoward. A list has a name and contains entries which have a position in the list and a textual value. Entries store a reference to the list they belong to as a foreign key.

Let's call the createDatabase function from main:

import std.file;

void main()
    if (!exists("todo.db"))

Save it and compile/run it again.

$ dub
Performing "debug" build using dmd for x86_64.
d2sqlite3 0.9.7: target for configuration "with-lib" is up to date.
todolist ~master: building configuration "application"...
To force a rebuild of up-to-date targets, run again with --force.
Running ./todolist

Dub tells me that the sqlite package is still up to date (fortunately!), then rebuilds and run the application. I now have a 5 kB todo.db file in my directory containing my database, meaning that my code did work:

        ├── dub.sdl
        ├── dub.selections.json
        ├── source
        │   └── app.d
        ├── todo.db
        └── todolist

This is the end of our small example. Its purpose was simply to show how easy it is to integrate packages with dub and start coding. I leave to you the complete implementation of the TodoList application if you are interested in this.

Publishing packages

Publishing a Dub package is fairly easy. You have to publish your project on GitHub or BitBucket and to register it into Dub (you need a Dub account, which is free). Then anyone who adds the name of your project as a dependency in her/her dub.sdl project file will automatically have the content of your git repository available to his/her project. Whenever you want to release a new version, you'll simply have to create a git tag in your repository, and your users will be warned about a new release the next time they recompile their project.

At the time of this writing, the Dub package index contains about 700 packages.


I hope this post did interest you enough to go and check out the Dub documentation available at http://code.dlang.org. You'll learn a ton of things I did not cover in this post, such as creating libraries or running unit test builds.

Dub makes D development a lot easier by managing dependencies and letting the developer focus on the important thing: the code. It is a really nice tool that every D coder should be aware of.

Repost 0
Published by Olivier - dans Programmation
commenter cet article
13 août 2015 4 13 /08 /août /2015 19:01

Hello folks,

I struggled to install GP6 on Ubuntu 14.04 64bits, but now it works nice.

Here are the commands I had to type:

sudo apt-get install lib32z1 lib32ncurses5 ib32bz2-1.0
sudo apt install libportaudio2:i386
dpkg-deb --fsys-tarfile gp6-full-linux-r11621.deb > gp6.tar
sudo tar -C / -xvf gp6.tar
sudo apt-get install libssl0.9.8:i386
sudo apt-get install libpulse0:i386
sudo apt-get install libxrender1:i386
sudo apt-get install libglib2.0-0:i386
sudo apt install libpng12-0:i386
sudo apt install libfreetype6:i386
sudo apt install libsm6:i386
sudo apt install libfontconfig1:i386
sudo apt install libxml2:i386
sudo apt-get install libasound2-plugins:i386

Hope it help anyone in the same situation as me.

Happy strumming.

Repost 0
Published by Olivier
commenter cet article
12 mars 2015 4 12 /03 /mars /2015 20:00

C'est avec une peine immense que j'ai appris la disparition de Sir Terry Pratchett aujourd'hui, l'écrivain britanique de 66 ans, auteur des annales du disque monde.


L'auteur avait une forme rare d'Alzheimer, et militait pour le droit de pouvoir partir dignement, au moment de son choix.


Au revoir Monsieur Pratchett, et merci pour tous ces fous-rires, ces souvenirs et ces joies ressenties à la lecture des trente cinq tomes des annales (je lis le dernier en ce moment). J'espère que la Mort vous a bien accueilli et qu'il* avait du curry.




Tokien est mort, J K Rowling a refusé, Philip Pullman était indisponible, Salut je suis Terry Pratchett –  Un T-Shirt que l'auteur portait souvait aux conventions auxquelles il se rendait.




* : Oui, la Mort est un homme.

Repost 0
Published by Olivier - dans News
commenter cet article
10 janvier 2015 6 10 /01 /janvier /2015 10:24


Repost 0
Published by Olivier - dans News
commenter cet article
6 novembre 2013 3 06 /11 /novembre /2013 20:22




Repost 0
Published by Olivier - dans Projets personnels
commenter cet article
8 septembre 2013 7 08 /09 /septembre /2013 17:45

Une des nouvelles fonctionnalités que j'ai ajoutées à Rossignol dans la version 0.2 est la cohabitation avec Firefox. Il ne s'agit bien évidemment pas d'une version de Rossignol réécrite en JavaScript et XUL, mais d'un ensemble de fonctionnalités ajoutées permettant d'interagir sans peine avec le navigateur.


État des lieux des flux avec Firefox

Lorsque l'on affiche un flux RSS ou Atom avec Firefox, celui-ci nous propose de s'y abonner, via son système de marque-pages dynamiques, mais propose aussi d'utiliser une application tierce pour cela. Il suffit alors de parcourir l'arborescence du disque et d'indiquer à Firefox l'exécutable à utiliser.




Lorsque l'on s'abonne à un flux de cette manière, Firefox se contente de lancer l'exécutable sélectionné et de lui passer comme paramètre l'URL du flux avec le préfixe d'URI feed :


 rossignol feed://www.monsite.com/flux.xml 


À charge alors à l'application de s'abonner le flux passé en paramètre. Jusqu'ici, tout va bien.

Ce qui se complique un petit peu, c'est ce qui se passe lorsque l'application en question est déjà en cours d'exécution. Il faut bien comprendre qu'en l'état actuel des choses, nous risquons d'avoir une instance de l'application avec N flux et une autre avec N+1 flux. Tout ce petit monde doit donc communiquer pour synchroniser sa configuration afin que :

  • L'instance 1 n'écrase pas la configuration de l'instance 2 avec la sienne (qui compte un flux de moins).
  • L'utilisateur ait toujours à l'écran quelque chose de cohérent par rapport à ses actions, et non pas un état antérieur celles-ci.


La solution retenue

Rossignol ne sauvegarde sa configuration qu'à la fermeture de l'application. Le cas n°1 pourrait donc se produire si l'utilisateur fermait la première instance de Rossignol après la deuxième. J'ai donc choisi volontairement d'interdire l'ouverture de plusieurs instances de Rossignol par un même utilisateur. Au démarrage, on vérifie que l'on est la seule instance en cours d'exécution, si c'est le cas, on démarre normalement. Sinon, on se connecte à l'autre instance par un mécanisme de communication interprocessus et on lui envoie nos arguments de ligne de commande avant de s'arrêter promptement.


Comment tester que la présence d'une autre instance de l'application ?

Sous Windows, il existe plusieurs possibilités, mais la solution recommandée par Microsoft est d'utiliser un Mutex nommé. Le nom du mutex doit être préfixé par « Global\ » pour indiquer au système que l'on veut un mutex visible pour tout le système.

 auto handle = CreateNamedMutexW(null, true, name);

if (handle is null)
// erreur
else if (GetLastError() == ERROR_ALREADY_EXISTS)
// une autre instance est en cours d'exécution
// On est la seule instance de l'application


Sous Linux, il existe une fonction similaire pour créer un sémaphore, mais ce n'est pas la solution que j'ai retenue. Il faut savoir que sous Linux, en cas de crash de l'application, le sémaphore n'est pas libéré. C'est à l'utilisateur de saisir une commande shell pour libérer le sémaphore. J'ai donc préféré utiliser un simple fichier ouvert en création exclusive.

 auto handle = open(name, O_WRONLY | O_CREAT | O_EXCL);
if (handle < 0)
if (errno == EEXIST)
// Une autre instance est en cours d'exécution
// erreur
// On est la seule instance de l'application


Si le programme venait à planter et à ne pas supprimer le fichier, l'utilisateur n'aura qu'à supprimer ce fichier, ce qui est beaucoup plus accessible pour lui. Si vous connaissez une méthode plus sûre que celle-là, je suis preneur.


Comment communiquer entre processus ?


Sous Windows, la communication entre les processus est assurée par un pipe nommé. C'est assez simple à mettre en œuvre, surtout pour une communication dans un seul sens (client vers serveur). Je vous épargne le code de gestion des erreurs :


 // Code serveur
// Creation d'un pipe
auto handle = CreateNamedPipeW(toUTF16z(name),

// Attente d'une connexion d'un client
auto success = ConnectNamedPipe(m_handle, null);

// Lecture d'un message
success = ReadFile(handle, buffer.ptr, buffer.length, &bytesRead, null);

// Déconnecte immédiatement le client

// Code client
// Création d'un pipe
auto handle = CreateFileW(toUTF16z(name),
// Envoi d'un message
auto success = WriteFile(m_handle,


Sous Linux, les pipes nommés sont assez différents conceptuellement de leur homonymes Windows. J'ai donc utilisé les sockets UNIX à la place, qui fonctionnent comme les pipes nommés sous Windows. Là aussi, pour des raisons de concision, j'ai enlevé le code de gestion des erreurs.


 // Code serveur
// Création d'un socket serveur
auto handle = socket(AF_UNIX, SOCK_STREAM, 0);
sockaddr_un local;
local.sun_family = AF_UNIX;
strcpy(cast(char*)local.sun_path.ptr, szName);
uint len = cast(uint)(strlen(name) + local.sun_family.sizeof);
auto success = bind(ipc.m_handle, cast(const sockaddr*)&local, len);

success = listen(ipc.m_handle, 1);

// Attente d'une connexion d'un client
sockaddr_un remote;
uint t = cast(uint)remote.sizeof;
auto client_handle = accept(m_handle, cast(sockaddr*)&remote, &t);

// lecture d'un message
auto bytesRead = recv(client_handle, buffer.ptr, buffer.length, 0);

// déconnecte immédiatement le client

// Code client
// Création d'un socket client
auto handle = socket(AF_UNIX, SOCK_STREAM, 0);

// connexion
sockaddr_un remote;
remote.sun_family = AF_UNIX;
strcpy(cast(char*)remote.sun_path, szName);
uint len = cast(uint)(strlen(szName) + remote.sun_family.sizeof);
auto success = connect(ipc.m_handle, cast(const sockaddr*)&remote, len);

// Envoi d'un message
auto bytesWritten = send(m_handle, msg.ptr, msg.length, 0);


La mise en place d'une bonne intégration de Rossignol dans le menu des flux de Firefox a nécessité quelques aménagements dans le code, notament du code spécifique à chaque plate-forme. La capacité de D à appeler du code C directement sans passer par un wrapper à la JNI ou P/Invoke prend ici tout son sens.


Comme en C++, le RAII reste la meilleure méthode pour s'assurer de la bonne libération des ressources, que ce soit en utilisant le destructeur d'une structure sur la pile ou l'instruction scope.

Repost 0
Published by Olivier - dans Projets personnels
commenter cet article
4 septembre 2013 3 04 /09 /septembre /2013 15:12


J'ai sorti hier une deuxième version alpha de Rossignol. Pour fêter cela, j'ai décidé de consacrer un autre petit billet à ce nouveau projet. Nous avions vu la dernière fois les choix que j'avais fait en matière de bibliothèque graphique et de parsing XML. Cette fois je vais vous parler de threading.

Garder une interface réactive


Dans un logiciel avec une interface graphique, la tâche principale de l'application est une boucle d'événements. L'application se contente d'attendre un message que lui envoie le gestionnaire de fenêtre (un événement), le traite et se remet en attente d'un message suivant. Selon le système, cette boucle de message peut prendre plusieurs formes, mais avec SWT, ça ressemble à ça :


while (!window.isDisposed())


  if (!display.readAndDispatch())





Si l'application met trop de temps à répondre à un événement, elle aura du retard pour traiter l'événement suivant. Les conséquences pour l'utilisateur en seront immédiates : l'interface du programme (ses fenêtres et boutons) ne s'actualisera plus pendant quelques temps. Elle ne réagira pas à aucune sollicitation. Elle sera comme figée et il semblera à l'utilisateur que le programme a planté, jusqu'à ce que le traitement sont terminé.


Pour pallier ce problème, une solution consiste à faire effectuer tous les traitements longs dans des threads séparés (on parle de « worker threads »). Ainsi, pendant que le thread principal continue de traiter les nouveaux messages qui lui arrivent, l'application peut effectuer des traitements longs. C'est pour cela que les ingénieurs de chez Microsoft, en concevant la nouvelle API Windows RT, ont imposé que toute opération pouvant prendre plus de 50μs se fasse dans un thread séparé. Même si je n'utilise pas leur API ni leur nouveau système d'exploitation, c'est une consigne que j'ai souhaité suivre pour la réalisation de Rossignol.


À l'issue de ces traitements, les worker threads ont souvent le besoin de modifier l'affichage de l'application, par exemple, pour afficher le résultat d'un calcul. Et c'est là que les choses se compliquent. La plupart des gestionnaires de fenêtre ne gèrent pas la modification concurrente de l'interface par des threads séparés. La plupart de bibliothèques imposent donc la contrainte suivante : toute modification de l'interface doit être faite dans le thread principal (celui qui s'occupe de la boucle de messages).


Chaque bibliothèque propose donc en général d'un mécanisme pour faire renvoyer du « travail à faire » d'un worker thread vers le thread principal. En SWT, ce sont les méthodes syncExec et asyncExec de la classe Display.


Tout ceci est fort joli, mais il s'agit d'une solution Java, un langage étranger à Rossignol (qui ne contient aucune ligne de Java). Voyons donc comment D gère les threads, dans tout ça…



Le threading en D



D est un langage moderne dont la première version stable est apparue après l'avènement des microprocesseurs multicœurs grand public. Il est a donc tout naturellement inclus les problématiques de gestion du multitâche dans son système de type. Les concepteurs de D ont fait plusieurs constats :

  • Les bugs liés au multithreading sont essentiellement dus à une mauvaise synchronisation des accès à des ressources partagées entre les threads.

  • Dans la plupart des langages, la mémoire est implicitement partagée entre les threads.


Dès lors, ils ont choisi d'inverser le problème en interdisant par défaut le partage de variable entre les threads :

  • Par défaut, les variables globales sont thread-local. Sauf si elles sont implicitement marquées shared (qui est un qualificateur de type).

  • Les constantes (objets immuables) sont implicitement partagées et n'ont pas besoin d'être synchronisées.

  • Les objets shared doivent faire l'objet de précautions particulières dans leur manipulation.


Le threading de bas niveau est implémenté dans DRuntime (modules core.*). C'est l'environnement d'exécution de D, qui est constitué de code spécifique à un système ou un compilateur donné. La classe core.thread.Thread en particulier se charge de créer un thread au moyen de sa méthode start. C'est le pendant de java.lang.Thread. C'est la solution à utiliser à bas niveau, si l'on veut avoir le maximum de contrôle ou si l'on doit écrire du code pas vraiment idiomatique, comme par exemple utiliser certaines fonctionnalités écrites à l'origine pour un autre langage.


Au-dessus de ceci, la bibliothèque standard (modules std.*) propose deux modules distincts.


Le premier s'appelle std.concurrency. C'est historiquement le premier à avoir été implémenté. Il propose un système de messagerie entre threads. Le module se charge de vérifier à la compilation que les threads ne puissent s'échanger que :

  • Des types valeurs

  • Des types références thread-safe (classes synchronized ou immutable par exemple).


Ces contraintes permettent de garantir que l'accès à des ressources partagées est explicite et contrôlé. Ce module est utile lorsqu'un nombre défini de threads hétérogènes ont des gros besoins de communication. C'est encore malgré tout un module d'assez bas niveau puisque la création de threads est explicite et contrôlée par l'utilisateur.


Le second module s'appelle std.parallelism. Celui-ci est basé sur des primitives de haut niveau : foreach parallèle, map et reduce parallèles, ainsi qu'un concept de tâches similaires aux futures et promises de C++11.


Si vous avez l'expérience du package java.util.concurrent de Java 5 ou de Grand Central Dispatch de Objective-C, vous serez également en terrain connu : la classe TaskPool se comporte de manière similaire à Executor de Java ou aux dispatch queues d'Apple : c'est une FIFO à laquelle on soumet des tâches à exécuter qui seront dispatchées automatiquement sur un nombre donné de threads.


Ce module est donc approprié lorsque la même opération doit être exécutée en parallèle sur des données différentes, ou qu'une opération doit être effectuée en tâche de fond avant d'être retournée à un thread bien spécifique.



Et Rossignol dans tout ça ?


Si je ne vous ai pas déjà perdus, vous aurez compris de quelles solutions on a besoin en développant une application DWT :

  • Pour toute tâche où l'on aurait besoin d'un java.lang.Thread ou si l'on doit contourner le système de type pour utiliser SWT, il faut utiliser core.thread.Thread.

  • Pour le reste, quand on a besoin d'un traitement long à lancer en tâche de fond, std.parallelism et ses classes Task et TaskPool font merveille.


Repost 0
Published by Olivier - dans Projets personnels
commenter cet article
30 août 2013 5 30 /08 /août /2013 13:21


Je prends la plume aujourd'hui pour vous présenter un nouveau projet sur lequel j'œuvre depuis environ un mois : Rossignol, un agrégateur de flux RSS pour environnements de bureau.




L'envie de tester un peu les bibliothèques d'interface utilisateur graphique en D m'a pris. D'après les forums, l'une des plus abouties est DWT, un binding de SWT, la bibliothèque du projet Eclipse, l'environnement de développement intégré populaire dans le monde Java. Point n'est question de Java ici, puisque DWT est 100% native, mais le code à écrire sera très Java-esque, et pas vraiment idiomatique.

Mais revenons à nos moutons, ou devrais-je dire, à nos rossignols. Quand j'ai vu avec quelle relative facilité j'arrivais à faire une interface graphique fonctionnelle avec DWT, il m'a pris l'envie de lancer un petit projet autour de ça. Rossignol était né.

Je n'ai jamais trouvé chaussure à mon pied en matière d'agrégateur RSS. Du coup, pourquoi ne pas faire le mien ? Après tout, ça ne doit pas être très compliqué…


XML, mon amour


Autant le dire tout de suite, le module std.xml de la bibliothèque standard de D est mauvais. Sa documentation le reconnait comme obsolète et voué à être remplacé par quelque chose de mieux. Dès lors, il me semblait totalement absurde de l'utiliser. J'avais donc le choix entre utiliser un binding vers une bibliothèque C/C++ existante et réécrire un parser moi-même. C'est cette dernière option que j'ai choisie.

Contrairement à C et C++, D a une manière bien à lui de gérer les chaines de caractères. Ce sont des tableaux de caractères Unicode immuables. En outre, les tableaux de D ont des propriétés intéressantes que n'ont pas les tableaux C :

  • Ils connaissent leur taille
  • Ils sont découpables en sous-tableaux (slices), un peu comme les listes en Python. Un slice est simplement une paire de pointeurs qui fonctionne comme une vue d'un ensemble plus grand.

Ces propriétés permettent de tirer quelques conclusions :

  • Dans un programme multithread, on n'a pas besoin de synchroniser les accès aux chaines de caractères. Elles peuvent être partagées librement entre les threads, puisqu'elles sont immuables.
  • Pour prendre une sous-chaine à partir d'une chaine plus grande, on ne copie pas celle-ci, on la slice (ce qui revient à copier deux pointeurs). Dans le cadre d'un parseur événementiel (à la SAX), cela augure d'excellentes performances par rapport au C (où il faut forcément faire une copie pour pouvoir rajouter le 0 terminal).

Ce sont ces deux conclusions m'ont incité à tenter d'écrire moi-même le parsing XML de Rossignol. XML n'étant pas un format atrocement compliqué, j'avais un prototype fonctionnel en moins d'une semaine. La prise en charge d'Unicode directement par le langage, la programmation par contrats et les tests unitaires intégrés sont les trois fonctionnalités de D que j'ai le plus appréciées durant cet exercice. Le langage permet de spécifier des contraintes à vérifier avant et après chaque brique de la chaine logicielle. Avec ça, dès que l'on casse quelque chose, on reçoit une exception AssertError au démarrage nous indiquant quelle contrainte a été violée, ce qui fait gagner un temps fou en mise au point.


DWT, la bibliothèque graphique


Venons en maintenant à DWT. Comme je l'ai déjà dit, c'est en quelque sorte un portage en D de SWT. On écrit du D comme si on écrivait du Java. Les langages étant très proches du point de vue syntaxique, on peut presque copier/coller les snippets de code de SWT et les recompiler tels quels. Ça rend la documentation très simple, c'est un bon point.

En revanche, le style Java n'est pas le meilleur qui soit pour D : devoir instancier une classe pour gérer un événement alors qu'on pourrait utiliser un delegate n'est pas optimal. En plus, cela nécessite d'utiliser le ramasse-miettes là où on pourrait s'en passer (allocation sur la pile pour les classes à sémantique de valeur comme Point ou Size, par exemple) : On met inutilement la pression sur le GC.

A contrario, certaines fonctionnalités de D sont les bienvenues. Là où  SWT prohibe l'héritage en Java de ses widgets, le alias this de D permet d'ajouter des fonctionnalités à une classe sans en dériver.

J'ai opté pour une interface épurée. Seules les fonctionnalités essentielles doivent être mises en avant. Nous autres geeks avons souvent le défaut de vouloir rajouter le plus de fonctionnalités possibles dans l'interface. Je crois que c'est un défaut. Il n'y a qu'à comparer les interfaces des navigateurs Web entre les années 1990 et les années 2010. Alors que le nombre de fonctionnalités a explosé, les interfaces se sont faites de moins en moins chargées et vont directement à l'essentiel. C'est cette ligne directrice que je me suis fixée pour ce projet. Je me refuse par exemple à rajouter une quatrième colonne dans le panneau de droite alors que j'aimerai bien pouvoir classer les articles par catégorie. Je vais devoir réfléchir à une autre manière de fournir cette fonctionnalité (les suggestions sont les bienvenues).


Le bazar des flux


Connaissez-vous cette petite BD xkcd sur les standards ? Et bien elle pourrait coller à merveille pour le monde merveilleux de la syndication de contenu Web. Si l'histoire de RSS vous intéresse, je vous suggère de lire sa page Wikipédia, mais pour faire les chose simplement, voici l'état des lieux des formats les plus utilisés aujourd'hui :

  • L'évolution historique du premier format RSS de Netscape est RSS 1.1 (RSS veut ici dire Rich Site Summary). Il utilise des éléments de l'espace de nom RDF et pallie souvent son manque de fonctionnalités avec des extensions, par exemple des tags du Dublin Core.
  • Le format RSS 2.0 (RSS voulant dire ici Really Simple Syndication) est le format le plus utilisé de nos jours. Il est incompatible avec le premier et fournit les fonctionnalités les plus courantes absentes de l'autre. Comme son nom l'indique, c'est un format simple.
  • Atom est un standard IETF (RFC 4287) dont la vocation est de fournir un format très détaillé et le plus exhaustif en fonctionnalités possible. Par exemple, un même article peut avoir plusieurs auteurs et/ou contributeurs, il sait gérer de multiples types de lien (internes et externes) ainsi que de multiples langues.

Autour de ces trois familles de flux gravitent des formats hybrides (comme des flux RSS 2.0 utilisant des dates issues du Dublin Core) ainsi que des microformats dédiés à une application particulière. Bref c'est le bazar ! :)




Voilà pour cette petite introduction à mon nouveau projet. Il y a encore beaucoup à dire mais je ne voudrais pas saturer mon auditoire. Je consacrerai un prochain billet à expliquer comment est géré le parallélisme dans Rossignol. Le langage D propose plusieurs approches du threading (de plus ou moins haut niveau) et je vous parlerai une prochaine fois des solutions que j'ai retenues.

Repost 0
Published by Olivier - dans Projets personnels
commenter cet article
2 juillet 2012 1 02 /07 /juillet /2012 19:13

J'ai finalement reçu les autocollants pour clavier Bépo que j'avais commandé chez Beaujoie. Ils sont arrivés dans une simple enveloppe au format lettre.






Comme vous pouvez de voir sur cette photo, les lettres E et T sont séparées des autres. la raison en est simple : ce sont les touches qui ont les ergots de repères pour les index (à la place des touches F et J en azerty). Les autres touches sont déjà dans leur ordre d'apparition sur le clavier. Comme je sais que je risque de les oublier, je les pose en priorité.






Les autocollants sont plutôt petits par rapport à mes doigts : j'utilise donc un coton-tige dont j'ai coupé une tête pour ler placer plus facilement. Et voilà le travail !





Au bout de quelques de patience, le clavier est enfin recouvert :





Je tiens à souligner la qualité des autocollants Beaujoie : j'ai fait quelques erreurs qui m'ont obligé à décoller plusieurs autocollants pour les recoller ailleurs : aucun problème n'est survenu, les autocollants se décollent sans se déchirer et se recollent sans problème. La qualité semble donc au rendez-vous !

Repost 0
Published by Olivier
commenter cet article
30 juin 2012 6 30 /06 /juin /2012 11:38




J'ai décidé il y a 2 semaines de changer la disposition de mon clavier pour passer au bépo. Le bépo est une disposition ergonomique et moderne pour le Français qui contrairement à l'azerty n'a pas été pensé pour préserver les tiges des machines à écrire du début du XXème siècle. Au contraire, le bépo minimise les efforts demandés pour écrire en Français. Les objectifs sont multiples :

  • Faciliter l'accès à certains caractères du français, comme les majuscules accentuées ou les « guillemets »
  • Améliorer la vitesse de frappe
  • Prévenir les maladies professionnelles liées à l'utilisation du clavier (TMS).


Les curieux pourront trouver plus d'informations à ce sujet sur le site officiel du projet Bépo.


Contrairement à ce que l'on pourrait penser, il n'est pas nécessaire de changer de clavier pour commencer à apprendre à taper en bépo. J'ai simplement téléchargé et installé le pilote pour Windows et Mac (la quasi totalité des distributions linux proposent le bépo en standard).  Le choix de la disposition a utiliser est alors proposé dans le tray (en bas à droite sou windows, en haut à droite sous Mac) :




Le pilote propose deux modes :

  • Bépo pur
  • Bépo avec azerty pour les raccourcis clavier (mode bépo-azerty), que j'utilise.

Évidemment, cela ne va pas effacer toutes les touches de mon clavier et réécrire les nouvelles inscriptions par dessus. J'utilise donc pour le moment un clavier azerty somme toute assez banal. L'objectif étant la frappe en aveugle, ce n'est dérangeant qu'au début.


Pour faciliter l'apprentissage, j'ai procédé par étapes :

  1. J'ai tout d'abord imprimé la carte du clavier, sur une feuille que j'ai plié de manière à ce qu'elle soit visible entre l'écran et le clavier.
  2. Je suis tout d'abord resté en azerty par défaut, ne basculant en bépo que pour faire mes exercices de frappe (quotidiens).
  3. Pour les exercices, j'ai tout d'abord utilisé le logiciel TIPP, avant d'opter pour XUL Typist.
  4. Au bout de deux semaines à fonctionner de la sorte, je me suis senti suffisamment à l'aise pour basculer en bépo par défaut, ne revenant en azerty que lorsque j'ai besoin de taper quelque chose en urgence.



Au bout d'une semaine d'utilisation, je connaissais assez bien la disposition du clavier (qui est plutôt logique) et je ne regardais pratiquement plus la feuille sur laquelle j'avais imprimé la carte du clavier (si ce n'est pour les caractère spéciaux et autres ponctuations).


Au bout de deux semaines, je frappe en moyenne en bépo à 23 mots/minutes (statistique relevée par XUL typist). C'est encore bas, mais suffisant pour les tâches courantes. Je frappe bien évidemment en aveugle à dix doigts, ce qui l'objectif du bépo. J'ai conservé mon poste professionnel en azerty, et ne suis en bépo qu'à la maison. L'utilisation de deux disposition ne semble pas être trop un problème, le cerveau semblant bien faire la distinction entre les deux (c'était, je l'avoue, une de mes principales réticences à basculer). Ce chiffre de 23 mots/minutes est parfaitement normal est reste dans la moyenne observée des gens qui basculent en bépo. La vitesse devant arriver au bout de quatre semaines environ.


J'ai conservé les ouvertures de sessions en azerty, n'étant pas assez à l'aise pour taper des mots de passes en aveugle en bépo.


J'ai commandé un jeu d'autocollants pour clavier destinés pour changer physiquement mon clavier :

  1. Si des amis passent chez moi et ont besoin d'utiliser mon ordinateur
  2. Pour les mots de passe
  3. Je trouve dommage que tout ce qui est inscrit sur mon clavier soit faux.


Je ferai sans doute un nouveau billet lorsque je les recevrai. D'ici là, mon niveau devrait s'être amélioré.

Repost 0
Published by Olivier
commenter cet article