Discussion:
Motif de recherche pour une fonction C++
(trop ancien pour répondre)
Rémi Moyen
2009-02-25 15:44:25 UTC
Permalink
Bonjour,

J'utilise Vim et j'essaye de trouver un motif de recherche qui
corresponde à toutes les définitions de fonctions dans un fichier de
code C++. Fondamentalement, c'est pas très dur, ce qui m'embête c'est
juste qu'à force d'ajouter des cas particuliers je suis en train de
copier toute la grammaire pour décider de ce qui peut être une
fonction ou pas...

Par exemple, j'avais commencé trivialement avec :
[^{]* {
Mais non seulement je matche aussi des lignes genre "if (...) {", mais
en plus je ne matche pas des définitions sur plusieurs lignes. Alors
j'ai rajouté des bouts, j'ai précisé des choses et en deux minutes
d'essais j'en arrive à :
\(\<\h\w*\>\s\+\)\=\(\<\h\w*\>::\)\=\<\h\w*\>(\n\=\(\s*\(const\s\+\)\=
\<\h\w*\>[&\*]\=\s*\<\h\w*\>,\=\|\n\)*\n\=)\s*\(const\)\=\s*{

Ce qui marche plutôt bien, sauf que non seulement ça commence à être
une usine à gaz incompréhensible, mais en plus ça ne matche toujours
pas tout (par exemple ça ne marche pas sur les constructeurs de
classes si il y a quelque chose entre ) et {, ou encore ça ne marche
pas si les arguments d'une fonction sont des pointeurs de pointeurs
(**), des réferences sur des pointeurs (*&), etc.).

Alors évidemment, je peux continuer à ajouter des choses pour tout ces
cas-là, mais je vais finir avec un truc immense et illisible.

D'où ma question : est-ce qu'il y a un moyen plus court de faire ça ?
J'imagine que dans tous les mappings/syntax highlighting/autres/... de
vim, je ne suis pas le premier à faire du C++ !

Accessoirement, est-ce qu'il y a un moyen simple de définir une sorte
de motif personnalisé que je puisse réutiliser ? Par exemple est-ce
que je peux dire que [une courte séquence de caractères de mon choix]
veut dire \<\h\w*\> ? Si j'utilise \1, \2 etc. je ne vais pas matcher
le motif de recherche, mais ce qui a déjà été matché par le n-ième
groupe.

Merci d'avance !
--
Rémi Moyen
Patrick Texier
2009-02-25 18:36:47 UTC
Permalink
Post by Rémi Moyen
J'utilise Vim et j'essaye de trouver un motif de recherche qui
corresponde à toutes les définitions de fonctions dans un fichier de
code C++.
C'est le but du programme ctags (rechercher les définitions et les
écrire dans un fichier), dont la version la plus utilisée est Exuberant
Ctags <http://ctags.sourceforge.net> et qui gère le C++.

Vim permet ensuite de retrouver la définition de la fonction où se
trouve le curseur, et doit y avoir un tas de scripts sur
<http://www.vim.org> qui utilisent ce fichier tags.
--
Patrick Texier

vim:syntax=mail:ai:ts=4:et:tw=72
Rémi Moyen
2009-02-26 09:44:30 UTC
Permalink
Post by Patrick Texier
Post by Rémi Moyen
J'utilise Vim et j'essaye de trouver un motif de recherche qui
corresponde à toutes les définitions de fonctions dans un fichier de
code C++.
C'est le but du programme ctags (rechercher les définitions et les
écrire dans un fichier), dont la version la plus utilisée est Exuberant
Ctags <http://ctags.sourceforge.net> et qui gère le C++.
Ah oui, j'avais déjà entendu parler de ctags, je n'ai plus qu'à
regarder réellement comment ça marche.
Post by Patrick Texier
Vim permet ensuite de retrouver la définition de la fonction où se
trouve le curseur, et doit y avoir un tas de scripts sur
<http://www.vim.org> qui utilisent ce fichier tags.
Ah, mais est-ce que ça veut dire qu'il faut lancer ctags puis regarder
un fichier qui contient le résultat ? Ça veut dire que si j'édite mon
fichier source, avant de pouvoir matcher une définition de fonction,
je dois relancer ctags ? Bon, je peux évidemment intégrer ça dans une
commande depuis vim, mais ça me semble un peu lourd...

Merci de l'info !
--
Rémi Moyen
Luc Hermitte
2009-02-25 19:49:52 UTC
Permalink
Post by Rémi Moyen
Bonjour,
J'utilise Vim et j'essaye de trouver un motif de recherche qui
corresponde à toutes les définitions de fonctions dans un fichier de
code C++. Fondamentalement, c'est pas très dur, ce qui m'embête c'est
juste qu'à force d'ajouter des cas particuliers je suis en train de
copier toute la grammaire pour décider de ce qui peut être une
fonction ou pas...
[...]
D'où ma question : est-ce qu'il y a un moyen plus court de faire ça ?
Tu veux faire quoi exactement ?
Matcher n'importe quelle fonction, ou alors une fonction bien
précise ?
Post by Rémi Moyen
J'imagine que dans tous les mappings/syntax highlighting/autres/... de
vim, je ne suis pas le premier à faire du C++ !
Tout à fait!
Post by Rémi Moyen
Accessoirement, est-ce qu'il y a un moyen simple de définir une sorte
de motif personnalisé que je puisse réutiliser ? Par exemple est-ce
que je peux dire que [une courte séquence de caractères de mon choix]
veut dire \<\h\w*\> ? Si j'utilise \1, \2 etc. je ne vais pas matcher
le motif de recherche, mais ce qui a déjà été matché par le n-ième
groupe.
Tu peux les construire en agglomérant des regex stockées dans des
variables.
C'est ce que j'ai fait dans ma lib d'analyse de C++ pour vim:
http://code.google.com/p/lh-vim/source/browse/cpp/trunk/autoload/lh/cpp/AnalysisLib_Function.vim
, fonctions lh#cpp#AnalysisLib_Function#SignatureToSearchRegex() qui
proviennent de mon vieil ftplugin gotoimpl.

ctags est effectivement un meilleur début si tu veux toutes les
fonctions, mais il est assez limité. Si tes signatures sont écrites
sur plusieurs lignes, ctags ne saura pas t'amener à la bonne surcharge
qui t'intéresse du premier coup. Ce qu'il est possible de faire, c'est
de récupérer la signature reconnue par ctags, la balancer à ma
bibliothèque pour la décoder dans un premier temps, pour construire
dans un second temps la regex associée à une fonction donnée.

Mais .... quel est le problème que tu cherches à résoudre exactement ?

NB: il reste des bugs dans cette version de gotoimpl, et la toute
dernière version de lh-cpp n'a pas encore été commitée.

--
Luc Hermitte
http://lh-vim.googlecode.com/
http://hermitte.free.fr/vim/
Rémi Moyen
2009-02-26 09:52:48 UTC
Permalink
Post by Luc Hermitte
Post by Rémi Moyen
Bonjour,
J'utilise Vim et j'essaye de trouver un motif de recherche qui
corresponde à toutes les définitions de fonctions dans un fichier de
code C++. Fondamentalement, c'est pas très dur, ce qui m'embête c'est
juste qu'à force d'ajouter des cas particuliers je suis en train de
copier toute la grammaire pour décider de ce qui peut être une
fonction ou pas...
[...]
D'où ma question : est-ce qu'il y a un moyen plus court de faire ça ?
Tu veux faire quoi exactement ?
Matcher n'importe quelle fonction, ou alors une fonction bien
précise ?
N'importe quelle fonction. L'usage que j'ai actuellement, c'est en
fait dans une commande qui rajoute automatiquement un entête
particulier (une doc !) juste au dessus de la fonction. Basiquement,
je veux remplacer "void f() {" par "/*! comment */ void f() {" (avec
des sauts de ligne bien comme il faut). Et je veux pouvoir le faire en
cours d'édition, pour une fonction donnée, et non pas en traitement
externe d'un fichier "figé", avec un :.s/ par exemple (en particulier,
je ne veux pas que toutes les fonctions de mon fichier soient traités
automatiquement, je veux contrôler pour quelles fonctions je veux
ajouter cet entête).

