Valhalla

Transformer Atom en un IDE Vala - Version 1.0.0

Le problème exposé dans ce sujet a été résolu.

Un logo que je n’ai absolument pas créé

Bonjour à tous !

Je suis Baptiste alias Bat’, développeur amateur. Je code surtout en JavaScript et Vala. Et ça tombe bien, puisque le projet que je vais vous présenter ici est lié à ces deux langages. :D

En savoir plus sur le projet

Genèse

Ce projet est né lorsqu’il y a quelque temps, j’en ai eu marre d’avoir l’autocomplétion par défaut d’Atom, mon éditeur de code, quand j’écrivais du Vala. Quand on vient du monde du C#, et qu’on a l’habitude de Visual Studio et d’IntelliSense, on a du mal à passer à Atom et son autocomplétion … sommaire. J’ai donc décidé d’apprendre à créer des packages pour Atom, et j’ai commencé le développement de Valhalla.

Généralités et avancement

Ce projet, Valhalla donc, est un package pour l’éditeur de code Atom écrit en JavaScript (ES6). Il est encore dans une phase de développement et reste expérimental : il est déjà utilisable, mais pas complet, parfois un peu lent ou bugué.

Valhalla n’est pas mon seul projet, et j’ai d’autres activités à côté, donc il se peut que le développement soit plus ou moins actif.

Pour le moment, voici ce qui a été fait :

  • On propose les espaces de noms disponibles lorsqu’on écrit une nouvelle directive using ;
  • On propose les variables et les méthodes locales, lorsqu’elles sont disponibles (au niveau de leur portée) ;
  • On propose les propriétés et les méthodes disponibles pour une variable locale, si on a écrit son nom ;
  • On propose les propriétés et les méthodes d’instance, quand on a écrit this. (fonction qui a tendance à être lente) ;
  • On affiche une erreur si on essaie d’utiliser this hors d’une classe ;
  • On propose une liste des classes disponibles quand on a écrit new auparavant ;
  • Il y a aussi un petit outil pour créer rapidement des nouvelles classes ou interfaces. Il est accessible à partir du menu Vala en haut de la fenêtre, dans le menu contextuel de l’éditeur, ou dans celui du navigateur de fichier (alias Tree View).

C’est déjà un bon début, mais il reste encore beaucoup à faire.

Objectifs personnels

Bon, pas grand-chose d’original ici … J’aimerai :

  • Apprendre des nouvelles choses, en JavaScript notamment, et sur les APIs d’Atom. Je compte aussi partager ces nouvelles connaissances, en faisant un tutoriel sur la création de packages pour Atom, un sujet assez mal documenté ;
  • M’amuser, puisque je fais ça par passion, ce n’est pas mon travail. Donc si le projet m’ennuie, il est tout à fait probable que je passe à autre chose pendant un certain temps ;
  • Mener ce projet à bien, ou au moins essayer. Ce projet peut avoir une fin, ou presque. En effet, une fois que tout ce que je veux implémenter le sera, les seules modifications qui seront faites seront de la correction de bugs. On peut donc le mener à bien, et c’est ce que je veux essayer de faire, parce que laisser un package à moitié terminé, alors que des gens l’utilisent en se disant que ça va s’améliorer … bof.

Le projet et son originalité

Un des gros problème de l’écosystème Vala est qu’il n’y a pas de bon éditeur pour le langage, multiplateforme et actif. Avec Valhalla, j’essaie de contrer ce problème. C’est aussi le seul package pour Atom qui fasse cela aujourd’hui, même si Vala avait déjà la coloration syntaxique que je vous conseille fortement d’utiliser en complément de Valhalla d’ailleurs.

Objectifs

