1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2017 EDF R&D
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.
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.
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
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
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
25 from __future__ import absolute_import
26 from __future__ import print_function
28 from builtins import object
31 from Extensions.i18n import tr
32 filePattern="'[^\(\)]([^\(\)]*\([^\(\)]*\))*[^\(\)]*'"
33 filePattern2='"[^\(\)]([^\(\)]*\([^\(\)]*\))*[^\(\)]*"'
35 class Formatage (object):
37 Cette classe contient toutes les méthodes nécessaires au formatage
38 de la chaine de caracteres issue d'un generator en un fichier
39 'lisible' ie avec indentations
41 L'objet attend en parametre du constructeur (argument l_jdc) une representation
42 du jeu de commandes sous la forme d'une liste.
44 Chaque element de la liste est la representation d'une etape.
46 La representation d'une etape est une liste dont le premier element est une chaine de
47 caracteres donnant le debut de la commande ("xxx=lire_maillage(", par exemple).
48 Les elements suivants sont les representations des mots cles simples et facteurs.
49 Elle se termine avec un element de fin : ");"
51 La representation d'un mot cle simple est une chaine de caracteres (info=2, par exemple).
53 La representation d'un mot cle facteur est semblable à celle de l'étape : premier element
54 caracteristique du mot cle facteur suivi d'elements representatifs des mots cles simples.
55 Elle se termine avec un element de fin : ")" ou "),".
57 def __init__(self,l_jdc,code=None,mode=None,sep='=',l_max=72):
58 # l_jdc représente le jeu de commandes brut sous forme de liste
72 comment=re.compile("\n#")
74 for etape in self.l_jdc:
75 self.count = self.count+1
78 # L'etape est sous la forme d'une liste dont le premier element est une chaine
80 self.indent.append(len(etape[0]))
81 self.indent_courant = self.indent[0]
82 self.texte_etape = '\n' + etape[0]
84 self.formateEtape(etape[1:])
86 # L'etape est deja sous forme de chaine de caracteres
88 self.texte_etape = etape
90 m=comment.match(self.texte_etape)
91 # si ce n est pas la premiere ligne
92 if self.jdc_fini != "" :
93 # si il n y avait pas de commentaire avant on met un saut de ligne
94 if commentaireavant == 0 :
95 self.jdc_fini = self.jdc_fini + '\n' + self.texte_etape
97 self.jdc_fini = self.jdc_fini + self.texte_etape
98 # si c est la premiere ligne
100 # on ne met pas de saut de ligne avant la premiere ligne
101 # si c est un commentaire on enleve le saut de ligne precedent
102 if m : self.texte_etape=self.texte_etape[1:]
103 self.jdc_fini = self.texte_etape
113 def formateEtape(self,liste):
115 Enrichissement de la chaine de caracteres representant l'etape (attribut
116 texte_etape de l'objet Formatage).
117 Les elements a ajouter sont dans l'argument liste de la methode.
118 L'objet "liste" à traiter a été produit par le module generator. En particulier
119 les parenthèses et les virgules ont été produites par ce module
121 l_patterns_fin_etape = ( ');' , ');\n' )
122 l_patterns_fin_mcf = ( ')' , '),' )
125 for element in liste :
126 if type(element)==list:
128 # il s'agit d'un mot-clé facteur
129 # on écrit son nom (element[0])
130 longueur = self.longueur(self.texte_etape)
132 increment = len(('\n'+self.indent_courant*' ')*ind + element[0])
137 self.texte_etape = self.texte_etape + (u'\n'+self.indent_courant*' ')*ind + element[0]
138 length = len(self.indent)
139 self.indent.insert(length,self.indent[length-1]+len(element[0]))
140 self.indent_courant = self.indent[length]
142 self.formateEtape(element[1:])
143 #elif type(element) == types.StringType:
144 #elif type(element) == bytes:
145 # PNPNPN -> marre du python 2 et 3
146 # on remplace par else dans if
149 # il s'agit d'un mot-clé simple ou de ')' ou ');' ou '),' ou ');\n'
151 if element in l_patterns_fin_mcf :
152 self.traiteMcfact(s_mcfact=element,ind=ind)
153 elif element in l_patterns_fin_etape :
154 self.traiteEtape(s_etape=element,ind=ind)
156 self.traiteMcsimp(s_mcsimp=element,ind=ind)
160 def traiteEtape(self,s_etape,ind) :
162 Traite une partie du jdc formaté : s_etape, une chaîne de caractères
164 L'attribut self.texte_etape est modifié (complété) par le traitement
165 L'attribut self.indent est modifié par le traitement
166 L'attribut self.indent_courant est modifié par le traitement
168 length = len(self.indent)
170 last = self.indent[length-1]
171 self.indent.remove(last)
172 self.indent_courant=self.indent[length-2]
174 self.indent_courant=self.indent[0]
175 self.texte_etape = self.texte_etape + s_etape.strip()
177 def traiteMcfact(self,s_mcfact,ind) :
179 Traite une partie du jdc formaté : s_mcfact, une chaîne de caractères
180 contenant un mot-clef facteur.
181 L'attribut self.texte_etape est modifié (complété) par le traitement
182 L'attribut self.indent est modifié par le traitement
183 L'attribut self.indent_courant est modifié par le traitement
185 self.texte_etape = self.texte_etape + s_mcfact.strip()
186 length = len(self.indent)
188 last = self.indent[length-1]
189 self.indent.remove(last)
190 self.indent_courant=self.indent[length-2]
192 self.indent_courant=self.indent[0]
196 def traiteMcsimp(self,s_mcsimp,ind) :
198 Traite une partie du jdc formaté : s_mcsimp, une chaîne de caractères
199 contenant un mot-clef simple.
200 L'attribut self.texte_etape est modifié (complété) par le traitement
203 # Ajout PN pour defi_fonction
204 if self.texte_etape.find("DEFI_FONCTION") > 1 :
206 if s_mcsimp.find("\n") > 1:
207 txt=""; bool = 0; numident=1
208 for l in s_mcsimp.splitlines() :
211 numident=s_mcsimp.find("=")+2
214 txt=txt+('\n'+self.indent_courant*' '+numident*' ')*ind+l
218 longueur = self.longueur(self.texte_etape)
219 increment = len((u'\n'+self.indent_courant*' ')*ind + s_mcsimp.strip())
220 if (bool_fonction == 1 ) :
221 self.texte_etape = self.texte_etape+'\n'+self.indent_courant*' ' +s_mcsimp
222 elif ( ((1-ind)*longueur+increment) <= self.l_max ) :
223 self.texte_etape = self.texte_etape + ('\n'+self.indent_courant*' ')*ind +s_mcsimp.strip()
226 #nom,valeur = string.split(s_mcsimp,self.sep,1)
227 nom,valeur = str.split(s_mcsimp,self.sep,1)
228 chaine = self.creerChaine(nom,valeur,'\n'+self.indent_courant*' ',ind)
229 #self.jdc_fini = self.jdc_fini + ('\n'+self.indent_courant*' ')*ind + s_mcsimp.strip()
230 self.texte_etape = self.texte_etape + chaine
234 def longueur(self,texte):
236 texte est une string qui peut contenir des retours chariots
237 Cette méthode retourne la longueur de la dernière ligne de texte
239 #liste = texte.split('\n')
240 #return len(liste[-1])
241 if texte [-1] == '\n' : return 0
242 return len(texte[texte.rfind('\n'):-1])
245 def creerChaine(self,nom,valeur,increment,ind):
247 La methode creerChaine reconstitue un objet Eficas à partir de
252 if len(increment + nom + self.sep) <= self.l_max:
253 texte = increment*ind
254 label = nom + self.sep
256 longueur = len(increment + label)
258 if ('(' not in valeur) or (valeur[0:3]=='"""') :
259 # il s'agit d'une vraie chaîne de caractères
261 texte = (self.l_max-2-val)*' '+valeur
263 elif re.match(filePattern,valeur) or re.match(filePattern2,valeur):
265 texte = (self.l_max-2-val)*' '+valeur
268 # il s'agit d'une liste de tuple
269 # c est trop complique on ne splitte pas
270 if valeur[0:2]=='((' or valeur[0:2]=='[(':
273 # il s'agit d'une liste
274 liste = valeur.split(',')
278 if len(ajout) == 0 : continue
279 longueur = self.longueur(texte = (texte + label)) + len(ajout +',') + (1-i)*len(increment)
280 if longueur <= self.l_max:
282 texte = texte + ajout +','
284 texte = texte + ajout
288 texte = texte + increment + (len(label)+2)*' ' + ajout + ','
290 texte = texte + increment + (len(label)+2)*' ' + ajout
296 # On a une ( mais pas de , . On passe la chaine sans modification
298 texte = (self.l_max-2-val)*' '+valeur
303 class FormatageLigne(Formatage) :
304 def __init__(self,l_jdc,code=None,mode=None,sep='=',l_max="**"):
305 Formatage.__init__(self,l_jdc,code=None,mode=None,sep='=',l_max="**")
307 def formateJdc(self):
308 texte1=Formatage.formateJdc(self)
310 lignes=texte1.split("\n")
312 pattern_debut_blanc = re.compile(r"^ \s*.*")
313 pattern_commentaire = re.compile(r"^\s*#.*")
314 pattern_vide=re.compile(r"\s*^$")
316 if pattern_commentaire.match(l) or pattern_vide.match(l):
319 if not pattern_debut_blanc.match(l) : texte=l
320 else : texte+=re.sub(r'^ \s*',' ',l)