J'ai d'autres usages en tête, mais ils sont du même genre, cad ajouter/
modifier la définition, suivant une règle prédéfinie, mais appliquée
au cas par cas sur demande et en cours d'édition, pas systématiquement
sur tout un fichier.

En réalité, je n'ai pas vraiment besoin de reconnaitre les définitions
dans l'absolu, puisque je lancerais presque certainement ma commande
avec le curseur déjà positionné sur une définition. Mais j'ai quand
même besoin d'identifier les différents morceaux de la définition
(type de retour, nom de classe si il existe, nom de fonction, etc.),
donc ça revient un peu au même à mon sens. En tout cas, je ne vois pas
comment ça pourrait me simplifier les choses...
Post by Luc Hermitte
Post by Rémi Moyen
Accessoirement, est-ce qu'il y a un moyen simple de définir une sorte
de motif personnalisé que je puisse réutiliser ? Par exemple est-ce
que je peux dire que [une courte séquence de caractères de mon choix]
veut dire \<\h\w*\> ? Si j'utilise \1, \2 etc. je ne vais pas matcher
le motif de recherche, mais ce qui a déjà été matché par le n-ième
groupe.
Tu peux les construire en agglomérant des regex stockées dans des
variables.
C'est ce que j'ai fait dans ma lib d'analyse de C++ pour vim:http://code.google.com/p/lh-vim/source/browse/cpp/trunk/autoload/lh/c...
, fonctions lh#cpp#AnalysisLib_Function#SignatureToSearchRegex() qui
proviennent de mon vieil ftplugin gotoimpl.
Euh... Bon, ta réponse est un peu du chinois pour moi, mais je vais
aller regarder la doc et ton code, ça m'eclaircira sans doute les
idées. Je reviendrais poser des questions quand j'aurais compris :-)
Post by Luc Hermitte
ctags est effectivement un meilleur début si tu veux toutes les
fonctions, mais il est assez limité. Si tes signatures sont écrites
sur plusieurs lignes, ctags ne saura pas t'amener à la bonne surcharge
qui t'intéresse du premier coup. Ce qu'il est possible de faire, c'est
de récupérer la signature reconnue par ctags, la balancer à ma
bibliothèque pour la décoder dans un premier temps, pour construire
dans un second temps la regex associée à une fonction donnée.
Mouais. Je vais regarder ctags, mais je sens que ça ne va pas être
très pratique pour faire ce que je veux...