Les objectifs du projet sont les suivants :

  • Offrir une autocomplétion, complète et intelligente pour le Vala dans Atom ;
  • Aider les développeurs avec des choses comme le refactoring ou la génération de fichiers ;
  • Aider les développeurs à repérer leurs erreurs, ou les parties qu’ils pourraient améliorer ;
  • Pourquoi pas, si ça n’est pas trop compliqué, proposer un débogueur pour le code Vala ;
  • Peut-être d’autres choses, que vous pouvez me suggérer. ;)

Bref, il y a du travail !

À vous de jouer !

Si je vous présente ce projet ici, c’est aussi parce que si vous testez et me faites vos retours, j’avancerai surement beaucoup plus vite. Donc si vous avez la gentillesse de tester, vous gagnerez … ma reconnaissance. :p

Pour tester, il faut bien-sûr disposer d’Atom. ensuite, vous pouvez exécuter la commande apm install valhalla ou aller dans les paramètres, puis Install et enfin rechercher Valhalla et l’installer.

Merci beaucoup à tous ceux qui prendront la peine de tester et de me faire leurs retours, même s’ils ne connaissent pas du tout Vala. :)

Quelques images pour la route

Aller, pour vous donner envie, voici quelques exemples de ce que fait Valhalla.

Autocomplétion des méthodes locales
Assistant de création de classes
Propriétés et méthodes d’une variable locale (un peu buggé)
Méthodes et propriétés d’instance

En savoir plus

Le projet est bien-sûr libre, et disponible sur GitHub (même si je préfère GitLab, mais on est obligé de passer par GitHub pour publier son package).

Et voilà, si vous avez des remarques, de suggestions, des questions ou autre, n’hésitez pas, ce sujet est avant tout pour ça. J’espère que ce petit projet vous aidera dans la création de vos propres projets. En tout cas merci de m’avoir lu, j’espère que vous avez envie de tester, ou de suivre ce projet. :)

apm install valhalla

+20 -0

Vipère comme nom ? Vaillance ? Vidal ? voilà ? Vicomte ?

qwerty

J'aime bien Vipère, même si on y associe quand même quelque chose de négatif … Enfin en fait ce n'est pas très grave, vu que la communauté Vala est majoritairement anglophone, personne ne comprendra. :p Sinon j'avais pensé à Vanille, mais faut voir … Si vous avez d'autres idées proposez, et je ferai un petit sondage pour voir laquelle plaît le plus. :)

C'est pas super original mais la plupart des packages Atom d'autocomplétion ont comme nom autocomplete-[nom du langage]. C'est moins stylé que Valhalla mais au moins t'es sûr que ton package sera téléchargé :)

+3 -0

C'est l'heure du verdict ! :pirate:

On a donc …

Rang Nom Votes
1 Valhalla 5
2 Velouté 3
3 Vanille 2
4 Vipère 0 (un +1 et un -1)
4 Aval-On 0
4 autocomplete-vala 0
4 Vanina 0 (un +1 et un -1)

C'est donc le nom Valhalla qui retenu ! Mais merci quand même à tous ceux qui ont proposé d'autres idées, toutes sympas. :)

+2 -0

Je viens de fixer le bug qu'on avait sur les propriétés et les méthodes de variables locales. Avant, on voyait aussi les méthodes locales, maintenant on voit seulement celles disponibles pour l'objet qu'on manipule.

Avant ça buggait

Maintenant, ça bug plus !

Je vais aussi essayer d'un peu plus uniformiser l'interface de suggestions, avec l'affichage des arguments à passer à une mthode par exemple, qui ne s'affiche pas toujours.

Bonjour tout le monde ! (ou plutôt bonsoir)

Pour comprendre le travail que je viens de terminer, il faut savoir qu'avant … maintenant, Valhalla utilisait deux parseurs de code différents : un pour les fichiers .vapi qui contiennent la description des APIs (qui était un peu mal fait), et un pour le code de l'utilisateur. J'ai fait en sorte qu'on en ai plus qu'un seul. Pour vous ça ne change rien, mai pour moi, ça veut dire environ 400 lignes de code à maintenir en moins, et c'est toujours ça de gagné. Cette unification m'a demandé une réécriture d'une bonne partie du moteur de suggestions, et certains bugs sont malheureusement apparus pendant ce travail. Mais je compte bien-sûr les fixer, dès que possible.

