Salome HOME
premiere version
[tools/eficas.git] / generator / Formatage.py
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2013   EDF R&D
3 #
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License.
8 #
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 # Lesser General Public License for more details.
13 #
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 #
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #
20 """
21     Ce module contient la classe Formatage qui permet le formatage d'une 
22     liste de chaines de caractères dans une syntaxe représentative d'un
23     jeu de commandes en un texte présentable
24 """
25 import types,string,re
26 from Extensions.i18n import tr
27
28 class Formatage :
29   """ 
30      Cette classe contient toutes les méthodes nécessaires au formatage
31      de la chaine de caracteres issue d'un generator en un fichier
32      'lisible' ie avec indentations
33
34      L'objet attend en parametre du constructeur (argument l_jdc) une representation
35      du jeu de commandes sous la forme d'une liste.
36
37      Chaque element de la liste est la representation d'une etape.
38
39      La representation d'une etape est une liste dont le premier element est une chaine de
40      caracteres donnant le debut de la commande ("xxx=lire_maillage(", par exemple).
41      Les elements suivants sont les representations des mots cles simples et facteurs.
42      Elle se termine avec un element de fin : ");"
43
44      La representation d'un mot cle simple est une chaine de caracteres (info=2, par exemple).
45
46      La representation d'un mot cle facteur est semblable à celle de l'étape : premier element
47      caracteristique du mot cle facteur suivi d'elements representatifs des mots cles simples.
48      Elle se termine avec un element de fin : ")" ou "),".
49   """
50   def __init__(self,l_jdc,code=None,mode=None,sep='=',l_max=72):
51     # l_jdc représente le jeu de commandes brut sous forme de liste
52     self.l_jdc = l_jdc
53     self.jdc_fini =''
54     self.count = 0
55     self.sep=sep
56     self.l_max=l_max
57     if mode == '.py':
58        self.sep = '='
59        self.l_max = 132 
60     elif code == 'ASTER':
61        self.sep = ':'
62        self.l_max = 72
63
64   def formate_jdc(self):
65     comment=re.compile("\n#")
66     commentaireavant=0
67     for etape in self.l_jdc:
68       self.count = self.count+1
69       self.texte_etape = ''
70       if type(etape)==types.ListType:
71         # L'etape est sous la forme d'une liste dont le premier element est une chaine
72         self.indent=[]
73         self.indent.append(len(etape[0]))
74         self.indent_courant = self.indent[0]
75         self.texte_etape = '\n' + etape[0]
76         if len(etape)>1 :
77           self.formate_etape(etape[1:])
78       else :
79         # L'etape est deja sous forme de chaine de caracteres
80         self.indent=[]
81         self.texte_etape = etape
82
83       m=comment.match(self.texte_etape)
84       # si ce n est pas la premiere ligne
85       if self.jdc_fini != ""  : 
86         # si il n y avait pas de commentaire avant on met un saut de ligne
87         if commentaireavant == 0 :
88            self.jdc_fini = self.jdc_fini + '\n' + self.texte_etape
89         else :
90            self.jdc_fini = self.jdc_fini + self.texte_etape
91       # si c est la premiere ligne
92       else :
93         # on ne met pas de saut de ligne avant la premiere ligne 
94         # si c est un commentaire on enleve le saut de ligne precedent
95         if m : self.texte_etape=self.texte_etape[1:]
96         self.jdc_fini = self.texte_etape
97       if m : 
98         commentaireavant=1 
99       else :
100         commentaireavant=0 
101
102     return self.jdc_fini
103   
104   
105
106   def formate_etape(self,liste):
107     """
108         Enrichissement de la chaine de caracteres representant l'etape (attribut
109         texte_etape de l'objet Formatage).
110         Les elements a ajouter sont dans l'argument liste de la methode.
111         L'objet "liste" à traiter a été produit par le module generator. En particulier
112         les parenthèses et les virgules ont été produites par ce module
113     """
114     l_patterns_fin_etape = ( ');' , ');\n' )
115     l_patterns_fin_mcf   = ( ')'  , '),'   )
116
117     ind = 0
118     for element in liste :
119       if type(element) == types.ListType:
120
121         # il s'agit d'un mot-clé facteur
122         # on écrit son nom (element[0])
123         longueur = self.longueur(self.texte_etape)
124         try:
125           increment = len(('\n'+self.indent_courant*' ')*ind + element[0])
126         except:
127           print tr('ERREUR')
128           print liste
129           print element
130         self.texte_etape = self.texte_etape + (u'\n'+self.indent_courant*' ')*ind + element[0]
131         length = len(self.indent)
132         self.indent.insert(length,self.indent[length-1]+len(element[0]))
133         self.indent_courant = self.indent[length]
134         # on écrit ses fils
135         self.formate_etape(element[1:])
136       elif type(element) == types.StringType:
137
138         # il s'agit d'un mot-clé simple ou de ')' ou ');' ou '),' ou ');\n'
139
140         if element in l_patterns_fin_mcf :
141               self.traite_mcfact(s_mcfact=element,ind=ind)
142         elif element in l_patterns_fin_etape :
143               self.traite_etape(s_etape=element,ind=ind)
144         else :
145               self.traite_mcsimp(s_mcsimp=element,ind=ind)
146
147       ind = 1
148
149   def traite_etape(self,s_etape,ind) :
150       """
151           Traite une partie du jdc formaté : s_etape, une chaîne de caractères
152           contenant une étape
153           L'attribut self.texte_etape est modifié (complété) par le traitement
154           L'attribut self.indent est modifié par le traitement
155           L'attribut self.indent_courant est modifié par le traitement
156       """
157       length = len(self.indent)
158       if length > 1:
159           last = self.indent[length-1]
160           self.indent.remove(last)
161           self.indent_courant=self.indent[length-2]
162       else :
163           self.indent_courant=self.indent[0]
164       self.texte_etape = self.texte_etape + string.strip(s_etape)
165
166   def traite_mcfact(self,s_mcfact,ind) :
167       """
168           Traite une partie du jdc formaté : s_mcfact, une chaîne de caractères
169           contenant un mot-clef facteur.
170           L'attribut self.texte_etape est modifié (complété) par le traitement
171           L'attribut self.indent est modifié par le traitement
172           L'attribut self.indent_courant est modifié par le traitement
173       """
174       self.texte_etape = self.texte_etape + string.strip(s_mcfact)
175       length = len(self.indent)
176       if length > 1:
177            last = self.indent[length-1]
178            self.indent.remove(last)
179            self.indent_courant=self.indent[length-2]
180       else :
181            self.indent_courant=self.indent[0]
182       return
183
184
185   def traite_mcsimp(self,s_mcsimp,ind) :
186       """
187           Traite une partie du jdc formaté : s_mcsimp, une chaîne de caractères
188           contenant un mot-clef simple.
189           L'attribut self.texte_etape est modifié (complété) par le traitement
190       """
191       #
192       # Ajout PN pour defi_fonction
193       if self.texte_etape.find("DEFI_FONCTION") > 1 :
194           bool_fonction=1
195           if s_mcsimp.find("\n")  > 1:
196               txt=""; bool = 0; numident=1
197               for l in s_mcsimp.splitlines() :
198                  if bool == 0 :
199                     bool = 1
200                     numident=s_mcsimp.find("=")+2
201                     txt=l
202                  else :
203                     txt=txt+('\n'+self.indent_courant*' '+numident*' ')*ind+l
204               s_mcsimp = txt
205       else : 
206           bool_fonction=0
207       longueur = self.longueur(self.texte_etape)
208       increment = len((u'\n'+self.indent_courant*' ')*ind + string.strip(s_mcsimp))
209       if (bool_fonction == 1 ) :
210           self.texte_etape = self.texte_etape+'\n'+self.indent_courant*' ' +s_mcsimp
211       elif ( ((1-ind)*longueur+increment) <= self.l_max ) :
212           self.texte_etape = self.texte_etape + ('\n'+self.indent_courant*' ')*ind + string.strip(s_mcsimp)
213       else :
214           # il faut couper ...
215           nom,valeur = string.split(s_mcsimp,self.sep,1)
216           chaine = self.creer_chaine(nom,valeur,'\n'+self.indent_courant*' ',ind)
217           #self.jdc_fini = self.jdc_fini + ('\n'+self.indent_courant*' ')*ind + string.strip(s_mcsimp)
218           self.texte_etape = self.texte_etape + chaine
219       return
220
221
222   def longueur(self,texte):
223     """ 
224        texte est une string qui peut contenir des retours chariots
225        Cette méthode retourne la longueur de la dernière ligne de texte 
226     """
227     liste = string.split(texte,'\n')
228     return len(liste[-1])
229
230   def creer_chaine(self,nom,valeur,increment,ind):
231     """
232         La methode creer_chaine reconstitue un objet Eficas à partir de
233              - son nom,
234              - sa valeur.
235     """
236     s=''
237     if len(increment + nom + self.sep) <= self.l_max:
238       texte = increment*ind
239       label = nom + self.sep
240       s=texte + label
241       longueur = len(increment + label)
242
243       if ('(' not in valeur) or (valeur[0:3]=='"""'):
244         # il s'agit d'une vraie chaîne de caractères
245         val = len(valeur)
246         texte = (self.l_max-2-val)*' '+valeur
247         s=s+'\n'+texte
248
249       elif ',' in valeur:
250         # il s'agit d'une liste de tuple
251         # c est trop complique on ne splitte pas
252         if valeur[0:2]=='((' or valeur[0:2]=='[(':
253            s=s+valeur
254            return s
255         # il s'agit d'une liste
256         liste = string.split(valeur,',')
257         i=0
258         for arg in liste :
259           ajout = string.strip(arg)
260           if len(ajout) == 0 : continue
261           longueur = self.longueur(texte = (texte + label)) + len(ajout +',') + (1-i)*len(increment)
262           if longueur  <= self.l_max:
263               if ajout[-1] != ')':
264                 texte = texte + ajout +','
265               else :
266                 texte = texte + ajout
267           else :
268             i=1
269             if ajout[-1] != ')':
270               texte = texte  + increment + (len(label)+2)*' ' + ajout  + ','
271             else :
272               texte = texte  + increment + (len(label)+2)*' ' + ajout
273
274         s=s+texte
275         s =  s + ','
276
277       else :
278         # On a une ( mais pas de , . On passe la chaine sans modification
279         val = len(valeur)
280         texte = (self.l_max-2-val)*' '+valeur
281         s=s+'\n'+texte
282
283     return s