Merci de ton aide !
--
Rémi Moyen
Luc Hermitte
2009-02-26 10:57:22 UTC
Permalink
Post by Rémi Moyen
Post by Luc Hermitte
Tu veux faire quoi exactement ?
Matcher n'importe quelle fonction, ou alors une fonction bien
précise ?
N'importe quelle fonction.
Alors ctags est ce qu'il se fait de plus simple pour l'instant -- je
surveille des projets comme oink/pork/elsa, mais leur prise en main
n'est
ni triviale ni trivialement portable (je suis sous un Solaris sans
gcc)

Car comment savoir si F(foo, bar); est une déclaration de fonction
ou un appel juste avec des regex ? Entre le retour d'int implicite, et
les
contructeurs, une regex suffit difficilement.
Post by Rémi Moyen
L'usage que j'ai actuellement, c'est en
fait dans une commande qui rajoute automatiquement un entête
particulier (une doc !) juste au dessus de la fonction. Basiquement,
je veux remplacer "void f() {" par "/*! comment */ void f() {" (avec
des sauts de ligne bien comme il faut).
Tu veux doxygener ton code donc. J'ai déjà tout ce qu'il faut dans ma
suite. cf la commande :DOX, qui s'applique sur des signatures de
fonctions.
Post by Rémi Moyen
Et je veux pouvoir le faire en
cours d'édition, pour une fonction donnée, et non pas en traitement
externe d'un fichier "figé", avec un :.s/ par exemple (en particulier,
je ne veux pas que toutes les fonctions de mon fichier soient traités
automatiquement, je veux contrôler pour quelles fonctions je veux
ajouter cet entête).
Dans ma suite, à divers endroits (cf p.ex. UnmatchedFunctions) je
réalise
des recherches de fonctions (déjà "extraites" avec ctags), et les
présente à
l'utilisateur pour qu'il sélectionne celles qui lui font plaisir.
De là, il est "facile" d'appliquer :DOX sur les fonctions qui ont été
retenues.
(en gros, ce n'est pas encore fait, et il n'y a plus qu'à intégrer les
diverses
briques existantes)
Post by Rémi Moyen
J'ai d'autres usages en tête, mais ils sont du même genre, cad ajouter/
modifier la définition, suivant une règle prédéfinie, mais appliquée
au cas par cas sur demande et en cours d'édition, pas systématiquement
sur tout un fichier.
En réalité, je n'ai pas vraiment besoin de reconnaitre les définitions
dans l'absolu, puisque je lancerais presque certainement ma commande
avec le curseur déjà positionné sur une définition. Mais j'ai quand
même besoin d'identifier les différents morceaux de la définition
(type de retour, nom de classe si il existe, nom de fonction, etc.),
donc ça revient un peu au même à mon sens.
Dans ma lib, il y a déjà tout ce qu'il faut. ....#AnalysePrototype
prend un
prototype de fonction, et renvoie un "dictionnaire" qui contient:
- nom
- scope (namespaces::classes::)
- liste de paramètres (avec nom, type, et valeur par défaut pour
chaque param)
- type de retour
- flag si la fonction est const
- autre qualificateur (static/const)
- liste de spécifications d'exception

Et :DOX, de sont côté cherche à déduire si le paramètre est "in", ou
"in,out|out".
Post by Rémi Moyen
En tout cas, je ne vois pas
comment ça pourrait me simplifier les choses...
ctags est juste ce qu'il se fait de plus simple pour lister les
fonctions.
Post by Rémi Moyen
Post by Luc Hermitte
Post by Rémi Moyen
Accessoirement, est-ce qu'il y a un moyen simple de définir une sorte
de motif personnalisé que je puisse réutiliser ? Par exemple est-ce
que je peux dire que [une courte séquence de caractères de mon choix]
veut dire \<\h\w*\> ? Si j'utilise \1, \2 etc. je ne vais pas matcher
le motif de recherche, mais ce qui a déjà été matché par le n-ième
groupe.
Tu peux les construire en agglomérant des regex stockées dans des
variables.
C'est ce que j'ai fait dans ma lib d'analyse de C++ pour vim:http://code.google.com/p/lh-vim/source/browse/cpp/trunk/autoload/lh/c...
, fonctions lh#cpp#AnalysisLib_Function#SignatureToSearchRegex() qui
proviennent de mon vieil ftplugin gotoimpl.
Euh... Bon, ta réponse est un peu du chinois pour moi, mais je vais
aller regarder la doc et ton code, ça m'éclaircira sans doute les
idées. Je reviendrais poser des questions quand j'aurais compris :-)
Si tu te sens de rajouter d'autres fonctionnalités, de béta tester ou
autre, n'hésite pas.
BTW, :Override n'est pas finie (elle n'insère pas encore correctement
les signatures
de redéfinitions), et j'ai pondu (mais non commité) un :Constructor
qui permet de
générer un constructeur d'initialisation à partir des attributs de la
classe courante.
Post by Rémi Moyen
Post by Luc Hermitte
ctags est effectivement un meilleur début si tu veux toutes les
fonctions, mais il est assez limité. Si tes signatures sont écrites
sur plusieurs lignes, ctags ne saura pas t'amener à la bonne surcharge
qui t'intéresse du premier coup. Ce qu'il est possible de faire, c'est
de récupérer la signature reconnue par ctags, la balancer à ma
bibliothèque pour la décoder dans un premier temps, pour construire
dans un second temps la regex associée à une fonction donnée.
Mouais. Je vais regarder ctags, mais je sens que ça ne va pas être
très pratique pour faire ce que je veux...
Disons que vim n'est pas adapté pour faire ce que ctags fait, même
s'il
le fait mal.
Post by Rémi Moyen
Merci de ton aide !
Avec plaisir.

--
Luc Hermitte
http://lh-vim.googlecode.com/
http://hermitte.free.fr/vim/

Loading...