Il y a aussi des points positifs à cette refonte. Les performances ont par exemple étés légèrement améliorées (même si ça reste un gros point faible de Valhalla), et vous aurez maintenant l'affichage des arguments pour les méthodes d'instance.

J'en ai aussi profité pour ajouter plein de // TODO dans mon code, et maintenant je vois bien ce qu'il faut que je fasse pour avoir une meilleure autocomplétion (et il y a du travail, je peux vous le garantir :D ). Je vais donc continuer à travailler sur tout ça, je reviens bientôt avec des nouvelles fraîches. :)

Hello ZdS,

J’ai encore avancé aujourd’hui. Au programme, pas mal de petites améliorations de l’autocomplétion, mais la plupart ne sont pas très visibles. L’une des plus marquantes est que si vous créez une nouvelle instance d’une classe se trouvant dans un namespace qui n’a pas déjà été importé, le using UnNamespace; est ajouté automatiquement à la suite des autres. Les arguments sont aussi désormais proposés comme n’importe quelles autres variables locales, et on affiche leur documentation, s’ils en ont une.

Les arguments s’affichent dans la fonction, avec leur documentation.

J’ai aussi amélioré les performances, qui deviennent tout à fait correcte dans la plupart des cas. Par contre le lancement d’Atom est extrêmement ralenti par la lecture de tous les fichiers .vapi (une centaine par défaut). J’ai deux solutions pour lutter contre cela. La première serait de sérialiser les fichiers d’APIs parsé, et Atom me les rendrait au démarrage suivant. Seulement je ne sais pas si ça change grand-chose en terme de performances, puisqu’un fichier doit sûrement être lu la aussi. La seconde serait de ne charger que les .vapis que l’utilisateur veut, avec les plus utilisés (GLib, GTK+, Cairo, la SDL …) par défaut. Il me reste encore quelques // TODO1 à faire, et après, si les performances restent correctes, ce qui n’est pas gagné, je passerai à autre chose que de l’autocomplétion, comme le refactoring ou la détection d’erreurs en temps réel.


  1. Quelle belle façon de s’organiser, n’est-ce pas ? :D 

Salut tout le monde,

Quelques news du projet. Je viens de booster les performances aux démarrage, sans même avoir eu a utiliser une des deux techniques que j'avais évoqué la dernière fois. Pour ceux qui veulent connaître mon secret, il faut savoir que j'utilise beaucoup d'expressions régulières (Regex) pour parser le code Vala. Mais en JavaScript, quand on crée une Regex, elle est d'abord « compilée » et c'est surtout ça qui prends du temps. Jusqu'à présent, je recréait les mêmes Regex à chaque ligne de code que je parsait, et c'était donc très lent. Mais maintenant, elles sont créés une fois au lancement de Valhalla et n'ont pas à être recompilées.

Le lancement est plus rapide, mais il prends encore un peu de temps, il faudra quand même que je m'intéresse aux solutions que j'ai proposé la dernière fois.

Au niveau de l'autocomplétion, j'ai aussi résolu quelques bugs, notamment au niveau des variables locales qui étaient des génériques dont le type et le nom s'affichaient mal, tout est maintenant OK. Et on ne proposera plus une variable à un moment où elle n'a pas encore été déclarée.

Pas de variable locale avant sa déclaration1

Après avoir testé réellement Valhalla, en codant un peu sur Valse, je me suis rendu compte que la complétion comme elle est aujourd'hui n'est pas très utile, et que je peux faire beaucoup mieux. Je pense donc que je vais me focaliser d'abord là dessus, et une fois que j'aurai une autocomplétion digne d'IntelliSense2, je passerait à autre chose.


  1. Et oui, je suis passé à un thème sombre. 

  2. Il y a un petit peu de travail pour en arriver là … :-° 

C'est même assez simple si tu connais un peu JavaScript ou CoffeeScript. Comme je l'ai dit, je rédigerai sûrement un tutoriel sur la création de packages, mais en attendant, je vais te donner quelques pistes.

Déjà, il te faudra Atom, c'est mieux. :D Ensuite, tu vas lance cette commande qui va créer un nouveau package dans le dossier courant.

1
apm init -p mon-package-php 

Tu peux aussi préciser que tu veux du JavaScript (ES6) et pas du CoffeeScript comme c'est le cas par défaut, en rajoutant -s javascript. Ensuite, tu vas te retrouver avec un package Hello world, que tu peux admirer en lançant (ou rechargeant, avec Alt+Ctrl+R) Atom, puis en allant dans le menu Packages > mon-package-php > Toggle (je crois :p ). Tu peux t'amuser un peu à modifier les fichiers dans ./lib si tu veux.

Si tu veux proposer de l'autocomplétion, il faut que tu ailles dans ton package.json et que tu y ajoutes ceci.

1
2
3
4
5
6
7
"providedServices": {
  "autocomplete.provider": {
    "versions": {
      "2.0.0": "getProvider"
    }
  }
}

Ensuite, il faut que aille dans ./lib/mon-package-php.js (ou .coffee) et que tu ajoutes une méthode appelée getProvider dans l'objet principal, celui qui est exporté.

Elle doit retourner un objet qui ressemble à ça (je te conseille de le mettre dans un autre fichier. Si tu ne vois pas comment faire, regarde comment je m'organise).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{
    selector = '.text.html.php',
    inclusionPriority = 10,
    excludeLowerPriority = true,

    getSuggestions: ({editor, bufferPosition, scopeDescriptor, prefix, activatedManually}) => {
        return new Promise ((resolve) => {
            resolve ([
                {
                    text: 'Une suggestion',
                    type: 'function',
                    description: 'Hello !'
                }
            ]);
        });
    }
}

Ici, j'ai mis .text.html.php comme selector, autrement dit Atom demandera des suggestions dans le scope .text.html.php. Les deux propriétés suivantes évitent juste que les suggestions par défaut n'apparaissent. Ensuite, il y a la méthode getSuggestions qui sera appelée à chaque fois qu'Atom aura besoin des suggestions. Il faut renvoyer une promesse, qu'on résout, en lui passant un tableau contenant nos suggestions.

Mon exemple est vraiment le code minimal pour avoir quelque chose de visible. Il faudra sûrement ajouter un peu de logique à tout ça, pour rendre le tout plus intelligent. Là encore tu peux regarde comment je fais pour t'aider (bien que je sois en train de changer pas mal le coder pour l'optimiser).

Pour le format des suggestions, tu peux regarder du côté de la doc officielle.

Voilà, j'espère t'avoir aidé. Si tu as un problème, n'hésite pas à me contacter par MP, ou à créer un sujet sur le forum. :)

Parce que le package est écrit en JavaScript et pas en Vala, donc déjà ça complique un peu les choses, même si ça reste peut-être possible je pense grâce à GObject Introspection. Et puis aussi parce que ce qui est amusant c'est de faire son propre parseur, juste récupérer les valeurs qu'une bibliothèque nous donne, c'est efficace, mais pas très gratifiant. Quand à la visualisation des erreurs en temps réel, c'est au programme, et il y en a déjà une qui s'affiche : essaie de taper this hors d'une classe. ^^

En parlant du parseur justement, je suis en train de le réécrire pour optimiser tout ça (mon code était mal fait et c'est une raison supplémentaire qui faisait que c'était pas super rapide). J'en ait profité pour fixer certains bugs qu'on pouvait avoir dans des cas un peu particuliers (deux instruction sur la même ligne, etc). Ce gros changement n'est pas encore terminé, mais la prochaine version devrait vraiment améliorer les performances.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte