Grammalecte  Hex Artifact Content

Artifact 2561b9d2fe335ebf044372fce3e077b694af398f84cb37f2045ac4fea4a26986:


0000: 23 21 2f 75 73 72 2f 62 69 6e 2f 65 6e 76 20 70  #!/usr/bin/env p
0010: 79 74 68 6f 6e 33 0a 23 20 63 6f 64 69 6e 67 3a  ython3.# coding:
0020: 20 55 54 46 2d 38 0a 0a 22 22 22 0a 47 72 61 6d   UTF-8..""".Gram
0030: 6d 61 6c 65 63 74 65 20 62 75 69 6c 64 65 72 0a  malecte builder.
0040: 22 22 22 0a 0a 69 6d 70 6f 72 74 20 73 79 73 0a  """..import sys.
0050: 69 6d 70 6f 72 74 20 6f 73 0a 69 6d 70 6f 72 74  import os.import
0060: 20 72 65 0a 69 6d 70 6f 72 74 20 7a 69 70 66 69   re.import zipfi
0070: 6c 65 0a 69 6d 70 6f 72 74 20 74 72 61 63 65 62  le.import traceb
0080: 61 63 6b 0a 69 6d 70 6f 72 74 20 63 6f 6e 66 69  ack.import confi
0090: 67 70 61 72 73 65 72 0a 69 6d 70 6f 72 74 20 64  gparser.import d
00a0: 61 74 65 74 69 6d 65 0a 69 6d 70 6f 72 74 20 61  atetime.import a
00b0: 72 67 70 61 72 73 65 0a 69 6d 70 6f 72 74 20 69  rgparse.import i
00c0: 6d 70 6f 72 74 6c 69 62 0a 69 6d 70 6f 72 74 20  mportlib.import 
00d0: 75 6e 69 74 74 65 73 74 0a 69 6d 70 6f 72 74 20  unittest.import 
00e0: 6a 73 6f 6e 0a 69 6d 70 6f 72 74 20 70 6c 61 74  json.import plat
00f0: 66 6f 72 6d 0a 0a 66 72 6f 6d 20 64 69 73 74 75  form..from distu
0100: 74 69 6c 73 20 69 6d 70 6f 72 74 20 64 69 72 5f  tils import dir_
0110: 75 74 69 6c 2c 20 66 69 6c 65 5f 75 74 69 6c 0a  util, file_util.
0120: 0a 23 69 6d 70 6f 72 74 20 64 69 61 6c 6f 67 5f  .#import dialog_
0130: 62 75 6e 64 6c 65 64 0a 69 6d 70 6f 72 74 20 63  bundled.import c
0140: 6f 6d 70 69 6c 65 5f 72 75 6c 65 73 0a 69 6d 70  ompile_rules.imp
0150: 6f 72 74 20 68 65 6c 70 65 72 73 0a 69 6d 70 6f  ort helpers.impo
0160: 72 74 20 6c 65 78 5f 62 75 69 6c 64 0a 0a 0a 73  rt lex_build...s
0170: 57 61 72 6e 69 6e 67 4d 65 73 73 61 67 65 20 3d  WarningMessage =
0180: 20 22 54 68 65 20 63 6f 6e 74 65 6e 74 20 6f 66   "The content of
0190: 20 74 68 69 73 20 66 6f 6c 64 65 72 20 69 73 20   this folder is 
01a0: 67 65 6e 65 72 61 74 65 64 20 62 79 20 63 6f 64  generated by cod
01b0: 65 20 61 6e 64 20 72 65 70 6c 61 63 65 64 20 61  e and replaced a
01c0: 74 20 65 61 63 68 20 62 75 69 6c 64 2e 5c 6e 22  t each build.\n"
01d0: 0a 0a 0a 64 65 66 20 67 65 74 43 6f 6e 66 69 67  ...def getConfig
01e0: 20 28 73 4c 61 6e 67 29 3a 0a 20 20 20 20 22 6c   (sLang):.    "l
01f0: 6f 61 64 20 63 6f 6e 66 69 67 2e 69 6e 69 20 69  oad config.ini i
0200: 6e 20 3c 73 4c 61 6e 67 3e 20 61 74 20 67 63 5f  n <sLang> at gc_
0210: 6c 61 6e 67 2f 3c 73 4c 61 6e 67 3e 2c 20 72 65  lang/<sLang>, re
0220: 74 75 72 6e 73 20 78 43 6f 6e 66 69 67 50 61 72  turns xConfigPar
0230: 73 65 72 20 6f 62 6a 65 63 74 22 0a 20 20 20 20  ser object".    
0240: 78 43 6f 6e 66 69 67 20 3d 20 63 6f 6e 66 69 67  xConfig = config
0250: 70 61 72 73 65 72 2e 43 6f 6e 66 69 67 50 61 72  parser.ConfigPar
0260: 73 65 72 28 29 0a 20 20 20 20 78 43 6f 6e 66 69  ser().    xConfi
0270: 67 2e 6f 70 74 69 6f 6e 78 66 6f 72 6d 20 3d 20  g.optionxform = 
0280: 73 74 72 0a 20 20 20 20 74 72 79 3a 0a 20 20 20  str.    try:.   
0290: 20 20 20 20 20 78 43 6f 6e 66 69 67 2e 72 65 61       xConfig.rea
02a0: 64 5f 66 69 6c 65 28 6f 70 65 6e 28 66 22 67 63  d_file(open(f"gc
02b0: 5f 6c 61 6e 67 2f 7b 73 4c 61 6e 67 7d 2f 63 6f  _lang/{sLang}/co
02c0: 6e 66 69 67 2e 69 6e 69 22 2c 20 22 72 22 2c 20  nfig.ini", "r", 
02d0: 65 6e 63 6f 64 69 6e 67 3d 22 75 74 66 2d 38 22  encoding="utf-8"
02e0: 29 29 0a 20 20 20 20 65 78 63 65 70 74 20 46 69  )).    except Fi
02f0: 6c 65 4e 6f 74 46 6f 75 6e 64 45 72 72 6f 72 3a  leNotFoundError:
0300: 0a 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 66  .        print(f
0310: 22 23 20 45 72 72 6f 72 2e 20 43 61 6e e2 80 99  "# Error. Can...
0320: 74 20 72 65 61 64 20 63 6f 6e 66 69 67 20 66 69  t read config fi
0330: 6c 65 20 3c 7b 73 4c 61 6e 67 7d 3e 22 29 0a 20  le <{sLang}>"). 
0340: 20 20 20 20 20 20 20 65 78 69 74 28 29 0a 20 20         exit().  
0350: 20 20 72 65 74 75 72 6e 20 78 43 6f 6e 66 69 67    return xConfig
0360: 0a 0a 0a 64 65 66 20 63 72 65 61 74 65 4f 70 74  ...def createOpt
0370: 69 6f 6e 73 4c 61 62 65 6c 50 72 6f 70 65 72 74  ionsLabelPropert
0380: 69 65 73 20 28 64 4f 70 74 4c 62 6c 29 3a 0a 20  ies (dOptLbl):. 
0390: 20 20 20 22 63 72 65 61 74 65 20 63 6f 6e 74 65     "create conte
03a0: 6e 74 20 66 6f 72 20 2e 70 72 6f 70 65 72 74 69  nt for .properti
03b0: 65 73 20 66 69 6c 65 73 20 28 4c 69 62 72 65 4f  es files (LibreO
03c0: 66 66 69 63 65 29 22 0a 20 20 20 20 73 43 6f 6e  ffice)".    sCon
03d0: 74 65 6e 74 20 3d 20 22 22 0a 20 20 20 20 66 6f  tent = "".    fo
03e0: 72 20 73 4f 70 74 2c 20 74 4c 61 62 65 6c 20 69  r sOpt, tLabel i
03f0: 6e 20 64 4f 70 74 4c 62 6c 2e 69 74 65 6d 73 28  n dOptLbl.items(
0400: 29 3a 0a 20 20 20 20 20 20 20 20 73 43 6f 6e 74  ):.        sCont
0410: 65 6e 74 20 2b 3d 20 66 22 7b 73 4f 70 74 7d 3d  ent += f"{sOpt}=
0420: 7b 74 4c 61 62 65 6c 5b 30 5d 7d 5c 6e 22 0a 20  {tLabel[0]}\n". 
0430: 20 20 20 20 20 20 20 69 66 20 74 4c 61 62 65 6c         if tLabel
0440: 5b 31 5d 3a 0a 20 20 20 20 20 20 20 20 20 20 20  [1]:.           
0450: 20 73 43 6f 6e 74 65 6e 74 20 2b 3d 20 66 22 68   sContent += f"h
0460: 6c 70 5f 7b 73 4f 70 74 7d 3d 7b 74 4c 61 62 65  lp_{sOpt}={tLabe
0470: 6c 5b 31 5d 7d 5c 6e 22 0a 20 20 20 20 72 65 74  l[1]}\n".    ret
0480: 75 72 6e 20 73 43 6f 6e 74 65 6e 74 0a 0a 0a 64  urn sContent...d
0490: 65 66 20 63 72 65 61 74 65 44 69 61 6c 6f 67 4f  ef createDialogO
04a0: 70 74 69 6f 6e 73 58 44 4c 20 28 64 56 61 72 73  ptionsXDL (dVars
04b0: 29 3a 0a 20 20 20 20 22 63 72 65 61 74 65 20 62  ):.    "create b
04c0: 75 6e 64 6c 65 64 20 64 69 61 6c 6f 67 20 6f 70  undled dialog op
04d0: 74 69 6f 6e 73 20 66 69 6c 65 20 2e 78 64 6c 20  tions file .xdl 
04e0: 28 4c 69 62 72 65 4f 66 66 69 63 65 29 22 0a 20  (LibreOffice)". 
04f0: 20 20 20 69 54 61 62 20 3d 20 31 0a 20 20 20 20     iTab = 1.    
0500: 6e 50 6f 73 59 20 3d 20 35 0a 20 20 20 20 6e 57  nPosY = 5.    nW
0510: 69 64 74 68 20 3d 20 32 34 30 0a 20 20 20 20 73  idth = 240.    s
0520: 43 6f 6e 74 65 6e 74 20 3d 20 22 22 0a 20 20 20  Content = "".   
0530: 20 64 4f 70 74 20 3d 20 64 56 61 72 73 5b 22 64   dOpt = dVars["d
0540: 4f 70 74 57 72 69 74 65 72 22 5d 0a 20 20 20 20  OptWriter"].    
0550: 64 4f 70 74 4c 61 62 65 6c 20 3d 20 64 56 61 72  dOptLabel = dVar
0560: 73 5b 22 64 4f 70 74 4c 61 62 65 6c 22 5d 5b 64  s["dOptLabel"][d
0570: 56 61 72 73 5b 22 6c 61 6e 67 22 5d 5d 0a 20 20  Vars["lang"]].  
0580: 20 20 66 6f 72 20 73 47 72 6f 75 70 2c 20 6c 47    for sGroup, lG
0590: 72 6f 75 70 4f 70 74 69 6f 6e 73 20 69 6e 20 64  roupOptions in d
05a0: 56 61 72 73 5b 22 6c 53 74 72 75 63 74 4f 70 74  Vars["lStructOpt
05b0: 22 5d 3a 0a 20 20 20 20 20 20 20 20 73 43 6f 6e  "]:.        sCon
05c0: 74 65 6e 74 20 2b 3d 20 66 27 3c 64 6c 67 3a 66  tent += f'<dlg:f
05d0: 69 78 65 64 6c 69 6e 65 20 64 6c 67 3a 69 64 3d  ixedline dlg:id=
05e0: 22 7b 73 47 72 6f 75 70 7d 22 20 64 6c 67 3a 74  "{sGroup}" dlg:t
05f0: 61 62 2d 69 6e 64 65 78 3d 22 7b 69 54 61 62 7d  ab-index="{iTab}
0600: 22 20 64 6c 67 3a 74 6f 70 3d 22 7b 6e 50 6f 73  " dlg:top="{nPos
0610: 59 7d 22 20 64 6c 67 3a 6c 65 66 74 3d 22 35 22  Y}" dlg:left="5"
0620: 20 64 6c 67 3a 77 69 64 74 68 3d 22 7b 6e 57 69   dlg:width="{nWi
0630: 64 74 68 7d 22 20 64 6c 67 3a 68 65 69 67 68 74  dth}" dlg:height
0640: 3d 22 31 30 22 20 64 6c 67 3a 76 61 6c 75 65 3d  ="10" dlg:value=
0650: 22 26 61 6d 70 3b 7b 73 47 72 6f 75 70 7d 22 20  "&amp;{sGroup}" 
0660: 2f 3e 5c 6e 27 0a 20 20 20 20 20 20 20 20 69 54  />\n'.        iT
0670: 61 62 20 2b 3d 20 31 0a 20 20 20 20 20 20 20 20  ab += 1.        
0680: 66 6f 72 20 6c 4c 69 6e 65 4f 70 74 69 6f 6e 73  for lLineOptions
0690: 20 69 6e 20 6c 47 72 6f 75 70 4f 70 74 69 6f 6e   in lGroupOption
06a0: 73 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 6e  s:.            n
06b0: 45 6c 65 6d 57 69 64 74 68 20 3d 20 6e 57 69 64  ElemWidth = nWid
06c0: 74 68 20 2f 2f 20 6c 65 6e 28 6c 4c 69 6e 65 4f  th // len(lLineO
06d0: 70 74 69 6f 6e 73 29 0a 20 20 20 20 20 20 20 20  ptions).        
06e0: 20 20 20 20 6e 50 6f 73 59 20 2b 3d 20 31 30 0a      nPosY += 10.
06f0: 20 20 20 20 20 20 20 20 20 20 20 20 6e 50 6f 73              nPos
0700: 58 20 3d 20 31 30 0a 20 20 20 20 20 20 20 20 20  X = 10.         
0710: 20 20 20 66 6f 72 20 73 4f 70 74 20 69 6e 20 6c     for sOpt in l
0720: 4c 69 6e 65 4f 70 74 69 6f 6e 73 3a 0a 20 20 20  LineOptions:.   
0730: 20 20 20 20 20 20 20 20 20 20 20 20 20 73 48 65               sHe
0740: 6c 70 20 3d 20 66 27 64 6c 67 3a 68 65 6c 70 2d  lp = f'dlg:help-
0750: 74 65 78 74 3d 22 26 61 6d 70 3b 68 6c 70 5f 7b  text="&amp;hlp_{
0760: 73 4f 70 74 7d 22 27 20 20 69 66 20 64 4f 70 74  sOpt}"'  if dOpt
0770: 4c 61 62 65 6c 5b 73 4f 70 74 5d 5b 31 5d 20 20  Label[sOpt][1]  
0780: 65 6c 73 65 20 22 22 0a 20 20 20 20 20 20 20 20  else "".        
0790: 20 20 20 20 20 20 20 20 73 43 68 65 63 6b 65 64          sChecked
07a0: 20 3d 20 22 74 72 75 65 22 20 69 66 20 64 4f 70   = "true" if dOp
07b0: 74 5b 73 4f 70 74 5d 20 65 6c 73 65 20 22 66 61  t[sOpt] else "fa
07c0: 6c 73 65 22 0a 20 20 20 20 20 20 20 20 20 20 20  lse".           
07d0: 20 20 20 20 20 73 43 6f 6e 74 65 6e 74 20 2b 3d       sContent +=
07e0: 20 66 27 3c 64 6c 67 3a 63 68 65 63 6b 62 6f 78   f'<dlg:checkbox
07f0: 20 64 6c 67 3a 69 64 3d 22 7b 73 4f 70 74 7d 22   dlg:id="{sOpt}"
0800: 20 64 6c 67 3a 74 61 62 2d 69 6e 64 65 78 3d 22   dlg:tab-index="
0810: 7b 69 54 61 62 7d 22 20 64 6c 67 3a 74 6f 70 3d  {iTab}" dlg:top=
0820: 22 7b 6e 50 6f 73 59 7d 22 20 64 6c 67 3a 6c 65  "{nPosY}" dlg:le
0830: 66 74 3d 22 7b 6e 50 6f 73 58 7d 22 20 64 6c 67  ft="{nPosX}" dlg
0840: 3a 77 69 64 74 68 3d 22 7b 6e 45 6c 65 6d 57 69  :width="{nElemWi
0850: 64 74 68 7d 22 20 64 6c 67 3a 68 65 69 67 68 74  dth}" dlg:height
0860: 3d 22 31 30 22 20 64 6c 67 3a 76 61 6c 75 65 3d  ="10" dlg:value=
0870: 22 26 61 6d 70 3b 7b 73 4f 70 74 7d 22 20 64 6c  "&amp;{sOpt}" dl
0880: 67 3a 63 68 65 63 6b 65 64 3d 22 7b 73 43 68 65  g:checked="{sChe
0890: 63 6b 65 64 7d 22 20 7b 73 48 65 6c 70 7d 20 2f  cked}" {sHelp} /
08a0: 3e 5c 6e 27 0a 20 20 20 20 20 20 20 20 20 20 20  >\n'.           
08b0: 20 20 20 20 20 69 54 61 62 20 2b 3d 20 31 0a 20       iTab += 1. 
08c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6e                 n
08d0: 50 6f 73 58 20 2b 3d 20 6e 45 6c 65 6d 57 69 64  PosX += nElemWid
08e0: 74 68 0a 20 20 20 20 20 20 20 20 6e 50 6f 73 59  th.        nPosY
08f0: 20 2b 3d 20 31 30 0a 20 20 20 20 72 65 74 75 72   += 10.    retur
0900: 6e 20 73 43 6f 6e 74 65 6e 74 0a 0a 0a 64 65 66  n sContent...def
0910: 20 63 72 65 61 74 65 4f 58 54 20 28 73 70 4c 61   createOXT (spLa
0920: 6e 67 2c 20 64 56 61 72 73 2c 20 64 4f 78 74 2c  ng, dVars, dOxt,
0930: 20 73 70 4c 61 6e 67 50 61 63 6b 2c 20 62 49 6e   spLangPack, bIn
0940: 73 74 61 6c 6c 29 3a 0a 20 20 20 20 22 63 72 65  stall):.    "cre
0950: 61 74 65 20 65 78 74 65 6e 73 69 6f 6e 20 66 6f  ate extension fo
0960: 72 20 57 72 69 74 65 72 22 0a 20 20 20 20 70 72  r Writer".    pr
0970: 69 6e 74 28 22 42 75 69 6c 64 69 6e 67 20 65 78  int("Building ex
0980: 74 65 6e 73 69 6f 6e 20 66 6f 72 20 57 72 69 74  tension for Writ
0990: 65 72 22 29 0a 20 20 20 20 73 70 66 5a 69 70 20  er").    spfZip 
09a0: 3d 20 66 22 5f 62 75 69 6c 64 2f 7b 64 56 61 72  = f"_build/{dVar
09b0: 73 5b 27 6e 61 6d 65 27 5d 7d 2d 7b 64 56 61 72  s['name']}-{dVar
09c0: 73 5b 27 6c 61 6e 67 27 5d 7d 2d 76 7b 64 56 61  s['lang']}-v{dVa
09d0: 72 73 5b 27 76 65 72 73 69 6f 6e 27 5d 7d 2e 6f  rs['version']}.o
09e0: 78 74 22 0a 20 20 20 20 68 5a 69 70 20 3d 20 7a  xt".    hZip = z
09f0: 69 70 66 69 6c 65 2e 5a 69 70 46 69 6c 65 28 73  ipfile.ZipFile(s
0a00: 70 66 5a 69 70 2c 20 6d 6f 64 65 3d 27 77 27 2c  pfZip, mode='w',
0a10: 20 63 6f 6d 70 72 65 73 73 69 6f 6e 3d 7a 69 70   compression=zip
0a20: 66 69 6c 65 2e 5a 49 50 5f 44 45 46 4c 41 54 45  file.ZIP_DEFLATE
0a30: 44 29 0a 0a 20 20 20 20 23 20 50 61 63 6b 61 67  D)..    # Packag
0a40: 65 20 61 6e 64 20 70 61 72 73 65 72 0a 20 20 20  e and parser.   
0a50: 20 63 6f 70 79 47 72 61 6d 6d 61 6c 65 63 74 65   copyGrammalecte
0a60: 50 79 50 61 63 6b 61 67 65 49 6e 5a 69 70 46 69  PyPackageInZipFi
0a70: 6c 65 28 68 5a 69 70 2c 20 73 70 4c 61 6e 67 50  le(hZip, spLangP
0a80: 61 63 6b 2c 20 22 70 79 74 68 6f 6e 70 61 74 68  ack, "pythonpath
0a90: 2f 22 29 0a 20 20 20 20 68 5a 69 70 2e 77 72 69  /").    hZip.wri
0aa0: 74 65 28 22 67 72 61 6d 6d 61 6c 65 63 74 65 2d  te("grammalecte-
0ab0: 63 6c 69 2e 70 79 22 2c 20 22 70 79 74 68 6f 6e  cli.py", "python
0ac0: 70 61 74 68 2f 67 72 61 6d 6d 61 6c 65 63 74 65  path/grammalecte
0ad0: 2d 63 6c 69 2e 70 79 22 29 0a 0a 20 20 20 20 23  -cli.py")..    #
0ae0: 20 45 78 74 65 6e 73 69 6f 6e 20 66 69 6c 65 73   Extension files
0af0: 0a 20 20 20 20 68 5a 69 70 2e 77 72 69 74 65 73  .    hZip.writes
0b00: 74 72 28 22 4d 45 54 41 2d 49 4e 46 2f 6d 61 6e  tr("META-INF/man
0b10: 69 66 65 73 74 2e 78 6d 6c 22 2c 20 68 65 6c 70  ifest.xml", help
0b20: 65 72 73 2e 66 69 6c 65 46 69 6c 65 28 22 67 63  ers.fileFile("gc
0b30: 5f 63 6f 72 65 2f 70 79 2f 6f 78 74 2f 6d 61 6e  _core/py/oxt/man
0b40: 69 66 65 73 74 2e 78 6d 6c 22 2c 20 64 56 61 72  ifest.xml", dVar
0b50: 73 29 29 0a 20 20 20 20 68 5a 69 70 2e 77 72 69  s)).    hZip.wri
0b60: 74 65 73 74 72 28 22 64 65 73 63 72 69 70 74 69  testr("descripti
0b70: 6f 6e 2e 78 6d 6c 22 2c 20 68 65 6c 70 65 72 73  on.xml", helpers
0b80: 2e 66 69 6c 65 46 69 6c 65 28 22 67 63 5f 63 6f  .fileFile("gc_co
0b90: 72 65 2f 70 79 2f 6f 78 74 2f 64 65 73 63 72 69  re/py/oxt/descri
0ba0: 70 74 69 6f 6e 2e 78 6d 6c 22 2c 20 64 56 61 72  ption.xml", dVar
0bb0: 73 29 29 0a 20 20 20 20 68 5a 69 70 2e 77 72 69  s)).    hZip.wri
0bc0: 74 65 73 74 72 28 22 4c 69 6e 67 75 69 73 74 69  testr("Linguisti
0bd0: 63 2e 78 63 75 22 2c 20 68 65 6c 70 65 72 73 2e  c.xcu", helpers.
0be0: 66 69 6c 65 46 69 6c 65 28 22 67 63 5f 63 6f 72  fileFile("gc_cor
0bf0: 65 2f 70 79 2f 6f 78 74 2f 4c 69 6e 67 75 69 73  e/py/oxt/Linguis
0c00: 74 69 63 2e 78 63 75 22 2c 20 64 56 61 72 73 29  tic.xcu", dVars)
0c10: 29 0a 20 20 20 20 68 5a 69 70 2e 77 72 69 74 65  ).    hZip.write
0c20: 73 74 72 28 22 47 72 61 6d 6d 61 6c 65 63 74 65  str("Grammalecte
0c30: 2e 70 79 22 2c 20 68 65 6c 70 65 72 73 2e 66 69  .py", helpers.fi
0c40: 6c 65 46 69 6c 65 28 22 67 63 5f 63 6f 72 65 2f  leFile("gc_core/
0c50: 70 79 2f 6f 78 74 2f 47 72 61 6d 6d 61 6c 65 63  py/oxt/Grammalec
0c60: 74 65 2e 70 79 22 2c 20 64 56 61 72 73 29 29 0a  te.py", dVars)).
0c70: 20 20 20 20 68 5a 69 70 2e 77 72 69 74 65 73 74      hZip.writest
0c80: 72 28 22 70 79 74 68 6f 6e 70 61 74 68 2f 68 65  r("pythonpath/he
0c90: 6c 70 65 72 73 2e 70 79 22 2c 20 68 65 6c 70 65  lpers.py", helpe
0ca0: 72 73 2e 66 69 6c 65 46 69 6c 65 28 22 67 63 5f  rs.fileFile("gc_
0cb0: 63 6f 72 65 2f 70 79 2f 6f 78 74 2f 68 65 6c 70  core/py/oxt/help
0cc0: 65 72 73 2e 70 79 22 2c 20 64 56 61 72 73 29 29  ers.py", dVars))
0cd0: 0a 0a 20 20 20 20 66 6f 72 20 73 66 20 69 6e 20  ..    for sf in 
0ce0: 64 56 61 72 73 5b 22 65 78 74 72 61 73 22 5d 2e  dVars["extras"].
0cf0: 73 70 6c 69 74 28 22 2c 22 29 3a 0a 20 20 20 20  split(","):.    
0d00: 20 20 20 20 68 5a 69 70 2e 77 72 69 74 65 73 74      hZip.writest
0d10: 72 28 73 66 2e 73 74 72 69 70 28 29 2c 20 68 65  r(sf.strip(), he
0d20: 6c 70 65 72 73 2e 66 69 6c 65 46 69 6c 65 28 73  lpers.fileFile(s
0d30: 70 4c 61 6e 67 20 2b 20 27 2f 27 20 2b 20 73 66  pLang + '/' + sf
0d40: 2e 73 74 72 69 70 28 29 2c 20 64 56 61 72 73 29  .strip(), dVars)
0d50: 29 0a 0a 20 20 20 20 69 66 20 22 6c 6f 67 6f 22  )..    if "logo"
0d60: 20 69 6e 20 64 56 61 72 73 2e 6b 65 79 73 28 29   in dVars.keys()
0d70: 20 61 6e 64 20 64 56 61 72 73 5b 22 6c 6f 67 6f   and dVars["logo
0d80: 22 5d 2e 73 74 72 69 70 28 29 3a 0a 20 20 20 20  "].strip():.    
0d90: 20 20 20 20 68 5a 69 70 2e 77 72 69 74 65 28 73      hZip.write(s
0da0: 70 4c 61 6e 67 20 2b 20 27 2f 27 20 2b 20 64 56  pLang + '/' + dV
0db0: 61 72 73 5b 22 6c 6f 67 6f 22 5d 2e 73 74 72 69  ars["logo"].stri
0dc0: 70 28 29 2c 20 64 56 61 72 73 5b 22 6c 6f 67 6f  p(), dVars["logo
0dd0: 22 5d 2e 73 74 72 69 70 28 29 29 0a 0a 20 20 20  "].strip())..   
0de0: 20 23 23 20 4f 50 54 49 4f 4e 53 0a 20 20 20 20   ## OPTIONS.    
0df0: 23 20 6f 70 74 69 6f 6e 73 20 64 69 61 6c 6f 67  # options dialog
0e00: 20 77 69 74 68 69 6e 20 4c 4f 2f 4f 4f 20 6f 70   within LO/OO op
0e10: 74 69 6f 6e 73 20 70 61 6e 65 6c 20 28 6c 65 67  tions panel (leg
0e20: 61 63 79 29 0a 20 20 20 20 23 68 5a 69 70 2e 77  acy).    #hZip.w
0e30: 72 69 74 65 73 74 72 28 22 70 79 74 68 6f 6e 70  ritestr("pythonp
0e40: 61 74 68 2f 6c 69 67 68 74 70 72 6f 6f 66 5f 68  ath/lightproof_h
0e50: 61 6e 64 6c 65 72 5f 67 72 61 6d 6d 61 6c 65 63  andler_grammalec
0e60: 74 65 2e 70 79 22 2c 20 68 65 6c 70 65 72 73 2e  te.py", helpers.
0e70: 66 69 6c 65 46 69 6c 65 28 22 67 63 5f 63 6f 72  fileFile("gc_cor
0e80: 65 2f 70 79 2f 6f 78 74 2f 6c 69 67 68 74 70 72  e/py/oxt/lightpr
0e90: 6f 6f 66 5f 68 61 6e 64 6c 65 72 5f 67 72 61 6d  oof_handler_gram
0ea0: 6d 61 6c 65 63 74 65 2e 70 79 22 2c 20 64 56 61  malecte.py", dVa
0eb0: 72 73 29 29 0a 20 20 20 20 23 6c 4c 69 6e 65 4f  rs)).    #lLineO
0ec0: 70 74 69 6f 6e 73 20 3d 20 6f 70 65 6e 28 73 70  ptions = open(sp
0ed0: 4c 61 6e 67 20 2b 20 22 2f 6f 70 74 69 6f 6e 73  Lang + "/options
0ee0: 2e 74 78 74 22 2c 20 22 72 22 2c 20 65 6e 63 6f  .txt", "r", enco
0ef0: 64 69 6e 67 3d 22 75 74 66 2d 38 22 29 2e 72 65  ding="utf-8").re
0f00: 61 64 6c 69 6e 65 73 28 29 0a 20 20 20 20 23 64  adlines().    #d
0f10: 69 61 6c 6f 67 5f 62 75 6e 64 6c 65 64 2e 63 28  ialog_bundled.c(
0f20: 64 56 61 72 73 5b 22 69 6d 70 6c 6e 61 6d 65 22  dVars["implname"
0f30: 5d 2c 20 6c 4c 69 6e 65 4f 70 74 69 6f 6e 73 2c  ], lLineOptions,
0f40: 20 68 5a 69 70 2c 20 64 56 61 72 73 5b 22 6c 61   hZip, dVars["la
0f50: 6e 67 22 5d 29 0a 0a 20 20 20 20 23 20 6f 70 74  ng"])..    # opt
0f60: 69 6f 6e 73 20 64 69 61 6c 6f 67 0a 20 20 20 20  ions dialog.    
0f70: 68 5a 69 70 2e 77 72 69 74 65 73 74 72 28 22 70  hZip.writestr("p
0f80: 79 74 68 6f 6e 70 61 74 68 2f 4f 70 74 69 6f 6e  ythonpath/Option
0f90: 73 2e 70 79 22 2c 20 68 65 6c 70 65 72 73 2e 66  s.py", helpers.f
0fa0: 69 6c 65 46 69 6c 65 28 22 67 63 5f 63 6f 72 65  ileFile("gc_core
0fb0: 2f 70 79 2f 6f 78 74 2f 4f 70 74 69 6f 6e 73 2e  /py/oxt/Options.
0fc0: 70 79 22 2c 20 64 56 61 72 73 29 29 0a 20 20 20  py", dVars)).   
0fd0: 20 68 5a 69 70 2e 77 72 69 74 65 28 22 67 63 5f   hZip.write("gc_
0fe0: 63 6f 72 65 2f 70 79 2f 6f 78 74 2f 6f 70 5f 73  core/py/oxt/op_s
0ff0: 74 72 69 6e 67 73 2e 70 79 22 2c 20 22 70 79 74  trings.py", "pyt
1000: 68 6f 6e 70 61 74 68 2f 6f 70 5f 73 74 72 69 6e  honpath/op_strin
1010: 67 73 2e 70 79 22 29 0a 20 20 20 20 23 20 6f 70  gs.py").    # op
1020: 74 69 6f 6e 73 20 64 69 61 6c 6f 67 20 77 69 74  tions dialog wit
1030: 68 69 6e 20 57 72 69 74 65 72 20 6f 70 74 69 6f  hin Writer optio
1040: 6e 73 20 70 61 6e 65 6c 0a 20 20 20 20 64 56 61  ns panel.    dVa
1050: 72 73 5b 22 78 64 6c 5f 64 69 61 6c 6f 67 5f 6f  rs["xdl_dialog_o
1060: 70 74 69 6f 6e 73 22 5d 20 3d 20 63 72 65 61 74  ptions"] = creat
1070: 65 44 69 61 6c 6f 67 4f 70 74 69 6f 6e 73 58 44  eDialogOptionsXD
1080: 4c 28 64 56 61 72 73 29 0a 20 20 20 20 64 56 61  L(dVars).    dVa
1090: 72 73 5b 22 78 63 73 5f 6f 70 74 69 6f 6e 73 22  rs["xcs_options"
10a0: 5d 20 3d 20 22 5c 6e 22 2e 6a 6f 69 6e 28 5b 20  ] = "\n".join([ 
10b0: 27 3c 70 72 6f 70 20 6f 6f 72 3a 6e 61 6d 65 3d  '<prop oor:name=
10c0: 22 27 2b 73 4f 70 74 2b 27 22 20 6f 6f 72 3a 74  "'+sOpt+'" oor:t
10d0: 79 70 65 3d 22 78 73 3a 73 74 72 69 6e 67 22 3e  ype="xs:string">
10e0: 3c 76 61 6c 75 65 3e 3c 2f 76 61 6c 75 65 3e 3c  <value></value><
10f0: 2f 70 72 6f 70 3e 27 20 66 6f 72 20 73 4f 70 74  /prop>' for sOpt
1100: 20 69 6e 20 64 56 61 72 73 5b 22 64 4f 70 74 50   in dVars["dOptP
1110: 79 74 68 6f 6e 22 5d 20 5d 29 0a 20 20 20 20 64  ython"] ]).    d
1120: 56 61 72 73 5b 22 78 63 75 5f 6c 61 62 65 6c 5f  Vars["xcu_label_
1130: 76 61 6c 75 65 73 22 5d 20 3d 20 22 5c 6e 22 2e  values"] = "\n".
1140: 6a 6f 69 6e 28 5b 20 27 3c 76 61 6c 75 65 20 78  join([ '<value x
1150: 6d 6c 3a 6c 61 6e 67 3d 22 27 2b 73 4c 61 6e 67  ml:lang="'+sLang
1160: 2b 27 22 3e 27 20 2b 20 64 56 61 72 73 5b 22 64  +'">' + dVars["d
1170: 4f 70 74 4c 61 62 65 6c 22 5d 5b 73 4c 61 6e 67  OptLabel"][sLang
1180: 5d 5b 22 5f 5f 6f 70 74 69 6f 6e 74 69 74 6c 65  ]["__optiontitle
1190: 5f 5f 22 5d 20 2b 20 27 3c 2f 76 61 6c 75 65 3e  __"] + '</value>
11a0: 27 20 20 66 6f 72 20 73 4c 61 6e 67 20 69 6e 20  '  for sLang in 
11b0: 64 56 61 72 73 5b 22 64 4f 70 74 4c 61 62 65 6c  dVars["dOptLabel
11c0: 22 5d 20 5d 29 0a 20 20 20 20 68 5a 69 70 2e 77  "] ]).    hZip.w
11d0: 72 69 74 65 73 74 72 28 22 64 69 61 6c 6f 67 2f  ritestr("dialog/
11e0: 6f 70 74 69 6f 6e 73 5f 70 61 67 65 2e 78 64 6c  options_page.xdl
11f0: 22 2c 20 68 65 6c 70 65 72 73 2e 66 69 6c 65 46  ", helpers.fileF
1200: 69 6c 65 28 22 67 63 5f 63 6f 72 65 2f 70 79 2f  ile("gc_core/py/
1210: 6f 78 74 2f 6f 70 74 69 6f 6e 73 5f 70 61 67 65  oxt/options_page
1220: 2e 78 64 6c 22 2c 20 64 56 61 72 73 29 29 0a 20  .xdl", dVars)). 
1230: 20 20 20 68 5a 69 70 2e 77 72 69 74 65 73 74 72     hZip.writestr
1240: 28 22 64 69 61 6c 6f 67 2f 4f 70 74 69 6f 6e 73  ("dialog/Options
1250: 44 69 61 6c 6f 67 2e 78 63 73 22 2c 20 68 65 6c  Dialog.xcs", hel
1260: 70 65 72 73 2e 66 69 6c 65 46 69 6c 65 28 22 67  pers.fileFile("g
1270: 63 5f 63 6f 72 65 2f 70 79 2f 6f 78 74 2f 4f 70  c_core/py/oxt/Op
1280: 74 69 6f 6e 73 44 69 61 6c 6f 67 2e 78 63 73 22  tionsDialog.xcs"
1290: 2c 20 64 56 61 72 73 29 29 0a 20 20 20 20 68 5a  , dVars)).    hZ
12a0: 69 70 2e 77 72 69 74 65 73 74 72 28 22 64 69 61  ip.writestr("dia
12b0: 6c 6f 67 2f 4f 70 74 69 6f 6e 73 44 69 61 6c 6f  log/OptionsDialo
12c0: 67 2e 78 63 75 22 2c 20 68 65 6c 70 65 72 73 2e  g.xcu", helpers.
12d0: 66 69 6c 65 46 69 6c 65 28 22 67 63 5f 63 6f 72  fileFile("gc_cor
12e0: 65 2f 70 79 2f 6f 78 74 2f 4f 70 74 69 6f 6e 73  e/py/oxt/Options
12f0: 44 69 61 6c 6f 67 2e 78 63 75 22 2c 20 64 56 61  Dialog.xcu", dVa
1300: 72 73 29 29 0a 20 20 20 20 68 5a 69 70 2e 77 72  rs)).    hZip.wr
1310: 69 74 65 73 74 72 28 22 64 69 61 6c 6f 67 2f 22  itestr("dialog/"
1320: 20 2b 20 64 56 61 72 73 5b 27 6c 61 6e 67 27 5d   + dVars['lang']
1330: 20 2b 20 22 5f 65 6e 2e 64 65 66 61 75 6c 74 22   + "_en.default"
1340: 2c 20 22 22 29 0a 20 20 20 20 66 6f 72 20 73 4c  , "").    for sL
1350: 61 6e 67 4c 62 6c 2c 20 64 4f 70 74 4c 62 6c 20  angLbl, dOptLbl 
1360: 69 6e 20 64 56 61 72 73 5b 27 64 4f 70 74 4c 61  in dVars['dOptLa
1370: 62 65 6c 27 5d 2e 69 74 65 6d 73 28 29 3a 0a 20  bel'].items():. 
1380: 20 20 20 20 20 20 20 68 5a 69 70 2e 77 72 69 74         hZip.writ
1390: 65 73 74 72 28 66 22 64 69 61 6c 6f 67 2f 7b 64  estr(f"dialog/{d
13a0: 56 61 72 73 5b 27 6c 61 6e 67 27 5d 7d 5f 7b 73  Vars['lang']}_{s
13b0: 4c 61 6e 67 4c 62 6c 7d 2e 70 72 6f 70 65 72 74  LangLbl}.propert
13c0: 69 65 73 22 2c 20 63 72 65 61 74 65 4f 70 74 69  ies", createOpti
13d0: 6f 6e 73 4c 61 62 65 6c 50 72 6f 70 65 72 74 69  onsLabelProperti
13e0: 65 73 28 64 4f 70 74 4c 62 6c 29 29 0a 0a 20 20  es(dOptLbl))..  
13f0: 20 20 23 23 20 41 44 44 4f 4e 53 20 4f 58 54 0a    ## ADDONS OXT.
1400: 20 20 20 20 70 72 69 6e 74 28 22 2b 20 4f 58 54      print("+ OXT
1410: 3a 20 22 2c 20 65 6e 64 3d 22 22 29 0a 20 20 20  : ", end="").   
1420: 20 66 6f 72 20 73 70 66 53 72 63 2c 20 73 70 66   for spfSrc, spf
1430: 44 73 74 20 69 6e 20 64 4f 78 74 2e 69 74 65 6d  Dst in dOxt.item
1440: 73 28 29 3a 0a 20 20 20 20 20 20 20 20 70 72 69  s():.        pri
1450: 6e 74 28 73 70 66 53 72 63 2c 20 65 6e 64 3d 22  nt(spfSrc, end="
1460: 2c 20 22 29 0a 20 20 20 20 20 20 20 20 69 66 20  , ").        if 
1470: 6f 73 2e 70 61 74 68 2e 69 73 64 69 72 28 73 70  os.path.isdir(sp
1480: 4c 61 6e 67 2b 27 2f 27 2b 73 70 66 53 72 63 29  Lang+'/'+spfSrc)
1490: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 66 6f  :.            fo
14a0: 72 20 73 66 20 69 6e 20 6f 73 2e 6c 69 73 74 64  r sf in os.listd
14b0: 69 72 28 73 70 4c 61 6e 67 2b 27 2f 27 2b 73 70  ir(spLang+'/'+sp
14c0: 66 53 72 63 29 3a 0a 20 20 20 20 20 20 20 20 20  fSrc):.         
14d0: 20 20 20 20 20 20 20 69 66 20 73 66 2e 65 6e 64         if sf.end
14e0: 73 77 69 74 68 28 28 27 2e 74 78 74 27 2c 20 27  swith(('.txt', '
14f0: 2e 70 79 27 29 29 3a 0a 20 20 20 20 20 20 20 20  .py')):.        
1500: 20 20 20 20 20 20 20 20 20 20 20 20 68 5a 69 70              hZip
1510: 2e 77 72 69 74 65 73 74 72 28 73 70 66 44 73 74  .writestr(spfDst
1520: 2b 22 2f 22 2b 73 66 2c 20 68 65 6c 70 65 72 73  +"/"+sf, helpers
1530: 2e 66 69 6c 65 46 69 6c 65 28 73 70 4c 61 6e 67  .fileFile(spLang
1540: 2b 27 2f 27 2b 73 70 66 53 72 63 2b 22 2f 22 2b  +'/'+spfSrc+"/"+
1550: 73 66 2c 20 64 56 61 72 73 29 29 0a 20 20 20 20  sf, dVars)).    
1560: 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65              else
1570: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
1580: 20 20 20 20 20 20 68 5a 69 70 2e 77 72 69 74 65        hZip.write
1590: 28 73 70 4c 61 6e 67 2b 27 2f 27 2b 73 70 66 53  (spLang+'/'+spfS
15a0: 72 63 2b 22 2f 22 2b 73 66 2c 20 73 70 66 44 73  rc+"/"+sf, spfDs
15b0: 74 2b 22 2f 22 2b 73 66 29 0a 20 20 20 20 20 20  t+"/"+sf).      
15c0: 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20    else:.        
15d0: 20 20 20 20 69 66 20 73 70 66 53 72 63 2e 65 6e      if spfSrc.en
15e0: 64 73 77 69 74 68 28 28 27 2e 74 78 74 27 2c 20  dswith(('.txt', 
15f0: 27 2e 70 79 27 29 29 3a 0a 20 20 20 20 20 20 20  '.py')):.       
1600: 20 20 20 20 20 20 20 20 20 68 5a 69 70 2e 77 72           hZip.wr
1610: 69 74 65 73 74 72 28 73 70 66 44 73 74 2c 20 68  itestr(spfDst, h
1620: 65 6c 70 65 72 73 2e 66 69 6c 65 46 69 6c 65 28  elpers.fileFile(
1630: 73 70 4c 61 6e 67 2b 27 2f 27 2b 73 70 66 53 72  spLang+'/'+spfSr
1640: 63 2c 20 64 56 61 72 73 29 29 0a 20 20 20 20 20  c, dVars)).     
1650: 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20         else:.   
1660: 20 20 20 20 20 20 20 20 20 20 20 20 20 68 5a 69               hZi
1670: 70 2e 77 72 69 74 65 28 73 70 4c 61 6e 67 2b 27  p.write(spLang+'
1680: 2f 27 2b 73 70 66 53 72 63 2c 20 73 70 66 44 73  /'+spfSrc, spfDs
1690: 74 29 0a 20 20 20 20 70 72 69 6e 74 28 29 0a 20  t).    print(). 
16a0: 20 20 20 68 5a 69 70 2e 63 6c 6f 73 65 28 29 0a     hZip.close().
16b0: 0a 20 20 20 20 23 20 49 6e 73 74 61 6c 6c 61 74  .    # Installat
16c0: 69 6f 6e 20 69 6e 20 57 72 69 74 65 72 20 70 72  ion in Writer pr
16d0: 6f 66 69 6c 65 0a 20 20 20 20 69 66 20 62 49 6e  ofile.    if bIn
16e0: 73 74 61 6c 6c 3a 0a 20 20 20 20 20 20 20 20 70  stall:.        p
16f0: 72 69 6e 74 28 22 3e 20 69 6e 73 74 61 6c 6c 61  rint("> installa
1700: 74 69 6f 6e 20 69 6e 20 57 72 69 74 65 72 22 29  tion in Writer")
1710: 0a 20 20 20 20 20 20 20 20 69 66 20 64 56 61 72  .        if dVar
1720: 73 2e 67 65 74 28 27 75 6e 6f 70 6b 67 27 2c 20  s.get('unopkg', 
1730: 46 61 6c 73 65 29 3a 0a 20 20 20 20 20 20 20 20  False):.        
1740: 20 20 20 20 63 6d 64 20 3d 20 27 22 27 2b 6f 73      cmd = '"'+os
1750: 2e 70 61 74 68 2e 61 62 73 70 61 74 68 28 64 56  .path.abspath(dV
1760: 61 72 73 2e 67 65 74 28 27 75 6e 6f 70 6b 67 27  ars.get('unopkg'
1770: 29 2b 27 22 20 61 64 64 20 2d 66 20 27 2b 73 70  )+'" add -f '+sp
1780: 66 5a 69 70 29 0a 20 20 20 20 20 20 20 20 20 20  fZip).          
1790: 20 20 70 72 69 6e 74 28 63 6d 64 29 0a 20 20 20    print(cmd).   
17a0: 20 20 20 20 20 20 20 20 20 6f 73 2e 73 79 73 74           os.syst
17b0: 65 6d 28 63 6d 64 29 0a 20 20 20 20 20 20 20 20  em(cmd).        
17c0: 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20  else:.          
17d0: 20 20 70 72 69 6e 74 28 22 23 20 45 72 72 6f 72    print("# Error
17e0: 3a 20 70 61 74 68 20 61 6e 64 20 66 69 6c 65 6e  : path and filen
17f0: 61 6d 65 20 6f 66 20 75 6e 6f 70 6b 67 20 6e 6f  ame of unopkg no
1800: 74 20 73 65 74 20 69 6e 20 63 6f 6e 66 69 67 2e  t set in config.
1810: 69 6e 69 22 29 0a 0a 0a 64 65 66 20 63 72 65 61  ini")...def crea
1820: 74 65 50 61 63 6b 61 67 65 5a 69 70 20 28 64 56  tePackageZip (dV
1830: 61 72 73 2c 20 73 70 4c 61 6e 67 50 61 63 6b 29  ars, spLangPack)
1840: 3a 0a 20 20 20 20 22 63 72 65 61 74 65 20 73 65  :.    "create se
1850: 72 76 65 72 20 7a 69 70 22 0a 20 20 20 20 73 70  rver zip".    sp
1860: 66 5a 69 70 20 3d 20 66 22 5f 62 75 69 6c 64 2f  fZip = f"_build/
1870: 7b 64 56 61 72 73 5b 27 6e 61 6d 65 27 5d 7d 2d  {dVars['name']}-
1880: 7b 64 56 61 72 73 5b 27 6c 61 6e 67 27 5d 7d 2d  {dVars['lang']}-
1890: 76 7b 64 56 61 72 73 5b 27 76 65 72 73 69 6f 6e  v{dVars['version
18a0: 27 5d 7d 2e 7a 69 70 22 0a 20 20 20 20 68 5a 69  ']}.zip".    hZi
18b0: 70 20 3d 20 7a 69 70 66 69 6c 65 2e 5a 69 70 46  p = zipfile.ZipF
18c0: 69 6c 65 28 73 70 66 5a 69 70 2c 20 6d 6f 64 65  ile(spfZip, mode
18d0: 3d 27 77 27 2c 20 63 6f 6d 70 72 65 73 73 69 6f  ='w', compressio
18e0: 6e 3d 7a 69 70 66 69 6c 65 2e 5a 49 50 5f 44 45  n=zipfile.ZIP_DE
18f0: 46 4c 41 54 45 44 29 0a 20 20 20 20 63 6f 70 79  FLATED).    copy
1900: 47 72 61 6d 6d 61 6c 65 63 74 65 50 79 50 61 63  GrammalectePyPac
1910: 6b 61 67 65 49 6e 5a 69 70 46 69 6c 65 28 68 5a  kageInZipFile(hZ
1920: 69 70 2c 20 73 70 4c 61 6e 67 50 61 63 6b 29 0a  ip, spLangPack).
1930: 20 20 20 20 66 6f 72 20 73 70 66 20 69 6e 20 5b      for spf in [
1940: 22 67 72 61 6d 6d 61 6c 65 63 74 65 2d 63 6c 69  "grammalecte-cli
1950: 2e 70 79 22 2c 20 22 67 72 61 6d 6d 61 6c 65 63  .py", "grammalec
1960: 74 65 2d 73 65 72 76 65 72 2e 70 79 22 2c 20 5c  te-server.py", \
1970: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1980: 20 22 52 45 41 44 4d 45 2e 74 78 74 22 2c 20 22   "README.txt", "
1990: 4c 49 43 45 4e 53 45 2e 74 78 74 22 2c 20 22 4c  LICENSE.txt", "L
19a0: 49 43 45 4e 53 45 2e 66 72 2e 74 78 74 22 5d 3a  ICENSE.fr.txt"]:
19b0: 0a 20 20 20 20 20 20 20 20 68 5a 69 70 2e 77 72  .        hZip.wr
19c0: 69 74 65 28 73 70 66 29 0a 20 20 20 20 68 5a 69  ite(spf).    hZi
19d0: 70 2e 77 72 69 74 65 73 74 72 28 22 73 65 74 75  p.writestr("setu
19e0: 70 2e 70 79 22 2c 20 68 65 6c 70 65 72 73 2e 66  p.py", helpers.f
19f0: 69 6c 65 46 69 6c 65 28 22 67 63 5f 6c 61 6e 67  ileFile("gc_lang
1a00: 2f 66 72 2f 73 65 74 75 70 2e 70 79 22 2c 20 64  /fr/setup.py", d
1a10: 56 61 72 73 29 29 0a 0a 0a 64 65 66 20 63 6f 70  Vars))...def cop
1a20: 79 47 72 61 6d 6d 61 6c 65 63 74 65 50 79 50 61  yGrammalectePyPa
1a30: 63 6b 61 67 65 49 6e 5a 69 70 46 69 6c 65 20 28  ckageInZipFile (
1a40: 68 5a 69 70 2c 20 73 70 4c 61 6e 67 50 61 63 6b  hZip, spLangPack
1a50: 2c 20 73 41 64 64 50 61 74 68 3d 22 22 29 3a 0a  , sAddPath=""):.
1a60: 20 20 20 20 22 63 6f 70 79 20 47 72 61 6d 6d 61      "copy Gramma
1a70: 6c 65 63 74 65 20 50 79 74 68 6f 6e 20 70 61 63  lecte Python pac
1a80: 6b 61 67 65 20 69 6e 20 7a 69 70 20 66 69 6c 65  kage in zip file
1a90: 22 0a 20 20 20 20 66 6f 72 20 73 66 20 69 6e 20  ".    for sf in 
1aa0: 6f 73 2e 6c 69 73 74 64 69 72 28 22 67 72 61 6d  os.listdir("gram
1ab0: 6d 61 6c 65 63 74 65 22 29 3a 0a 20 20 20 20 20  malecte"):.     
1ac0: 20 20 20 69 66 20 6e 6f 74 20 6f 73 2e 70 61 74     if not os.pat
1ad0: 68 2e 69 73 64 69 72 28 22 67 72 61 6d 6d 61 6c  h.isdir("grammal
1ae0: 65 63 74 65 2f 22 2b 73 66 29 3a 0a 20 20 20 20  ecte/"+sf):.    
1af0: 20 20 20 20 20 20 20 20 68 5a 69 70 2e 77 72 69          hZip.wri
1b00: 74 65 28 22 67 72 61 6d 6d 61 6c 65 63 74 65 2f  te("grammalecte/
1b10: 22 2b 73 66 2c 20 73 41 64 64 50 61 74 68 2b 22  "+sf, sAddPath+"
1b20: 67 72 61 6d 6d 61 6c 65 63 74 65 2f 22 2b 73 66  grammalecte/"+sf
1b30: 29 0a 20 20 20 20 66 6f 72 20 73 66 20 69 6e 20  ).    for sf in 
1b40: 6f 73 2e 6c 69 73 74 64 69 72 28 22 67 72 61 6d  os.listdir("gram
1b50: 6d 61 6c 65 63 74 65 2f 67 72 61 70 68 73 70 65  malecte/graphspe
1b60: 6c 6c 22 29 3a 0a 20 20 20 20 20 20 20 20 69 66  ll"):.        if
1b70: 20 6e 6f 74 20 6f 73 2e 70 61 74 68 2e 69 73 64   not os.path.isd
1b80: 69 72 28 22 67 72 61 6d 6d 61 6c 65 63 74 65 2f  ir("grammalecte/
1b90: 67 72 61 70 68 73 70 65 6c 6c 2f 22 2b 73 66 29  graphspell/"+sf)
1ba0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 68 5a  :.            hZ
1bb0: 69 70 2e 77 72 69 74 65 28 22 67 72 61 6d 6d 61  ip.write("gramma
1bc0: 6c 65 63 74 65 2f 67 72 61 70 68 73 70 65 6c 6c  lecte/graphspell
1bd0: 2f 22 2b 73 66 2c 20 73 41 64 64 50 61 74 68 2b  /"+sf, sAddPath+
1be0: 22 67 72 61 6d 6d 61 6c 65 63 74 65 2f 67 72 61  "grammalecte/gra
1bf0: 70 68 73 70 65 6c 6c 2f 22 2b 73 66 29 0a 20 20  phspell/"+sf).  
1c00: 20 20 66 6f 72 20 73 66 20 69 6e 20 6f 73 2e 6c    for sf in os.l
1c10: 69 73 74 64 69 72 28 22 67 72 61 6d 6d 61 6c 65  istdir("grammale
1c20: 63 74 65 2f 67 72 61 70 68 73 70 65 6c 6c 2f 5f  cte/graphspell/_
1c30: 64 69 63 74 69 6f 6e 61 72 69 65 73 22 29 3a 0a  dictionaries"):.
1c40: 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 6f          if not o
1c50: 73 2e 70 61 74 68 2e 69 73 64 69 72 28 22 67 72  s.path.isdir("gr
1c60: 61 6d 6d 61 6c 65 63 74 65 2f 67 72 61 70 68 73  ammalecte/graphs
1c70: 70 65 6c 6c 2f 5f 64 69 63 74 69 6f 6e 61 72 69  pell/_dictionari
1c80: 65 73 2f 22 2b 73 66 29 3a 0a 20 20 20 20 20 20  es/"+sf):.      
1c90: 20 20 20 20 20 20 68 5a 69 70 2e 77 72 69 74 65        hZip.write
1ca0: 28 22 67 72 61 6d 6d 61 6c 65 63 74 65 2f 67 72  ("grammalecte/gr
1cb0: 61 70 68 73 70 65 6c 6c 2f 5f 64 69 63 74 69 6f  aphspell/_dictio
1cc0: 6e 61 72 69 65 73 2f 22 2b 73 66 2c 20 73 41 64  naries/"+sf, sAd
1cd0: 64 50 61 74 68 2b 22 67 72 61 6d 6d 61 6c 65 63  dPath+"grammalec
1ce0: 74 65 2f 67 72 61 70 68 73 70 65 6c 6c 2f 5f 64  te/graphspell/_d
1cf0: 69 63 74 69 6f 6e 61 72 69 65 73 2f 22 2b 73 66  ictionaries/"+sf
1d00: 29 0a 20 20 20 20 66 6f 72 20 73 66 20 69 6e 20  ).    for sf in 
1d10: 6f 73 2e 6c 69 73 74 64 69 72 28 73 70 4c 61 6e  os.listdir(spLan
1d20: 67 50 61 63 6b 29 3a 0a 20 20 20 20 20 20 20 20  gPack):.        
1d30: 69 66 20 6e 6f 74 20 6f 73 2e 70 61 74 68 2e 69  if not os.path.i
1d40: 73 64 69 72 28 73 70 4c 61 6e 67 50 61 63 6b 2b  sdir(spLangPack+
1d50: 22 2f 22 2b 73 66 29 3a 0a 20 20 20 20 20 20 20  "/"+sf):.       
1d60: 20 20 20 20 20 68 5a 69 70 2e 77 72 69 74 65 28       hZip.write(
1d70: 73 70 4c 61 6e 67 50 61 63 6b 2b 22 2f 22 2b 73  spLangPack+"/"+s
1d80: 66 2c 20 73 41 64 64 50 61 74 68 2b 73 70 4c 61  f, sAddPath+spLa
1d90: 6e 67 50 61 63 6b 2b 22 2f 22 2b 73 66 29 0a 0a  ngPack+"/"+sf)..
1da0: 0a 64 65 66 20 63 72 65 61 74 65 20 28 73 4c 61  .def create (sLa
1db0: 6e 67 2c 20 78 43 6f 6e 66 69 67 2c 20 62 49 6e  ng, xConfig, bIn
1dc0: 73 74 61 6c 6c 4f 58 54 2c 20 62 4a 61 76 61 53  stallOXT, bJavaS
1dd0: 63 72 69 70 74 2c 20 62 55 73 65 43 61 63 68 65  cript, bUseCache
1de0: 29 3a 0a 20 20 20 20 22 6d 61 6b 65 20 47 72 61  ):.    "make Gra
1df0: 6d 6d 61 6c 65 63 74 65 20 66 6f 72 20 70 72 6f  mmalecte for pro
1e00: 6a 65 63 74 20 3c 73 4c 61 6e 67 3e 22 0a 20 20  ject <sLang>".  
1e10: 20 20 6f 4e 6f 77 20 3d 20 64 61 74 65 74 69 6d    oNow = datetim
1e20: 65 2e 64 61 74 65 74 69 6d 65 2e 6e 6f 77 28 29  e.datetime.now()
1e30: 0a 20 20 20 20 70 72 69 6e 74 28 22 3d 3d 3d 3d  .    print("====
1e40: 3d 3d 3d 3d 3d 3d 3d 3d 3d 3d 20 4d 41 4b 45 20  ========== MAKE 
1e50: 47 52 41 4d 4d 41 4c 45 43 54 45 20 5b 7b 30 7d  GRAMMALECTE [{0}
1e60: 5d 20 61 74 20 7b 31 2e 68 6f 75 72 3a 3e 32 7d  ] at {1.hour:>2}
1e70: 20 68 20 7b 31 2e 6d 69 6e 75 74 65 3a 3e 32 7d   h {1.minute:>2}
1e80: 20 6d 69 6e 20 7b 31 2e 73 65 63 6f 6e 64 3a 3e   min {1.second:>
1e90: 32 7d 20 73 20 3d 3d 3d 3d 3d 3d 3d 3d 3d 3d 3d  2} s ===========
1ea0: 3d 3d 3d 22 2e 66 6f 72 6d 61 74 28 73 4c 61 6e  ===".format(sLan
1eb0: 67 2c 20 6f 4e 6f 77 29 29 0a 0a 20 20 20 20 23  g, oNow))..    #
1ec0: 23 23 23 20 52 45 41 44 20 43 4f 4e 46 49 47 55  ### READ CONFIGU
1ed0: 52 41 54 49 4f 4e 0a 20 20 20 20 70 72 69 6e 74  RATION.    print
1ee0: 28 22 3e 20 72 65 61 64 20 63 6f 6e 66 69 67 75  ("> read configu
1ef0: 72 61 74 69 6f 6e 2e 2e 2e 22 29 0a 20 20 20 20  ration...").    
1f00: 73 70 4c 61 6e 67 20 3d 20 22 67 63 5f 6c 61 6e  spLang = "gc_lan
1f10: 67 2f 22 20 2b 20 73 4c 61 6e 67 0a 0a 20 20 20  g/" + sLang..   
1f20: 20 64 56 61 72 73 20 3d 20 78 43 6f 6e 66 69 67   dVars = xConfig
1f30: 2e 5f 73 65 63 74 69 6f 6e 73 5b 27 61 72 67 73  ._sections['args
1f40: 27 5d 0a 20 20 20 20 64 56 61 72 73 5b 27 6c 6f  '].    dVars['lo
1f50: 63 61 6c 65 73 27 5d 20 3d 20 64 56 61 72 73 5b  cales'] = dVars[
1f60: 22 6c 6f 63 61 6c 65 73 22 5d 2e 72 65 70 6c 61  "locales"].repla
1f70: 63 65 28 22 5f 22 2c 20 22 2d 22 29 0a 20 20 20  ce("_", "-").   
1f80: 20 64 56 61 72 73 5b 27 6c 6f 63 27 5d 20 3d 20   dVars['loc'] = 
1f90: 73 74 72 28 7b 20 73 3a 20 5b 73 5b 30 3a 32 5d  str({ s: [s[0:2]
1fa0: 2c 20 73 5b 33 3a 35 5d 2c 20 22 22 5d 20 20 66  , s[3:5], ""]  f
1fb0: 6f 72 20 73 20 69 6e 20 64 56 61 72 73 5b 22 6c  or s in dVars["l
1fc0: 6f 63 61 6c 65 73 22 5d 2e 73 70 6c 69 74 28 22  ocales"].split("
1fd0: 20 22 29 20 7d 29 0a 0a 20 20 20 20 23 23 20 43   ") })..    ## C
1fe0: 4f 4d 50 49 4c 45 20 52 55 4c 45 53 0a 20 20 20  OMPILE RULES.   
1ff0: 20 64 52 65 73 75 6c 74 20 3d 20 63 6f 6d 70 69   dResult = compi
2000: 6c 65 5f 72 75 6c 65 73 2e 6d 61 6b 65 28 73 70  le_rules.make(sp
2010: 4c 61 6e 67 2c 20 64 56 61 72 73 5b 27 6c 61 6e  Lang, dVars['lan
2020: 67 27 5d 2c 20 62 55 73 65 43 61 63 68 65 29 0a  g'], bUseCache).
2030: 20 20 20 20 64 56 61 72 73 2e 75 70 64 61 74 65      dVars.update
2040: 28 64 52 65 73 75 6c 74 29 0a 0a 20 20 20 20 23  (dResult)..    #
2050: 23 20 52 45 41 44 20 47 52 41 4d 4d 41 52 20 43  # READ GRAMMAR C
2060: 48 45 43 4b 45 52 20 50 4c 55 47 49 4e 53 0a 20  HECKER PLUGINS. 
2070: 20 20 20 70 72 69 6e 74 28 22 50 59 54 48 4f 4e     print("PYTHON
2080: 3a 22 29 0a 20 20 20 20 70 72 69 6e 74 28 22 2b  :").    print("+
2090: 20 50 6c 75 67 69 6e 73 3a 20 22 2c 20 65 6e 64   Plugins: ", end
20a0: 3d 22 22 29 0a 20 20 20 20 73 43 6f 64 65 50 6c  ="").    sCodePl
20b0: 75 67 69 6e 73 20 3d 20 22 22 0a 20 20 20 20 66  ugins = "".    f
20c0: 6f 72 20 73 66 20 69 6e 20 6f 73 2e 6c 69 73 74  or sf in os.list
20d0: 64 69 72 28 73 70 4c 61 6e 67 2b 22 2f 6d 6f 64  dir(spLang+"/mod
20e0: 75 6c 65 73 22 29 3a 0a 20 20 20 20 20 20 20 20  ules"):.        
20f0: 69 66 20 72 65 2e 6d 61 74 63 68 28 72 22 67 63  if re.match(r"gc
2100: 65 5f 5c 77 2b 5b 2e 5d 70 79 24 22 2c 20 73 66  e_\w+[.]py$", sf
2110: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 73  ):.            s
2120: 43 6f 64 65 50 6c 75 67 69 6e 73 20 2b 3d 20 22  CodePlugins += "
2130: 5c 6e 5c 6e 22 20 2b 20 6f 70 65 6e 28 73 70 4c  \n\n" + open(spL
2140: 61 6e 67 2b 27 2f 6d 6f 64 75 6c 65 73 2f 27 2b  ang+'/modules/'+
2150: 73 66 2c 20 22 72 22 2c 20 65 6e 63 6f 64 69 6e  sf, "r", encodin
2160: 67 3d 22 75 74 66 2d 38 22 29 2e 72 65 61 64 28  g="utf-8").read(
2170: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 70 72  ).            pr
2180: 69 6e 74 28 73 66 2c 20 65 6e 64 3d 22 2c 20 22  int(sf, end=", "
2190: 29 0a 20 20 20 20 70 72 69 6e 74 28 29 0a 20 20  ).    print().  
21a0: 20 20 64 56 61 72 73 5b 22 70 6c 75 67 69 6e 73    dVars["plugins
21b0: 22 5d 20 3d 20 73 43 6f 64 65 50 6c 75 67 69 6e  "] = sCodePlugin
21c0: 73 0a 0a 20 20 20 20 23 23 20 43 4f 50 59 20 47  s..    ## COPY G
21d0: 43 5f 43 4f 52 45 20 43 4f 4d 4d 4f 4e 20 46 49  C_CORE COMMON FI
21e0: 4c 45 53 0a 20 20 20 20 66 6f 72 20 73 66 20 69  LES.    for sf i
21f0: 6e 20 6f 73 2e 6c 69 73 74 64 69 72 28 22 67 63  n os.listdir("gc
2200: 5f 63 6f 72 65 2f 70 79 22 29 3a 0a 20 20 20 20  _core/py"):.    
2210: 20 20 20 20 69 66 20 6e 6f 74 20 6f 73 2e 70 61      if not os.pa
2220: 74 68 2e 69 73 64 69 72 28 22 67 63 5f 63 6f 72  th.isdir("gc_cor
2230: 65 2f 70 79 2f 22 2b 73 66 29 3a 0a 20 20 20 20  e/py/"+sf):.    
2240: 20 20 20 20 20 20 20 20 68 65 6c 70 65 72 73 2e          helpers.
2250: 63 6f 70 79 41 6e 64 46 69 6c 65 54 65 6d 70 6c  copyAndFileTempl
2260: 61 74 65 28 22 67 63 5f 63 6f 72 65 2f 70 79 2f  ate("gc_core/py/
2270: 22 2b 73 66 2c 20 22 67 72 61 6d 6d 61 6c 65 63  "+sf, "grammalec
2280: 74 65 2f 22 2b 73 66 2c 20 64 56 61 72 73 29 0a  te/"+sf, dVars).
2290: 20 20 20 20 66 69 6c 65 5f 75 74 69 6c 2e 63 6f      file_util.co
22a0: 70 79 5f 66 69 6c 65 28 22 33 72 64 2f 62 6f 74  py_file("3rd/bot
22b0: 74 6c 65 2e 70 79 22 2c 20 22 67 72 61 6d 6d 61  tle.py", "gramma
22c0: 6c 65 63 74 65 2f 62 6f 74 74 6c 65 2e 70 79 22  lecte/bottle.py"
22d0: 29 0a 20 20 20 20 6f 70 65 6e 28 22 67 72 61 6d  ).    open("gram
22e0: 6d 61 6c 65 63 74 65 2f 57 41 52 4e 49 4e 47 2e  malecte/WARNING.
22f0: 74 78 74 22 2c 20 22 77 22 2c 20 65 6e 63 6f 64  txt", "w", encod
2300: 69 6e 67 3d 22 75 74 66 2d 38 22 2c 20 6e 65 77  ing="utf-8", new
2310: 6c 69 6e 65 3d 22 5c 6e 22 29 2e 77 72 69 74 65  line="\n").write
2320: 28 73 57 61 72 6e 69 6e 67 4d 65 73 73 61 67 65  (sWarningMessage
2330: 29 0a 0a 20 20 20 20 23 23 20 43 52 45 41 54 45  )..    ## CREATE
2340: 20 47 52 41 4d 4d 41 52 20 43 48 45 43 4b 45 52   GRAMMAR CHECKER
2350: 20 50 41 43 4b 41 47 45 0a 20 20 20 20 73 70 4c   PACKAGE.    spL
2360: 61 6e 67 50 61 63 6b 20 3d 20 22 67 72 61 6d 6d  angPack = "gramm
2370: 61 6c 65 63 74 65 2f 22 2b 73 4c 61 6e 67 0a 20  alecte/"+sLang. 
2380: 20 20 20 68 65 6c 70 65 72 73 2e 63 72 65 61 74     helpers.creat
2390: 65 43 6c 65 61 6e 46 6f 6c 64 65 72 28 73 70 4c  eCleanFolder(spL
23a0: 61 6e 67 50 61 63 6b 29 0a 20 20 20 20 66 6f 72  angPack).    for
23b0: 20 73 66 20 69 6e 20 6f 73 2e 6c 69 73 74 64 69   sf in os.listdi
23c0: 72 28 22 67 63 5f 63 6f 72 65 2f 70 79 2f 6c 61  r("gc_core/py/la
23d0: 6e 67 5f 63 6f 72 65 22 29 3a 0a 20 20 20 20 20  ng_core"):.     
23e0: 20 20 20 69 66 20 6e 6f 74 20 6f 73 2e 70 61 74     if not os.pat
23f0: 68 2e 69 73 64 69 72 28 22 67 63 5f 63 6f 72 65  h.isdir("gc_core
2400: 2f 70 79 2f 6c 61 6e 67 5f 63 6f 72 65 2f 22 2b  /py/lang_core/"+
2410: 73 66 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  sf):.           
2420: 20 68 65 6c 70 65 72 73 2e 63 6f 70 79 41 6e 64   helpers.copyAnd
2430: 46 69 6c 65 54 65 6d 70 6c 61 74 65 28 22 67 63  FileTemplate("gc
2440: 5f 63 6f 72 65 2f 70 79 2f 6c 61 6e 67 5f 63 6f  _core/py/lang_co
2450: 72 65 2f 22 2b 73 66 2c 20 73 70 4c 61 6e 67 50  re/"+sf, spLangP
2460: 61 63 6b 2b 22 2f 22 2b 73 66 2c 20 64 56 61 72  ack+"/"+sf, dVar
2470: 73 29 0a 20 20 20 20 70 72 69 6e 74 28 22 2b 20  s).    print("+ 
2480: 4d 6f 64 75 6c 65 73 3a 20 22 2c 20 65 6e 64 3d  Modules: ", end=
2490: 22 22 29 0a 20 20 20 20 66 6f 72 20 73 66 20 69  "").    for sf i
24a0: 6e 20 6f 73 2e 6c 69 73 74 64 69 72 28 73 70 4c  n os.listdir(spL
24b0: 61 6e 67 2b 22 2f 6d 6f 64 75 6c 65 73 22 29 3a  ang+"/modules"):
24c0: 0a 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20  .        if not 
24d0: 73 66 2e 73 74 61 72 74 73 77 69 74 68 28 28 22  sf.startswith(("
24e0: 67 63 65 5f 22 2c 20 22 5f 5f 70 79 63 61 63 68  gce_", "__pycach
24f0: 65 5f 5f 22 29 29 3a 0a 20 20 20 20 20 20 20 20  e__")):.        
2500: 20 20 20 20 68 65 6c 70 65 72 73 2e 63 6f 70 79      helpers.copy
2510: 41 6e 64 46 69 6c 65 54 65 6d 70 6c 61 74 65 28  AndFileTemplate(
2520: 73 70 4c 61 6e 67 2b 22 2f 6d 6f 64 75 6c 65 73  spLang+"/modules
2530: 2f 22 2b 73 66 2c 20 73 70 4c 61 6e 67 50 61 63  /"+sf, spLangPac
2540: 6b 2b 22 2f 22 2b 73 66 2c 20 64 56 61 72 73 29  k+"/"+sf, dVars)
2550: 0a 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69  .            pri
2560: 6e 74 28 73 66 2c 20 65 6e 64 3d 22 2c 20 22 29  nt(sf, end=", ")
2570: 0a 20 20 20 20 70 72 69 6e 74 28 29 0a 0a 20 20  .    print()..  
2580: 20 20 23 20 54 45 53 54 20 46 49 4c 45 53 0a 20    # TEST FILES. 
2590: 20 20 20 77 69 74 68 20 6f 70 65 6e 28 22 67 72     with open("gr
25a0: 61 6d 6d 61 6c 65 63 74 65 2f 22 2b 73 4c 61 6e  ammalecte/"+sLan
25b0: 67 2b 22 2f 67 63 5f 74 65 73 74 2e 74 78 74 22  g+"/gc_test.txt"
25c0: 2c 20 22 77 22 2c 20 65 6e 63 6f 64 69 6e 67 3d  , "w", encoding=
25d0: 22 75 74 66 2d 38 22 2c 20 6e 65 77 6c 69 6e 65  "utf-8", newline
25e0: 3d 22 5c 6e 22 29 20 61 73 20 68 44 73 74 50 79  ="\n") as hDstPy
25f0: 3a 0a 20 20 20 20 20 20 20 20 68 44 73 74 50 79  :.        hDstPy
2600: 2e 77 72 69 74 65 28 22 23 20 54 45 53 54 53 20  .write("# TESTS 
2610: 46 4f 52 20 4c 41 4e 47 20 5b 22 20 2b 20 73 4c  FOR LANG [" + sL
2620: 61 6e 67 20 2b 20 22 5d 5c 6e 5c 6e 22 29 0a 20  ang + "]\n\n"). 
2630: 20 20 20 20 20 20 20 68 44 73 74 50 79 2e 77 72         hDstPy.wr
2640: 69 74 65 28 64 56 61 72 73 5b 27 67 63 74 65 73  ite(dVars['gctes
2650: 74 73 27 5d 29 0a 20 20 20 20 20 20 20 20 68 44  ts']).        hD
2660: 73 74 50 79 2e 77 72 69 74 65 28 22 5c 6e 22 29  stPy.write("\n")
2670: 0a 0a 20 20 20 20 63 72 65 61 74 65 4f 58 54 28  ..    createOXT(
2680: 73 70 4c 61 6e 67 2c 20 64 56 61 72 73 2c 20 78  spLang, dVars, x
2690: 43 6f 6e 66 69 67 2e 5f 73 65 63 74 69 6f 6e 73  Config._sections
26a0: 5b 27 6f 78 74 27 5d 2c 20 73 70 4c 61 6e 67 50  ['oxt'], spLangP
26b0: 61 63 6b 2c 20 62 49 6e 73 74 61 6c 6c 4f 58 54  ack, bInstallOXT
26c0: 29 0a 0a 20 20 20 20 63 72 65 61 74 65 50 61 63  )..    createPac
26d0: 6b 61 67 65 5a 69 70 28 64 56 61 72 73 2c 20 73  kageZip(dVars, s
26e0: 70 4c 61 6e 67 50 61 63 6b 29 0a 0a 20 20 20 20  pLangPack)..    
26f0: 23 23 23 23 20 4a 41 56 41 53 43 52 49 50 54 0a  #### JAVASCRIPT.
2700: 20 20 20 20 69 66 20 62 4a 61 76 61 53 63 72 69      if bJavaScri
2710: 70 74 3a 0a 20 20 20 20 20 20 20 20 70 72 69 6e  pt:.        prin
2720: 74 28 22 4a 41 56 41 53 43 52 49 50 54 3a 22 29  t("JAVASCRIPT:")
2730: 0a 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 22  .        print("
2740: 2b 20 50 6c 75 67 69 6e 73 3a 20 22 2c 20 65 6e  + Plugins: ", en
2750: 64 3d 22 22 29 0a 20 20 20 20 20 20 20 20 73 43  d="").        sC
2760: 6f 64 65 50 6c 75 67 69 6e 73 20 3d 20 22 22 0a  odePlugins = "".
2770: 20 20 20 20 20 20 20 20 66 6f 72 20 73 66 20 69          for sf i
2780: 6e 20 6f 73 2e 6c 69 73 74 64 69 72 28 73 70 4c  n os.listdir(spL
2790: 61 6e 67 2b 22 2f 6d 6f 64 75 6c 65 73 2d 6a 73  ang+"/modules-js
27a0: 22 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  "):.            
27b0: 69 66 20 72 65 2e 6d 61 74 63 68 28 72 22 67 63  if re.match(r"gc
27c0: 65 5f 5c 77 2b 5b 2e 5d 6a 73 24 22 2c 20 73 66  e_\w+[.]js$", sf
27d0: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
27e0: 20 20 20 73 43 6f 64 65 50 6c 75 67 69 6e 73 20     sCodePlugins 
27f0: 2b 3d 20 22 5c 6e 5c 6e 22 20 2b 20 6f 70 65 6e  += "\n\n" + open
2800: 28 73 70 4c 61 6e 67 2b 27 2f 6d 6f 64 75 6c 65  (spLang+'/module
2810: 73 2d 6a 73 2f 27 2b 73 66 2c 20 22 72 22 2c 20  s-js/'+sf, "r", 
2820: 65 6e 63 6f 64 69 6e 67 3d 22 75 74 66 2d 38 22  encoding="utf-8"
2830: 29 2e 72 65 61 64 28 29 0a 20 20 20 20 20 20 20  ).read().       
2840: 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 73           print(s
2850: 66 2c 20 65 6e 64 3d 22 2c 20 22 29 0a 20 20 20  f, end=", ").   
2860: 20 20 20 20 20 70 72 69 6e 74 28 29 0a 20 20 20       print().   
2870: 20 20 20 20 20 64 56 61 72 73 5b 22 70 6c 75 67       dVars["plug
2880: 69 6e 73 4a 53 22 5d 20 3d 20 73 43 6f 64 65 50  insJS"] = sCodeP
2890: 6c 75 67 69 6e 73 0a 0a 20 20 20 20 20 20 20 20  lugins..        
28a0: 23 20 6f 70 74 69 6f 6e 73 20 64 61 74 61 20 73  # options data s
28b0: 74 72 75 63 74 0a 20 20 20 20 20 20 20 20 64 56  truct.        dV
28c0: 61 72 73 5b 22 64 4f 70 74 4a 61 76 61 53 63 72  ars["dOptJavaScr
28d0: 69 70 74 22 5d 20 3d 20 6a 73 6f 6e 2e 64 75 6d  ipt"] = json.dum
28e0: 70 73 28 6c 69 73 74 28 64 56 61 72 73 5b 22 64  ps(list(dVars["d
28f0: 4f 70 74 4a 61 76 61 53 63 72 69 70 74 22 5d 2e  OptJavaScript"].
2900: 69 74 65 6d 73 28 29 29 29 0a 20 20 20 20 20 20  items())).      
2910: 20 20 64 56 61 72 73 5b 22 64 4f 70 74 46 69 72    dVars["dOptFir
2920: 65 66 6f 78 22 5d 20 3d 20 6a 73 6f 6e 2e 64 75  efox"] = json.du
2930: 6d 70 73 28 6c 69 73 74 28 64 56 61 72 73 5b 22  mps(list(dVars["
2940: 64 4f 70 74 46 69 72 65 66 6f 78 22 5d 2e 69 74  dOptFirefox"].it
2950: 65 6d 73 28 29 29 29 0a 20 20 20 20 20 20 20 20  ems())).        
2960: 64 56 61 72 73 5b 22 64 4f 70 74 54 68 75 6e 64  dVars["dOptThund
2970: 65 72 62 69 72 64 22 5d 20 3d 20 6a 73 6f 6e 2e  erbird"] = json.
2980: 64 75 6d 70 73 28 6c 69 73 74 28 64 56 61 72 73  dumps(list(dVars
2990: 5b 22 64 4f 70 74 54 68 75 6e 64 65 72 62 69 72  ["dOptThunderbir
29a0: 64 22 5d 2e 69 74 65 6d 73 28 29 29 29 0a 0a 20  d"].items())).. 
29b0: 20 20 20 20 20 20 20 23 20 63 72 65 61 74 65 20         # create 
29c0: 66 6f 6c 64 65 72 0a 20 20 20 20 20 20 20 20 73  folder.        s
29d0: 70 4c 61 6e 67 50 61 63 6b 20 3d 20 22 67 72 61  pLangPack = "gra
29e0: 6d 6d 61 6c 65 63 74 65 2d 6a 73 2f 22 2b 73 4c  mmalecte-js/"+sL
29f0: 61 6e 67 0a 20 20 20 20 20 20 20 20 68 65 6c 70  ang.        help
2a00: 65 72 73 2e 63 72 65 61 74 65 43 6c 65 61 6e 46  ers.createCleanF
2a10: 6f 6c 64 65 72 28 73 70 4c 61 6e 67 50 61 63 6b  older(spLangPack
2a20: 29 0a 0a 20 20 20 20 20 20 20 20 23 20 63 72 65  )..        # cre
2a30: 61 74 65 20 66 69 6c 65 73 0a 20 20 20 20 20 20  ate files.      
2a40: 20 20 66 6f 72 20 73 66 20 69 6e 20 6f 73 2e 6c    for sf in os.l
2a50: 69 73 74 64 69 72 28 22 6a 73 5f 65 78 74 65 6e  istdir("js_exten
2a60: 73 69 6f 6e 22 29 3a 0a 20 20 20 20 20 20 20 20  sion"):.        
2a70: 20 20 20 20 64 56 61 72 73 5b 73 66 5b 3a 2d 33      dVars[sf[:-3
2a80: 5d 5d 20 3d 20 6f 70 65 6e 28 22 6a 73 5f 65 78  ]] = open("js_ex
2a90: 74 65 6e 73 69 6f 6e 2f 22 2b 73 66 2c 20 22 72  tension/"+sf, "r
2aa0: 22 2c 20 65 6e 63 6f 64 69 6e 67 3d 22 75 74 66  ", encoding="utf
2ab0: 2d 38 22 29 2e 72 65 61 64 28 29 0a 20 20 20 20  -8").read().    
2ac0: 20 20 20 20 66 6f 72 20 73 66 20 69 6e 20 6f 73      for sf in os
2ad0: 2e 6c 69 73 74 64 69 72 28 22 67 63 5f 63 6f 72  .listdir("gc_cor
2ae0: 65 2f 6a 73 22 29 3a 0a 20 20 20 20 20 20 20 20  e/js"):.        
2af0: 20 20 20 20 69 66 20 6e 6f 74 20 6f 73 2e 70 61      if not os.pa
2b00: 74 68 2e 69 73 64 69 72 28 22 67 63 5f 63 6f 72  th.isdir("gc_cor
2b10: 65 2f 6a 73 2f 22 2b 73 66 29 20 61 6e 64 20 6e  e/js/"+sf) and n
2b20: 6f 74 20 73 66 2e 73 74 61 72 74 73 77 69 74 68  ot sf.startswith
2b30: 28 22 6a 73 65 78 5f 22 29 3a 0a 20 20 20 20 20  ("jsex_"):.     
2b40: 20 20 20 20 20 20 20 20 20 20 20 68 65 6c 70 65             helpe
2b50: 72 73 2e 63 6f 70 79 41 6e 64 46 69 6c 65 54 65  rs.copyAndFileTe
2b60: 6d 70 6c 61 74 65 28 22 67 63 5f 63 6f 72 65 2f  mplate("gc_core/
2b70: 6a 73 2f 22 2b 73 66 2c 20 22 67 72 61 6d 6d 61  js/"+sf, "gramma
2b80: 6c 65 63 74 65 2d 6a 73 2f 22 2b 73 66 2c 20 64  lecte-js/"+sf, d
2b90: 56 61 72 73 29 0a 20 20 20 20 20 20 20 20 6f 70  Vars).        op
2ba0: 65 6e 28 22 67 72 61 6d 6d 61 6c 65 63 74 65 2d  en("grammalecte-
2bb0: 6a 73 2f 57 41 52 4e 49 4e 47 2e 74 78 74 22 2c  js/WARNING.txt",
2bc0: 20 22 77 22 2c 20 65 6e 63 6f 64 69 6e 67 3d 22   "w", encoding="
2bd0: 75 74 66 2d 38 22 2c 20 6e 65 77 6c 69 6e 65 3d  utf-8", newline=
2be0: 22 5c 6e 22 29 2e 77 72 69 74 65 28 73 57 61 72  "\n").write(sWar
2bf0: 6e 69 6e 67 4d 65 73 73 61 67 65 29 0a 20 20 20  ningMessage).   
2c00: 20 20 20 20 20 66 6f 72 20 73 66 20 69 6e 20 6f       for sf in o
2c10: 73 2e 6c 69 73 74 64 69 72 28 22 67 63 5f 63 6f  s.listdir("gc_co
2c20: 72 65 2f 6a 73 2f 6c 61 6e 67 5f 63 6f 72 65 22  re/js/lang_core"
2c30: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 69  ):.            i
2c40: 66 20 6e 6f 74 20 6f 73 2e 70 61 74 68 2e 69 73  f not os.path.is
2c50: 64 69 72 28 22 67 63 5f 63 6f 72 65 2f 6a 73 2f  dir("gc_core/js/
2c60: 6c 61 6e 67 5f 63 6f 72 65 2f 22 2b 73 66 29 20  lang_core/"+sf) 
2c70: 61 6e 64 20 73 66 2e 73 74 61 72 74 73 77 69 74  and sf.startswit
2c80: 68 28 22 67 63 5f 22 29 3a 0a 20 20 20 20 20 20  h("gc_"):.      
2c90: 20 20 20 20 20 20 20 20 20 20 68 65 6c 70 65 72            helper
2ca0: 73 2e 63 6f 70 79 41 6e 64 46 69 6c 65 54 65 6d  s.copyAndFileTem
2cb0: 70 6c 61 74 65 28 22 67 63 5f 63 6f 72 65 2f 6a  plate("gc_core/j
2cc0: 73 2f 6c 61 6e 67 5f 63 6f 72 65 2f 22 2b 73 66  s/lang_core/"+sf
2cd0: 2c 20 73 70 4c 61 6e 67 50 61 63 6b 2b 22 2f 22  , spLangPack+"/"
2ce0: 2b 73 66 2c 20 64 56 61 72 73 29 0a 20 20 20 20  +sf, dVars).    
2cf0: 20 20 20 20 70 72 69 6e 74 28 22 2b 20 4d 6f 64      print("+ Mod
2d00: 75 6c 65 73 3a 20 22 2c 20 65 6e 64 3d 22 22 29  ules: ", end="")
2d10: 0a 20 20 20 20 20 20 20 20 66 6f 72 20 73 66 20  .        for sf 
2d20: 69 6e 20 6f 73 2e 6c 69 73 74 64 69 72 28 73 70  in os.listdir(sp
2d30: 4c 61 6e 67 2b 22 2f 6d 6f 64 75 6c 65 73 2d 6a  Lang+"/modules-j
2d40: 73 22 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  s"):.           
2d50: 20 69 66 20 6e 6f 74 20 73 66 2e 73 74 61 72 74   if not sf.start
2d60: 73 77 69 74 68 28 22 67 63 65 5f 22 29 3a 0a 20  swith("gce_"):. 
2d70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 68                 h
2d80: 65 6c 70 65 72 73 2e 63 6f 70 79 41 6e 64 46 69  elpers.copyAndFi
2d90: 6c 65 54 65 6d 70 6c 61 74 65 28 73 70 4c 61 6e  leTemplate(spLan
2da0: 67 2b 22 2f 6d 6f 64 75 6c 65 73 2d 6a 73 2f 22  g+"/modules-js/"
2db0: 2b 73 66 2c 20 73 70 4c 61 6e 67 50 61 63 6b 2b  +sf, spLangPack+
2dc0: 22 2f 22 2b 73 66 2c 20 64 56 61 72 73 29 0a 20  "/"+sf, dVars). 
2dd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 70                 p
2de0: 72 69 6e 74 28 73 66 2c 20 65 6e 64 3d 22 2c 20  rint(sf, end=", 
2df0: 22 29 0a 20 20 20 20 20 20 20 20 70 72 69 6e 74  ").        print
2e00: 28 29 0a 0a 20 20 20 20 20 20 20 20 74 72 79 3a  ()..        try:
2e10: 0a 20 20 20 20 20 20 20 20 20 20 20 20 62 75 69  .            bui
2e20: 6c 64 6a 73 20 3d 20 69 6d 70 6f 72 74 6c 69 62  ldjs = importlib
2e30: 2e 69 6d 70 6f 72 74 5f 6d 6f 64 75 6c 65 28 22  .import_module("
2e40: 67 63 5f 6c 61 6e 67 2e 22 2b 73 4c 61 6e 67 2b  gc_lang."+sLang+
2e50: 22 2e 62 75 69 6c 64 22 29 0a 20 20 20 20 20 20  ".build").      
2e60: 20 20 65 78 63 65 70 74 20 49 6d 70 6f 72 74 45    except ImportE
2e70: 72 72 6f 72 3a 0a 20 20 20 20 20 20 20 20 20 20  rror:.          
2e80: 20 20 70 72 69 6e 74 28 22 23 20 4e 6f 20 63 6f    print("# No co
2e90: 6d 70 6c 65 6d 65 6e 74 61 72 79 20 62 75 69 6c  mplementary buil
2ea0: 64 65 72 20 3c 62 75 69 6c 64 2e 70 79 3e 20 69  der <build.py> i
2eb0: 6e 20 66 6f 6c 64 65 72 20 67 63 5f 6c 61 6e 67  n folder gc_lang
2ec0: 2f 22 2b 73 4c 61 6e 67 29 0a 20 20 20 20 20 20  /"+sLang).      
2ed0: 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20    else:.        
2ee0: 20 20 20 20 62 75 69 6c 64 6a 73 2e 62 75 69 6c      buildjs.buil
2ef0: 64 28 73 4c 61 6e 67 2c 20 64 56 61 72 73 29 0a  d(sLang, dVars).
2f00: 0a 20 20 20 20 72 65 74 75 72 6e 20 64 56 61 72  .    return dVar
2f10: 73 5b 27 76 65 72 73 69 6f 6e 27 5d 0a 0a 0a 64  s['version']...d
2f20: 65 66 20 63 6f 70 79 47 72 61 70 68 73 70 65 6c  ef copyGraphspel
2f30: 6c 43 6f 72 65 20 28 62 4a 61 76 61 53 63 72 69  lCore (bJavaScri
2f40: 70 74 3d 46 61 6c 73 65 29 3a 0a 20 20 20 20 22  pt=False):.    "
2f50: 63 6f 70 79 20 47 72 61 70 68 73 70 65 6c 6c 20  copy Graphspell 
2f60: 70 61 63 6b 61 67 65 20 69 6e 20 47 72 61 6d 6d  package in Gramm
2f70: 61 6c 65 63 74 65 20 70 61 63 6b 61 67 65 22 0a  alecte package".
2f80: 20 20 20 20 68 65 6c 70 65 72 73 2e 63 72 65 61      helpers.crea
2f90: 74 65 43 6c 65 61 6e 46 6f 6c 64 65 72 28 22 67  teCleanFolder("g
2fa0: 72 61 6d 6d 61 6c 65 63 74 65 2f 67 72 61 70 68  rammalecte/graph
2fb0: 73 70 65 6c 6c 22 29 0a 20 20 20 20 64 69 72 5f  spell").    dir_
2fc0: 75 74 69 6c 2e 6d 6b 70 61 74 68 28 22 67 72 61  util.mkpath("gra
2fd0: 6d 6d 61 6c 65 63 74 65 2f 67 72 61 70 68 73 70  mmalecte/graphsp
2fe0: 65 6c 6c 2f 5f 64 69 63 74 69 6f 6e 61 72 69 65  ell/_dictionarie
2ff0: 73 22 29 0a 20 20 20 20 66 6f 72 20 73 66 20 69  s").    for sf i
3000: 6e 20 6f 73 2e 6c 69 73 74 64 69 72 28 22 67 72  n os.listdir("gr
3010: 61 70 68 73 70 65 6c 6c 22 29 3a 0a 20 20 20 20  aphspell"):.    
3020: 20 20 20 20 69 66 20 6e 6f 74 20 6f 73 2e 70 61      if not os.pa
3030: 74 68 2e 69 73 64 69 72 28 22 67 72 61 70 68 73  th.isdir("graphs
3040: 70 65 6c 6c 2f 22 2b 73 66 29 3a 0a 20 20 20 20  pell/"+sf):.    
3050: 20 20 20 20 20 20 20 20 66 69 6c 65 5f 75 74 69          file_uti
3060: 6c 2e 63 6f 70 79 5f 66 69 6c 65 28 22 67 72 61  l.copy_file("gra
3070: 70 68 73 70 65 6c 6c 2f 22 2b 73 66 2c 20 22 67  phspell/"+sf, "g
3080: 72 61 6d 6d 61 6c 65 63 74 65 2f 67 72 61 70 68  rammalecte/graph
3090: 73 70 65 6c 6c 22 29 0a 20 20 20 20 69 66 20 62  spell").    if b
30a0: 4a 61 76 61 53 63 72 69 70 74 3a 0a 20 20 20 20  JavaScript:.    
30b0: 20 20 20 20 68 65 6c 70 65 72 73 2e 63 72 65 61      helpers.crea
30c0: 74 65 43 6c 65 61 6e 46 6f 6c 64 65 72 28 22 67  teCleanFolder("g
30d0: 72 61 6d 6d 61 6c 65 63 74 65 2d 6a 73 2f 67 72  rammalecte-js/gr
30e0: 61 70 68 73 70 65 6c 6c 22 29 0a 20 20 20 20 20  aphspell").     
30f0: 20 20 20 64 69 72 5f 75 74 69 6c 2e 6d 6b 70 61     dir_util.mkpa
3100: 74 68 28 22 67 72 61 6d 6d 61 6c 65 63 74 65 2d  th("grammalecte-
3110: 6a 73 2f 67 72 61 70 68 73 70 65 6c 6c 2f 5f 64  js/graphspell/_d
3120: 69 63 74 69 6f 6e 61 72 69 65 73 22 29 0a 20 20  ictionaries").  
3130: 20 20 20 20 20 20 64 56 61 72 73 20 3d 20 7b 7d        dVars = {}
3140: 0a 20 20 20 20 20 20 20 20 66 6f 72 20 73 66 20  .        for sf 
3150: 69 6e 20 6f 73 2e 6c 69 73 74 64 69 72 28 22 6a  in os.listdir("j
3160: 73 5f 65 78 74 65 6e 73 69 6f 6e 22 29 3a 0a 20  s_extension"):. 
3170: 20 20 20 20 20 20 20 20 20 20 20 64 56 61 72 73             dVars
3180: 5b 73 66 5b 3a 2d 33 5d 5d 20 3d 20 6f 70 65 6e  [sf[:-3]] = open
3190: 28 22 6a 73 5f 65 78 74 65 6e 73 69 6f 6e 2f 22  ("js_extension/"
31a0: 2b 73 66 2c 20 22 72 22 2c 20 65 6e 63 6f 64 69  +sf, "r", encodi
31b0: 6e 67 3d 22 75 74 66 2d 38 22 29 2e 72 65 61 64  ng="utf-8").read
31c0: 28 29 0a 20 20 20 20 20 20 20 20 66 6f 72 20 73  ().        for s
31d0: 66 20 69 6e 20 6f 73 2e 6c 69 73 74 64 69 72 28  f in os.listdir(
31e0: 22 67 72 61 70 68 73 70 65 6c 6c 2d 6a 73 22 29  "graphspell-js")
31f0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  :.            if
3200: 20 6e 6f 74 20 6f 73 2e 70 61 74 68 2e 69 73 64   not os.path.isd
3210: 69 72 28 22 67 72 61 70 68 73 70 65 6c 6c 2d 6a  ir("graphspell-j
3220: 73 2f 22 2b 73 66 29 3a 0a 20 20 20 20 20 20 20  s/"+sf):.       
3230: 20 20 20 20 20 20 20 20 20 66 69 6c 65 5f 75 74           file_ut
3240: 69 6c 2e 63 6f 70 79 5f 66 69 6c 65 28 22 67 72  il.copy_file("gr
3250: 61 70 68 73 70 65 6c 6c 2d 6a 73 2f 22 2b 73 66  aphspell-js/"+sf
3260: 2c 20 22 67 72 61 6d 6d 61 6c 65 63 74 65 2d 6a  , "grammalecte-j
3270: 73 2f 67 72 61 70 68 73 70 65 6c 6c 22 29 0a 20  s/graphspell"). 
3280: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 68                 h
3290: 65 6c 70 65 72 73 2e 63 6f 70 79 41 6e 64 46 69  elpers.copyAndFi
32a0: 6c 65 54 65 6d 70 6c 61 74 65 28 22 67 72 61 70  leTemplate("grap
32b0: 68 73 70 65 6c 6c 2d 6a 73 2f 22 2b 73 66 2c 20  hspell-js/"+sf, 
32c0: 22 67 72 61 6d 6d 61 6c 65 63 74 65 2d 6a 73 2f  "grammalecte-js/
32d0: 67 72 61 70 68 73 70 65 6c 6c 2f 22 2b 73 66 2c  graphspell/"+sf,
32e0: 20 64 56 61 72 73 29 0a 0a 0a 64 65 66 20 63 6f   dVars)...def co
32f0: 70 79 47 72 61 70 68 73 70 65 6c 6c 44 69 63 74  pyGraphspellDict
3300: 69 6f 6e 61 72 69 65 73 20 28 64 56 61 72 73 2c  ionaries (dVars,
3310: 20 62 4a 61 76 61 53 63 72 69 70 74 3d 46 61 6c   bJavaScript=Fal
3320: 73 65 2c 20 62 43 6f 6d 6d 75 6e 69 74 79 44 69  se, bCommunityDi
3330: 63 74 3d 46 61 6c 73 65 2c 20 62 50 65 72 73 6f  ct=False, bPerso
3340: 6e 61 6c 44 69 63 74 3d 46 61 6c 73 65 29 3a 0a  nalDict=False):.
3350: 20 20 20 20 22 63 6f 70 79 20 72 65 71 75 65 73      "copy reques
3360: 74 65 64 20 47 72 61 70 68 73 70 65 6c 6c 20 64  ted Graphspell d
3370: 69 63 74 69 6f 6e 61 72 69 65 73 20 69 6e 20 47  ictionaries in G
3380: 72 61 6d 6d 61 6c 65 63 74 65 20 70 61 63 6b 61  rammalecte packa
3390: 67 65 22 0a 20 20 20 20 64 56 61 72 73 5b 22 64  ge".    dVars["d
33a0: 69 63 5f 6d 61 69 6e 5f 66 69 6c 65 6e 61 6d 65  ic_main_filename
33b0: 5f 70 79 22 5d 20 3d 20 22 22 0a 20 20 20 20 64  _py"] = "".    d
33c0: 56 61 72 73 5b 22 64 69 63 5f 6d 61 69 6e 5f 66  Vars["dic_main_f
33d0: 69 6c 65 6e 61 6d 65 5f 6a 73 22 5d 20 3d 20 22  ilename_js"] = "
33e0: 22 0a 20 20 20 20 64 56 61 72 73 5b 22 64 69 63  ".    dVars["dic
33f0: 5f 63 6f 6d 6d 75 6e 69 74 79 5f 66 69 6c 65 6e  _community_filen
3400: 61 6d 65 5f 70 79 22 5d 20 3d 20 22 22 0a 20 20  ame_py"] = "".  
3410: 20 20 64 56 61 72 73 5b 22 64 69 63 5f 63 6f 6d    dVars["dic_com
3420: 6d 75 6e 69 74 79 5f 66 69 6c 65 6e 61 6d 65 5f  munity_filename_
3430: 6a 73 22 5d 20 3d 20 22 22 0a 20 20 20 20 64 56  js"] = "".    dV
3440: 61 72 73 5b 22 64 69 63 5f 70 65 72 73 6f 6e 61  ars["dic_persona
3450: 6c 5f 66 69 6c 65 6e 61 6d 65 5f 70 79 22 5d 20  l_filename_py"] 
3460: 3d 20 22 22 0a 20 20 20 20 64 56 61 72 73 5b 22  = "".    dVars["
3470: 64 69 63 5f 70 65 72 73 6f 6e 61 6c 5f 66 69 6c  dic_personal_fil
3480: 65 6e 61 6d 65 5f 6a 73 22 5d 20 3d 20 22 22 0a  ename_js"] = "".
3490: 20 20 20 20 6c 44 69 63 74 20 3d 20 5b 20 28 22      lDict = [ ("
34a0: 6d 61 69 6e 22 2c 20 73 29 20 20 66 6f 72 20 73  main", s)  for s
34b0: 20 69 6e 20 64 56 61 72 73 5b 27 64 69 63 5f 66   in dVars['dic_f
34c0: 69 6c 65 6e 61 6d 65 73 27 5d 2e 73 70 6c 69 74  ilenames'].split
34d0: 28 22 2c 22 29 20 5d 0a 20 20 20 20 69 66 20 62  (",") ].    if b
34e0: 43 6f 6d 6d 75 6e 69 74 79 44 69 63 74 3a 0a 20  CommunityDict:. 
34f0: 20 20 20 20 20 20 20 6c 44 69 63 74 2e 61 70 70         lDict.app
3500: 65 6e 64 28 28 22 63 6f 6d 6d 75 6e 69 74 79 22  end(("community"
3510: 2c 20 64 56 61 72 73 5b 27 64 69 63 5f 63 6f 6d  , dVars['dic_com
3520: 6d 75 6e 69 74 79 5f 66 69 6c 65 6e 61 6d 65 27  munity_filename'
3530: 5d 29 29 0a 20 20 20 20 69 66 20 62 50 65 72 73  ])).    if bPers
3540: 6f 6e 61 6c 44 69 63 74 3a 0a 20 20 20 20 20 20  onalDict:.      
3550: 20 20 6c 44 69 63 74 2e 61 70 70 65 6e 64 28 28    lDict.append((
3560: 22 70 65 72 73 6f 6e 61 6c 22 2c 20 64 56 61 72  "personal", dVar
3570: 73 5b 27 64 69 63 5f 70 65 72 73 6f 6e 61 6c 5f  s['dic_personal_
3580: 66 69 6c 65 6e 61 6d 65 27 5d 29 29 0a 20 20 20  filename'])).   
3590: 20 66 6f 72 20 73 54 79 70 65 2c 20 73 46 69 6c   for sType, sFil
35a0: 65 4e 61 6d 65 20 69 6e 20 6c 44 69 63 74 3a 0a  eName in lDict:.
35b0: 20 20 20 20 20 20 20 20 73 70 66 50 79 44 69 63          spfPyDic
35c0: 20 3d 20 66 22 67 72 61 70 68 73 70 65 6c 6c 2f   = f"graphspell/
35d0: 5f 64 69 63 74 69 6f 6e 61 72 69 65 73 2f 7b 73  _dictionaries/{s
35e0: 46 69 6c 65 4e 61 6d 65 7d 2e 62 64 69 63 22 0a  FileName}.bdic".
35f0: 20 20 20 20 20 20 20 20 73 70 66 4a 53 44 69 63          spfJSDic
3600: 20 3d 20 66 22 67 72 61 70 68 73 70 65 6c 6c 2d   = f"graphspell-
3610: 6a 73 2f 5f 64 69 63 74 69 6f 6e 61 72 69 65 73  js/_dictionaries
3620: 2f 7b 73 46 69 6c 65 4e 61 6d 65 7d 2e 6a 73 6f  /{sFileName}.jso
3630: 6e 22 0a 20 20 20 20 20 20 20 20 69 66 20 6e 6f  n".        if no
3640: 74 20 6f 73 2e 70 61 74 68 2e 69 73 66 69 6c 65  t os.path.isfile
3650: 28 73 70 66 50 79 44 69 63 29 20 6f 72 20 28 62  (spfPyDic) or (b
3660: 4a 61 76 61 53 63 72 69 70 74 20 61 6e 64 20 6e  JavaScript and n
3670: 6f 74 20 6f 73 2e 70 61 74 68 2e 69 73 66 69 6c  ot os.path.isfil
3680: 65 28 73 70 66 4a 53 44 69 63 29 29 3a 0a 20 20  e(spfJSDic)):.  
3690: 20 20 20 20 20 20 20 20 20 20 62 75 69 6c 64 44            buildD
36a0: 69 63 74 69 6f 6e 61 72 79 28 64 56 61 72 73 2c  ictionary(dVars,
36b0: 20 73 54 79 70 65 2c 20 62 4a 61 76 61 53 63 72   sType, bJavaScr
36c0: 69 70 74 29 0a 20 20 20 20 20 20 20 20 70 72 69  ipt).        pri
36d0: 6e 74 28 73 70 66 50 79 44 69 63 29 0a 20 20 20  nt(spfPyDic).   
36e0: 20 20 20 20 20 66 69 6c 65 5f 75 74 69 6c 2e 63       file_util.c
36f0: 6f 70 79 5f 66 69 6c 65 28 73 70 66 50 79 44 69  opy_file(spfPyDi
3700: 63 2c 20 22 67 72 61 6d 6d 61 6c 65 63 74 65 2f  c, "grammalecte/
3710: 67 72 61 70 68 73 70 65 6c 6c 2f 5f 64 69 63 74  graphspell/_dict
3720: 69 6f 6e 61 72 69 65 73 22 29 0a 20 20 20 20 20  ionaries").     
3730: 20 20 20 64 56 61 72 73 5b 27 64 69 63 5f 27 2b     dVars['dic_'+
3740: 73 54 79 70 65 2b 27 5f 66 69 6c 65 6e 61 6d 65  sType+'_filename
3750: 5f 70 79 27 5d 20 3d 20 73 46 69 6c 65 4e 61 6d  _py'] = sFileNam
3760: 65 20 2b 20 27 2e 62 64 69 63 27 0a 20 20 20 20  e + '.bdic'.    
3770: 20 20 20 20 69 66 20 62 4a 61 76 61 53 63 72 69      if bJavaScri
3780: 70 74 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  pt:.            
3790: 70 72 69 6e 74 28 73 70 66 4a 53 44 69 63 29 0a  print(spfJSDic).
37a0: 20 20 20 20 20 20 20 20 20 20 20 20 66 69 6c 65              file
37b0: 5f 75 74 69 6c 2e 63 6f 70 79 5f 66 69 6c 65 28  _util.copy_file(
37c0: 73 70 66 4a 53 44 69 63 2c 20 22 67 72 61 6d 6d  spfJSDic, "gramm
37d0: 61 6c 65 63 74 65 2d 6a 73 2f 67 72 61 70 68 73  alecte-js/graphs
37e0: 70 65 6c 6c 2f 5f 64 69 63 74 69 6f 6e 61 72 69  pell/_dictionari
37f0: 65 73 22 29 0a 20 20 20 20 20 20 20 20 20 20 20  es").           
3800: 20 64 56 61 72 73 5b 27 64 69 63 5f 27 2b 73 54   dVars['dic_'+sT
3810: 79 70 65 2b 27 5f 66 69 6c 65 6e 61 6d 65 5f 6a  ype+'_filename_j
3820: 73 27 5d 20 3d 20 73 46 69 6c 65 4e 61 6d 65 20  s'] = sFileName 
3830: 2b 20 27 2e 6a 73 6f 6e 27 0a 20 20 20 20 64 56  + '.json'.    dV
3840: 61 72 73 5b 27 64 69 63 5f 6d 61 69 6e 5f 66 69  ars['dic_main_fi
3850: 6c 65 6e 61 6d 65 5f 70 79 27 5d 20 3d 20 64 56  lename_py'] = dV
3860: 61 72 73 5b 27 64 69 63 5f 64 65 66 61 75 6c 74  ars['dic_default
3870: 5f 66 69 6c 65 6e 61 6d 65 5f 70 79 27 5d 20 2b  _filename_py'] +
3880: 20 22 2e 62 64 69 63 22 0a 20 20 20 20 64 56 61   ".bdic".    dVa
3890: 72 73 5b 27 64 69 63 5f 6d 61 69 6e 5f 66 69 6c  rs['dic_main_fil
38a0: 65 6e 61 6d 65 5f 6a 73 27 5d 20 3d 20 64 56 61  ename_js'] = dVa
38b0: 72 73 5b 27 64 69 63 5f 64 65 66 61 75 6c 74 5f  rs['dic_default_
38c0: 66 69 6c 65 6e 61 6d 65 5f 6a 73 27 5d 20 2b 20  filename_js'] + 
38d0: 22 2e 6a 73 6f 6e 22 0a 0a 0a 64 65 66 20 62 75  ".json"...def bu
38e0: 69 6c 64 44 69 63 74 69 6f 6e 61 72 79 20 28 64  ildDictionary (d
38f0: 56 61 72 73 2c 20 73 54 79 70 65 2c 20 62 4a 61  Vars, sType, bJa
3900: 76 61 53 63 72 69 70 74 3d 46 61 6c 73 65 29 3a  vaScript=False):
3910: 0a 20 20 20 20 22 62 75 69 6c 64 20 62 69 6e 61  .    "build bina
3920: 72 79 20 64 69 63 74 69 6f 6e 61 72 79 20 66 6f  ry dictionary fo
3930: 72 20 47 72 61 70 68 73 70 65 6c 6c 20 66 72 6f  r Graphspell fro
3940: 6d 20 6c 65 78 69 63 6f 6e 73 22 0a 20 20 20 20  m lexicons".    
3950: 69 66 20 73 54 79 70 65 20 3d 3d 20 22 6d 61 69  if sType == "mai
3960: 6e 22 3a 0a 20 20 20 20 20 20 20 20 73 70 66 4c  n":.        spfL
3970: 65 78 53 72 63 20 3d 20 64 56 61 72 73 5b 27 6c  exSrc = dVars['l
3980: 65 78 69 63 6f 6e 5f 73 72 63 27 5d 0a 20 20 20  exicon_src'].   
3990: 20 20 20 20 20 6c 53 66 44 69 63 74 44 73 74 20       lSfDictDst 
39a0: 3d 20 64 56 61 72 73 5b 27 64 69 63 5f 66 69 6c  = dVars['dic_fil
39b0: 65 6e 61 6d 65 73 27 5d 2e 73 70 6c 69 74 28 22  enames'].split("
39c0: 2c 22 29 0a 20 20 20 20 20 20 20 20 6c 44 69 63  ,").        lDic
39d0: 4e 61 6d 65 20 3d 20 64 56 61 72 73 5b 27 64 69  Name = dVars['di
39e0: 63 5f 6e 61 6d 65 27 5d 2e 73 70 6c 69 74 28 22  c_name'].split("
39f0: 2c 22 29 0a 20 20 20 20 20 20 20 20 6c 44 65 73  ,").        lDes
3a00: 63 72 69 70 74 69 6f 6e 20 3d 20 64 56 61 72 73  cription = dVars
3a10: 5b 27 64 69 63 5f 64 65 73 63 72 69 70 74 69 6f  ['dic_descriptio
3a20: 6e 27 5d 2e 73 70 6c 69 74 28 22 2c 22 29 0a 20  n'].split(","). 
3a30: 20 20 20 20 20 20 20 6c 46 69 6c 74 65 72 20 3d         lFilter =
3a40: 20 64 56 61 72 73 5b 27 64 69 63 5f 66 69 6c 74   dVars['dic_filt
3a50: 65 72 27 5d 2e 73 70 6c 69 74 28 22 2c 22 29 0a  er'].split(",").
3a60: 20 20 20 20 20 20 20 20 66 6f 72 20 73 66 44 69          for sfDi
3a70: 63 74 44 73 74 2c 20 73 44 69 63 4e 61 6d 65 2c  ctDst, sDicName,
3a80: 20 73 44 65 73 63 72 69 70 74 69 6f 6e 2c 20 73   sDescription, s
3a90: 46 69 6c 74 65 72 20 69 6e 20 7a 69 70 28 6c 53  Filter in zip(lS
3aa0: 66 44 69 63 74 44 73 74 2c 20 6c 44 69 63 4e 61  fDictDst, lDicNa
3ab0: 6d 65 2c 20 6c 44 65 73 63 72 69 70 74 69 6f 6e  me, lDescription
3ac0: 2c 20 6c 46 69 6c 74 65 72 29 3a 0a 20 20 20 20  , lFilter):.    
3ad0: 20 20 20 20 20 20 20 20 6c 65 78 5f 62 75 69 6c          lex_buil
3ae0: 64 2e 62 75 69 6c 64 28 73 70 66 4c 65 78 53 72  d.build(spfLexSr
3af0: 63 2c 20 64 56 61 72 73 5b 27 6c 61 6e 67 27 5d  c, dVars['lang']
3b00: 2c 20 64 56 61 72 73 5b 27 6c 61 6e 67 5f 6e 61  , dVars['lang_na
3b10: 6d 65 27 5d 2c 20 73 66 44 69 63 74 44 73 74 2c  me'], sfDictDst,
3b20: 20 62 4a 61 76 61 53 63 72 69 70 74 2c 20 73 44   bJavaScript, sD
3b30: 69 63 4e 61 6d 65 2c 20 73 44 65 73 63 72 69 70  icName, sDescrip
3b40: 74 69 6f 6e 2c 20 73 46 69 6c 74 65 72 2c 20 64  tion, sFilter, d
3b50: 56 61 72 73 5b 27 73 74 65 6d 6d 69 6e 67 5f 6d  Vars['stemming_m
3b60: 65 74 68 6f 64 27 5d 2c 20 69 6e 74 28 64 56 61  ethod'], int(dVa
3b70: 72 73 5b 27 66 73 61 5f 6d 65 74 68 6f 64 27 5d  rs['fsa_method']
3b80: 29 29 0a 20 20 20 20 65 6c 73 65 3a 0a 20 20 20  )).    else:.   
3b90: 20 20 20 20 20 69 66 20 73 54 79 70 65 20 3d 3d       if sType ==
3ba0: 20 22 63 6f 6d 6d 75 6e 69 74 79 22 3a 0a 20 20   "community":.  
3bb0: 20 20 20 20 20 20 20 20 20 20 73 70 66 4c 65 78            spfLex
3bc0: 53 72 63 20 3d 20 64 56 61 72 73 5b 27 6c 65 78  Src = dVars['lex
3bd0: 69 63 6f 6e 5f 63 6f 6d 6d 75 6e 69 74 79 5f 73  icon_community_s
3be0: 72 63 27 5d 0a 20 20 20 20 20 20 20 20 20 20 20  rc'].           
3bf0: 20 73 66 44 69 63 74 44 73 74 20 3d 20 64 56 61   sfDictDst = dVa
3c00: 72 73 5b 27 64 69 63 5f 63 6f 6d 6d 75 6e 69 74  rs['dic_communit
3c10: 79 5f 66 69 6c 65 6e 61 6d 65 27 5d 0a 20 20 20  y_filename'].   
3c20: 20 20 20 20 20 20 20 20 20 73 44 69 63 4e 61 6d           sDicNam
3c30: 65 20 3d 20 64 56 61 72 73 5b 27 64 69 63 5f 63  e = dVars['dic_c
3c40: 6f 6d 6d 75 6e 69 74 79 5f 6e 61 6d 65 27 5d 0a  ommunity_name'].
3c50: 20 20 20 20 20 20 20 20 20 20 20 20 73 44 65 73              sDes
3c60: 63 72 69 70 74 69 6f 6e 20 3d 20 64 56 61 72 73  cription = dVars
3c70: 5b 27 64 69 63 5f 63 6f 6d 6d 75 6e 69 74 79 5f  ['dic_community_
3c80: 64 65 73 63 72 69 70 74 69 6f 6e 27 5d 0a 20 20  description'].  
3c90: 20 20 20 20 20 20 65 6c 69 66 20 73 54 79 70 65        elif sType
3ca0: 20 3d 3d 20 22 70 65 72 73 6f 6e 61 6c 22 3a 0a   == "personal":.
3cb0: 20 20 20 20 20 20 20 20 20 20 20 20 73 70 66 4c              spfL
3cc0: 65 78 53 72 63 20 3d 20 64 56 61 72 73 5b 27 6c  exSrc = dVars['l
3cd0: 65 78 69 63 6f 6e 5f 70 65 72 73 6f 6e 61 6c 5f  exicon_personal_
3ce0: 73 72 63 27 5d 0a 20 20 20 20 20 20 20 20 20 20  src'].          
3cf0: 20 20 73 66 44 69 63 74 44 73 74 20 3d 20 64 56    sfDictDst = dV
3d00: 61 72 73 5b 27 64 69 63 5f 70 65 72 73 6f 6e 61  ars['dic_persona
3d10: 6c 5f 66 69 6c 65 6e 61 6d 65 27 5d 0a 20 20 20  l_filename'].   
3d20: 20 20 20 20 20 20 20 20 20 73 44 69 63 4e 61 6d           sDicNam
3d30: 65 20 3d 20 64 56 61 72 73 5b 27 64 69 63 5f 70  e = dVars['dic_p
3d40: 65 72 73 6f 6e 61 6c 5f 6e 61 6d 65 27 5d 0a 20  ersonal_name']. 
3d50: 20 20 20 20 20 20 20 20 20 20 20 73 44 65 73 63             sDesc
3d60: 72 69 70 74 69 6f 6e 20 3d 20 64 56 61 72 73 5b  ription = dVars[
3d70: 27 64 69 63 5f 70 65 72 73 6f 6e 61 6c 5f 64 65  'dic_personal_de
3d80: 73 63 72 69 70 74 69 6f 6e 27 5d 0a 20 20 20 20  scription'].    
3d90: 20 20 20 20 6c 65 78 5f 62 75 69 6c 64 2e 62 75      lex_build.bu
3da0: 69 6c 64 28 73 70 66 4c 65 78 53 72 63 2c 20 64  ild(spfLexSrc, d
3db0: 56 61 72 73 5b 27 6c 61 6e 67 27 5d 2c 20 64 56  Vars['lang'], dV
3dc0: 61 72 73 5b 27 6c 61 6e 67 5f 6e 61 6d 65 27 5d  ars['lang_name']
3dd0: 2c 20 73 66 44 69 63 74 44 73 74 2c 20 62 4a 61  , sfDictDst, bJa
3de0: 76 61 53 63 72 69 70 74 2c 20 73 44 69 63 4e 61  vaScript, sDicNa
3df0: 6d 65 2c 20 73 44 65 73 63 72 69 70 74 69 6f 6e  me, sDescription
3e00: 2c 20 22 22 2c 20 64 56 61 72 73 5b 27 73 74 65  , "", dVars['ste
3e10: 6d 6d 69 6e 67 5f 6d 65 74 68 6f 64 27 5d 2c 20  mming_method'], 
3e20: 69 6e 74 28 64 56 61 72 73 5b 27 66 73 61 5f 6d  int(dVars['fsa_m
3e30: 65 74 68 6f 64 27 5d 29 29 0a 0a 0a 64 65 66 20  ethod']))...def 
3e40: 6d 61 69 6e 20 28 29 3a 0a 20 20 20 20 22 62 75  main ():.    "bu
3e50: 69 6c 64 20 47 72 61 6d 6d 61 6c 65 63 74 65 20  ild Grammalecte 
3e60: 77 69 74 68 20 72 65 71 75 65 73 74 65 64 20 6f  with requested o
3e70: 70 74 69 6f 6e 73 22 0a 20 20 20 20 70 72 69 6e  ptions".    prin
3e80: 74 28 22 50 79 74 68 6f 6e 3a 20 22 20 2b 20 73  t("Python: " + s
3e90: 79 73 2e 76 65 72 73 69 6f 6e 29 0a 20 20 20 20  ys.version).    
3ea0: 69 66 20 73 79 73 2e 76 65 72 73 69 6f 6e 20 3c  if sys.version <
3eb0: 20 22 33 2e 37 22 3a 0a 20 20 20 20 20 20 20 20   "3.7":.        
3ec0: 70 72 69 6e 74 28 22 50 79 74 68 6f 6e 20 33 2e  print("Python 3.
3ed0: 37 2b 20 72 65 71 75 69 72 65 64 22 29 0a 20 20  7+ required").  
3ee0: 20 20 20 20 20 20 72 65 74 75 72 6e 0a 20 20 20        return.   
3ef0: 20 78 50 61 72 73 65 72 20 3d 20 61 72 67 70 61   xParser = argpa
3f00: 72 73 65 2e 41 72 67 75 6d 65 6e 74 50 61 72 73  rse.ArgumentPars
3f10: 65 72 28 29 0a 20 20 20 20 78 50 61 72 73 65 72  er().    xParser
3f20: 2e 61 64 64 5f 61 72 67 75 6d 65 6e 74 28 22 6c  .add_argument("l
3f30: 61 6e 67 22 2c 20 74 79 70 65 3d 73 74 72 2c 20  ang", type=str, 
3f40: 6e 61 72 67 73 3d 27 2b 27 2c 20 68 65 6c 70 3d  nargs='+', help=
3f50: 22 6c 61 6e 67 20 70 72 6f 6a 65 63 74 20 74 6f  "lang project to
3f60: 20 67 65 6e 65 72 61 74 65 20 28 6e 61 6d 65 20   generate (name 
3f70: 6f 66 20 66 6f 6c 64 65 72 20 69 6e 20 2f 6c 61  of folder in /la
3f80: 6e 67 29 22 29 0a 20 20 20 20 78 50 61 72 73 65  ng)").    xParse
3f90: 72 2e 61 64 64 5f 61 72 67 75 6d 65 6e 74 28 22  r.add_argument("
3fa0: 2d 75 63 22 2c 20 22 2d 2d 75 73 65 5f 63 61 63  -uc", "--use_cac
3fb0: 68 65 22 2c 20 68 65 6c 70 3d 22 75 73 65 20 64  he", help="use d
3fc0: 61 74 61 20 63 61 63 68 65 20 69 6e 73 74 65 61  ata cache instea
3fd0: 64 20 6f 66 20 72 65 62 75 69 6c 64 69 6e 67 20  d of rebuilding 
3fe0: 72 75 6c 65 73 22 2c 20 61 63 74 69 6f 6e 3d 22  rules", action="
3ff0: 73 74 6f 72 65 5f 74 72 75 65 22 29 0a 20 20 20  store_true").   
4000: 20 78 50 61 72 73 65 72 2e 61 64 64 5f 61 72 67   xParser.add_arg
4010: 75 6d 65 6e 74 28 22 2d 66 72 62 22 2c 20 22 2d  ument("-frb", "-
4020: 2d 66 6f 72 63 65 5f 72 65 62 75 69 6c 64 22 2c  -force_rebuild",
4030: 20 68 65 6c 70 3d 22 66 6f 72 63 65 20 72 65 62   help="force reb
4040: 75 69 6c 64 69 6e 67 20 72 75 6c 65 73 22 2c 20  uilding rules", 
4050: 61 63 74 69 6f 6e 3d 22 73 74 6f 72 65 5f 74 72  action="store_tr
4060: 75 65 22 29 0a 20 20 20 20 78 50 61 72 73 65 72  ue").    xParser
4070: 2e 61 64 64 5f 61 72 67 75 6d 65 6e 74 28 22 2d  .add_argument("-
4080: 62 22 2c 20 22 2d 2d 62 75 69 6c 64 5f 64 61 74  b", "--build_dat
4090: 61 22 2c 20 68 65 6c 70 3d 22 6c 61 75 6e 63 68  a", help="launch
40a0: 20 62 75 69 6c 64 5f 64 61 74 61 2e 70 79 20 28   build_data.py (
40b0: 70 61 72 74 20 31 20 61 6e 64 20 32 29 22 2c 20  part 1 and 2)", 
40c0: 61 63 74 69 6f 6e 3d 22 73 74 6f 72 65 5f 74 72  action="store_tr
40d0: 75 65 22 29 0a 20 20 20 20 78 50 61 72 73 65 72  ue").    xParser
40e0: 2e 61 64 64 5f 61 72 67 75 6d 65 6e 74 28 22 2d  .add_argument("-
40f0: 62 62 22 2c 20 22 2d 2d 62 75 69 6c 64 5f 64 61  bb", "--build_da
4100: 74 61 5f 62 65 66 6f 72 65 22 2c 20 68 65 6c 70  ta_before", help
4110: 3d 22 6c 61 75 6e 63 68 20 62 75 69 6c 64 5f 64  ="launch build_d
4120: 61 74 61 2e 70 79 20 28 6f 6e 6c 79 20 70 61 72  ata.py (only par
4130: 74 20 31 3a 20 62 65 66 6f 72 65 20 64 69 63 74  t 1: before dict
4140: 69 6f 6e 61 72 79 20 62 75 69 6c 64 69 6e 67 29  ionary building)
4150: 22 2c 20 61 63 74 69 6f 6e 3d 22 73 74 6f 72 65  ", action="store
4160: 5f 74 72 75 65 22 29 0a 20 20 20 20 78 50 61 72  _true").    xPar
4170: 73 65 72 2e 61 64 64 5f 61 72 67 75 6d 65 6e 74  ser.add_argument
4180: 28 22 2d 62 61 22 2c 20 22 2d 2d 62 75 69 6c 64  ("-ba", "--build
4190: 5f 64 61 74 61 5f 61 66 74 65 72 22 2c 20 68 65  _data_after", he
41a0: 6c 70 3d 22 6c 61 75 6e 63 68 20 62 75 69 6c 64  lp="launch build
41b0: 5f 64 61 74 61 2e 70 79 20 28 6f 6e 6c 79 20 70  _data.py (only p
41c0: 61 72 74 20 32 3a 20 62 65 66 6f 72 65 20 64 69  art 2: before di
41d0: 63 74 69 6f 6e 61 72 79 20 62 75 69 6c 64 69 6e  ctionary buildin
41e0: 67 29 22 2c 20 61 63 74 69 6f 6e 3d 22 73 74 6f  g)", action="sto
41f0: 72 65 5f 74 72 75 65 22 29 0a 20 20 20 20 78 50  re_true").    xP
4200: 61 72 73 65 72 2e 61 64 64 5f 61 72 67 75 6d 65  arser.add_argume
4210: 6e 74 28 22 2d 64 22 2c 20 22 2d 2d 64 69 63 74  nt("-d", "--dict
4220: 22 2c 20 68 65 6c 70 3d 22 67 65 6e 65 72 61 74  ", help="generat
4230: 65 20 46 53 41 20 64 69 63 74 69 6f 6e 61 72 79  e FSA dictionary
4240: 22 2c 20 61 63 74 69 6f 6e 3d 22 73 74 6f 72 65  ", action="store
4250: 5f 74 72 75 65 22 29 0a 20 20 20 20 78 50 61 72  _true").    xPar
4260: 73 65 72 2e 61 64 64 5f 61 72 67 75 6d 65 6e 74  ser.add_argument
4270: 28 22 2d 74 22 2c 20 22 2d 2d 74 65 73 74 73 22  ("-t", "--tests"
4280: 2c 20 68 65 6c 70 3d 22 72 75 6e 20 75 6e 69 74  , help="run unit
4290: 20 74 65 73 74 73 22 2c 20 61 63 74 69 6f 6e 3d   tests", action=
42a0: 22 73 74 6f 72 65 5f 74 72 75 65 22 29 0a 20 20  "store_true").  
42b0: 20 20 78 50 61 72 73 65 72 2e 61 64 64 5f 61 72    xParser.add_ar
42c0: 67 75 6d 65 6e 74 28 22 2d 70 22 2c 20 22 2d 2d  gument("-p", "--
42d0: 70 65 72 66 22 2c 20 68 65 6c 70 3d 22 72 75 6e  perf", help="run
42e0: 20 70 65 72 66 6f 72 6d 61 6e 63 65 20 74 65 73   performance tes
42f0: 74 73 22 2c 20 61 63 74 69 6f 6e 3d 22 73 74 6f  ts", action="sto
4300: 72 65 5f 74 72 75 65 22 29 0a 20 20 20 20 78 50  re_true").    xP
4310: 61 72 73 65 72 2e 61 64 64 5f 61 72 67 75 6d 65  arser.add_argume
4320: 6e 74 28 22 2d 70 6d 22 2c 20 22 2d 2d 70 65 72  nt("-pm", "--per
4330: 66 5f 6d 65 6d 6f 22 2c 20 68 65 6c 70 3d 22 72  f_memo", help="r
4340: 75 6e 20 70 65 72 66 6f 72 6d 61 6e 63 65 20 74  un performance t
4350: 65 73 74 73 20 61 6e 64 20 73 74 6f 72 65 20 72  ests and store r
4360: 65 73 75 6c 74 73 20 69 6e 20 70 65 72 66 5f 6d  esults in perf_m
4370: 65 6d 6f 2e 74 78 74 22 2c 20 61 63 74 69 6f 6e  emo.txt", action
4380: 3d 22 73 74 6f 72 65 5f 74 72 75 65 22 29 0a 20  ="store_true"). 
4390: 20 20 20 78 50 61 72 73 65 72 2e 61 64 64 5f 61     xParser.add_a
43a0: 72 67 75 6d 65 6e 74 28 22 2d 6a 73 22 2c 20 22  rgument("-js", "
43b0: 2d 2d 6a 61 76 61 73 63 72 69 70 74 22 2c 20 68  --javascript", h
43c0: 65 6c 70 3d 22 4a 61 76 61 53 63 72 69 70 74 20  elp="JavaScript 
43d0: 62 75 69 6c 64 20 66 6f 72 20 46 69 72 65 66 6f  build for Firefo
43e0: 78 22 2c 20 61 63 74 69 6f 6e 3d 22 73 74 6f 72  x", action="stor
43f0: 65 5f 74 72 75 65 22 29 0a 20 20 20 20 78 50 61  e_true").    xPa
4400: 72 73 65 72 2e 61 64 64 5f 61 72 67 75 6d 65 6e  rser.add_argumen
4410: 74 28 22 2d 61 63 64 22 2c 20 22 2d 2d 61 64 64  t("-acd", "--add
4420: 5f 63 6f 6d 6d 75 6e 69 74 79 5f 64 69 63 74 69  _community_dicti
4430: 6f 6e 61 72 79 22 2c 20 68 65 6c 70 3d 22 61 64  onary", help="ad
4440: 64 20 63 6f 6d 6d 75 6e 69 74 79 20 64 69 63 74  d community dict
4450: 69 6f 6e 61 72 79 20 74 6f 20 74 68 65 20 62 75  ionary to the bu
4460: 69 6c 64 22 2c 20 61 63 74 69 6f 6e 3d 22 73 74  ild", action="st
4470: 6f 72 65 5f 74 72 75 65 22 29 0a 20 20 20 20 78  ore_true").    x
4480: 50 61 72 73 65 72 2e 61 64 64 5f 61 72 67 75 6d  Parser.add_argum
4490: 65 6e 74 28 22 2d 61 70 64 22 2c 20 22 2d 2d 61  ent("-apd", "--a
44a0: 64 64 5f 70 65 72 73 6f 6e 61 6c 5f 64 69 63 74  dd_personal_dict
44b0: 69 6f 6e 61 72 79 22 2c 20 68 65 6c 70 3d 22 61  ionary", help="a
44c0: 64 64 20 70 65 72 73 6f 6e 61 6c 20 64 69 63 74  dd personal dict
44d0: 69 6f 6e 61 72 79 20 74 6f 20 74 68 65 20 62 75  ionary to the bu
44e0: 69 6c 64 22 2c 20 61 63 74 69 6f 6e 3d 22 73 74  ild", action="st
44f0: 6f 72 65 5f 74 72 75 65 22 29 0a 20 20 20 20 78  ore_true").    x
4500: 50 61 72 73 65 72 2e 61 64 64 5f 61 72 67 75 6d  Parser.add_argum
4510: 65 6e 74 28 22 2d 66 78 22 2c 20 22 2d 2d 66 69  ent("-fx", "--fi
4520: 72 65 66 6f 78 22 2c 20 68 65 6c 70 3d 22 4c 61  refox", help="La
4530: 75 6e 63 68 20 46 69 72 65 66 6f 78 20 44 65 76  unch Firefox Dev
4540: 65 6c 6f 70 70 65 72 20 66 6f 72 20 57 65 62 45  elopper for WebE
4550: 78 74 65 6e 73 69 6f 6e 20 74 65 73 74 69 6e 67  xtension testing
4560: 22 2c 20 61 63 74 69 6f 6e 3d 22 73 74 6f 72 65  ", action="store
4570: 5f 74 72 75 65 22 29 0a 20 20 20 20 78 50 61 72  _true").    xPar
4580: 73 65 72 2e 61 64 64 5f 61 72 67 75 6d 65 6e 74  ser.add_argument
4590: 28 22 2d 66 78 6e 22 2c 20 22 2d 2d 66 69 72 65  ("-fxn", "--fire
45a0: 66 6f 78 5f 6e 69 67 68 74 6c 79 22 2c 20 68 65  fox_nightly", he
45b0: 6c 70 3d 22 4c 61 75 6e 63 68 20 46 69 72 65 66  lp="Launch Firef
45c0: 6f 78 20 4e 69 67 68 74 6c 79 20 66 6f 72 20 57  ox Nightly for W
45d0: 65 62 45 78 74 65 6e 73 69 6f 6e 20 74 65 73 74  ebExtension test
45e0: 69 6e 67 22 2c 20 61 63 74 69 6f 6e 3d 22 73 74  ing", action="st
45f0: 6f 72 65 5f 74 72 75 65 22 29 0a 20 20 20 20 78  ore_true").    x
4600: 50 61 72 73 65 72 2e 61 64 64 5f 61 72 67 75 6d  Parser.add_argum
4610: 65 6e 74 28 22 2d 6c 22 2c 20 22 2d 2d 6c 69 6e  ent("-l", "--lin
4620: 74 5f 77 65 62 5f 65 78 74 22 2c 20 68 65 6c 70  t_web_ext", help
4630: 3d 22 77 65 62 2d 65 78 74 20 6c 69 6e 74 20 6f  ="web-ext lint o
4640: 6e 20 74 68 65 20 57 65 62 45 78 74 65 6e 73 69  n the WebExtensi
4650: 6f 6e 22 2c 20 61 63 74 69 6f 6e 3d 22 73 74 6f  on", action="sto
4660: 72 65 5f 74 72 75 65 22 29 0a 20 20 20 20 78 50  re_true").    xP
4670: 61 72 73 65 72 2e 61 64 64 5f 61 72 67 75 6d 65  arser.add_argume
4680: 6e 74 28 22 2d 74 62 22 2c 20 22 2d 2d 74 68 75  nt("-tb", "--thu
4690: 6e 64 65 72 62 69 72 64 22 2c 20 68 65 6c 70 3d  nderbird", help=
46a0: 22 4c 61 75 6e 63 68 20 54 68 75 6e 64 65 72 62  "Launch Thunderb
46b0: 69 72 64 22 2c 20 61 63 74 69 6f 6e 3d 22 73 74  ird", action="st
46c0: 6f 72 65 5f 74 72 75 65 22 29 0a 20 20 20 20 78  ore_true").    x
46d0: 50 61 72 73 65 72 2e 61 64 64 5f 61 72 67 75 6d  Parser.add_argum
46e0: 65 6e 74 28 22 2d 74 62 62 22 2c 20 22 2d 2d 74  ent("-tbb", "--t
46f0: 68 75 6e 64 65 72 62 69 72 64 5f 62 65 74 61 22  hunderbird_beta"
4700: 2c 20 68 65 6c 70 3d 22 4c 61 75 6e 63 68 20 54  , help="Launch T
4710: 68 75 6e 64 65 72 62 69 72 64 20 42 65 74 61 22  hunderbird Beta"
4720: 2c 20 61 63 74 69 6f 6e 3d 22 73 74 6f 72 65 5f  , action="store_
4730: 74 72 75 65 22 29 0a 20 20 20 20 78 50 61 72 73  true").    xPars
4740: 65 72 2e 61 64 64 5f 61 72 67 75 6d 65 6e 74 28  er.add_argument(
4750: 22 2d 69 22 2c 20 22 2d 2d 69 6e 73 74 61 6c 6c  "-i", "--install
4760: 22 2c 20 68 65 6c 70 3d 22 69 6e 73 74 61 6c 6c  ", help="install
4770: 20 74 68 65 20 65 78 74 65 6e 73 69 6f 6e 20 69   the extension i
4780: 6e 20 57 72 69 74 65 72 20 28 70 61 74 68 20 6f  n Writer (path o
4790: 66 20 75 6e 6f 70 6b 67 20 6d 75 73 74 20 62 65  f unopkg must be
47a0: 20 73 65 74 20 69 6e 20 63 6f 6e 66 69 67 2e 69   set in config.i
47b0: 6e 69 29 22 2c 20 61 63 74 69 6f 6e 3d 22 73 74  ni)", action="st
47c0: 6f 72 65 5f 74 72 75 65 22 29 0a 20 20 20 20 78  ore_true").    x
47d0: 41 72 67 73 20 3d 20 78 50 61 72 73 65 72 2e 70  Args = xParser.p
47e0: 61 72 73 65 5f 61 72 67 73 28 29 0a 0a 20 20 20  arse_args()..   
47f0: 20 69 66 20 78 41 72 67 73 2e 62 75 69 6c 64 5f   if xArgs.build_
4800: 64 61 74 61 3a 0a 20 20 20 20 20 20 20 20 78 41  data:.        xA
4810: 72 67 73 2e 62 75 69 6c 64 5f 64 61 74 61 5f 62  rgs.build_data_b
4820: 65 66 6f 72 65 20 3d 20 54 72 75 65 0a 20 20 20  efore = True.   
4830: 20 20 20 20 20 78 41 72 67 73 2e 62 75 69 6c 64       xArgs.build
4840: 5f 64 61 74 61 5f 61 66 74 65 72 20 3d 20 54 72  _data_after = Tr
4850: 75 65 0a 0a 20 20 20 20 64 69 72 5f 75 74 69 6c  ue..    dir_util
4860: 2e 6d 6b 70 61 74 68 28 22 5f 62 75 69 6c 64 22  .mkpath("_build"
4870: 29 0a 20 20 20 20 64 69 72 5f 75 74 69 6c 2e 6d  ).    dir_util.m
4880: 6b 70 61 74 68 28 22 67 72 61 6d 6d 61 6c 65 63  kpath("grammalec
4890: 74 65 22 29 0a 20 20 20 20 69 66 20 78 41 72 67  te").    if xArg
48a0: 73 2e 6a 61 76 61 73 63 72 69 70 74 3a 0a 20 20  s.javascript:.  
48b0: 20 20 20 20 20 20 64 69 72 5f 75 74 69 6c 2e 6d        dir_util.m
48c0: 6b 70 61 74 68 28 22 67 72 61 6d 6d 61 6c 65 63  kpath("grammalec
48d0: 74 65 2d 6a 73 22 29 0a 0a 20 20 20 20 63 6f 70  te-js")..    cop
48e0: 79 47 72 61 70 68 73 70 65 6c 6c 43 6f 72 65 28  yGraphspellCore(
48f0: 78 41 72 67 73 2e 6a 61 76 61 73 63 72 69 70 74  xArgs.javascript
4900: 29 0a 0a 20 20 20 20 66 6f 72 20 73 4c 61 6e 67  )..    for sLang
4910: 20 69 6e 20 78 41 72 67 73 2e 6c 61 6e 67 3a 0a   in xArgs.lang:.
4920: 20 20 20 20 20 20 20 20 69 66 20 6f 73 2e 70 61          if os.pa
4930: 74 68 2e 65 78 69 73 74 73 28 22 67 63 5f 6c 61  th.exists("gc_la
4940: 6e 67 2f 22 2b 73 4c 61 6e 67 29 20 61 6e 64 20  ng/"+sLang) and 
4950: 6f 73 2e 70 61 74 68 2e 69 73 64 69 72 28 22 67  os.path.isdir("g
4960: 63 5f 6c 61 6e 67 2f 22 2b 73 4c 61 6e 67 29 3a  c_lang/"+sLang):
4970: 0a 20 20 20 20 20 20 20 20 20 20 20 20 78 43 6f  .            xCo
4980: 6e 66 69 67 20 3d 20 67 65 74 43 6f 6e 66 69 67  nfig = getConfig
4990: 28 73 4c 61 6e 67 29 0a 20 20 20 20 20 20 20 20  (sLang).        
49a0: 20 20 20 20 64 56 61 72 73 20 3d 20 78 43 6f 6e      dVars = xCon
49b0: 66 69 67 2e 5f 73 65 63 74 69 6f 6e 73 5b 27 61  fig._sections['a
49c0: 72 67 73 27 5d 0a 0a 20 20 20 20 20 20 20 20 20  rgs']..         
49d0: 20 20 20 69 66 20 6e 6f 74 20 64 56 61 72 73 5b     if not dVars[
49e0: 22 6c 65 78 69 63 6f 6e 5f 63 6f 6d 6d 75 6e 69  "lexicon_communi
49f0: 74 79 5f 73 72 63 22 5d 3a 0a 20 20 20 20 20 20  ty_src"]:.      
4a00: 20 20 20 20 20 20 20 20 20 20 78 41 72 67 73 2e            xArgs.
4a10: 61 64 64 5f 63 6f 6d 6d 75 6e 69 74 79 5f 64 69  add_community_di
4a20: 63 74 69 6f 6e 61 72 79 20 3d 20 46 61 6c 73 65  ctionary = False
4a30: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
4a40: 6e 6f 74 20 64 56 61 72 73 5b 22 6c 65 78 69 63  not dVars["lexic
4a50: 6f 6e 5f 70 65 72 73 6f 6e 61 6c 5f 73 72 63 22  on_personal_src"
4a60: 5d 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ]:.             
4a70: 20 20 20 78 41 72 67 73 2e 61 64 64 5f 70 65 72     xArgs.add_per
4a80: 73 6f 6e 61 6c 5f 64 69 63 74 69 6f 6e 61 72 79  sonal_dictionary
4a90: 20 3d 20 46 61 6c 73 65 0a 0a 20 20 20 20 20 20   = False..      
4aa0: 20 20 20 20 20 20 23 20 62 75 69 6c 64 20 64 61        # build da
4ab0: 74 61 0a 20 20 20 20 20 20 20 20 20 20 20 20 64  ta.            d
4ac0: 61 74 61 62 75 69 6c 64 20 3d 20 4e 6f 6e 65 0a  atabuild = None.
4ad0: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 78              if x
4ae0: 41 72 67 73 2e 62 75 69 6c 64 5f 64 61 74 61 5f  Args.build_data_
4af0: 62 65 66 6f 72 65 20 6f 72 20 78 41 72 67 73 2e  before or xArgs.
4b00: 62 75 69 6c 64 5f 64 61 74 61 5f 61 66 74 65 72  build_data_after
4b10: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
4b20: 20 20 23 20 6c 61 6e 67 20 64 61 74 61 0a 20 20    # lang data.  
4b30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 74 72                tr
4b40: 79 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  y:.             
4b50: 20 20 20 20 20 20 20 64 61 74 61 62 75 69 6c 64         databuild
4b60: 20 3d 20 69 6d 70 6f 72 74 6c 69 62 2e 69 6d 70   = importlib.imp
4b70: 6f 72 74 5f 6d 6f 64 75 6c 65 28 22 67 63 5f 6c  ort_module("gc_l
4b80: 61 6e 67 2e 22 2b 73 4c 61 6e 67 2b 22 2e 62 75  ang."+sLang+".bu
4b90: 69 6c 64 5f 64 61 74 61 22 29 0a 20 20 20 20 20  ild_data").     
4ba0: 20 20 20 20 20 20 20 20 20 20 20 65 78 63 65 70             excep
4bb0: 74 20 49 6d 70 6f 72 74 45 72 72 6f 72 3a 0a 20  t ImportError:. 
4bc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4bd0: 20 20 20 70 72 69 6e 74 28 22 23 20 45 72 72 6f     print("# Erro
4be0: 72 2e 20 43 6f 75 6c 64 6e e2 80 99 74 20 69 6d  r. Couldn...t im
4bf0: 70 6f 72 74 20 66 69 6c 65 20 62 75 69 6c 64 5f  port file build_
4c00: 64 61 74 61 2e 70 79 20 69 6e 20 66 6f 6c 64 65  data.py in folde
4c10: 72 20 67 63 5f 6c 61 6e 67 2f 22 2b 73 4c 61 6e  r gc_lang/"+sLan
4c20: 67 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 69  g).            i
4c30: 66 20 64 61 74 61 62 75 69 6c 64 20 61 6e 64 20  f databuild and 
4c40: 78 41 72 67 73 2e 62 75 69 6c 64 5f 64 61 74 61  xArgs.build_data
4c50: 5f 62 65 66 6f 72 65 3a 0a 20 20 20 20 20 20 20  _before:.       
4c60: 20 20 20 20 20 20 20 20 20 64 61 74 61 62 75 69           databui
4c70: 6c 64 2e 62 65 66 6f 72 65 28 27 67 63 5f 6c 61  ld.before('gc_la
4c80: 6e 67 2f 27 2b 73 4c 61 6e 67 2c 20 64 56 61 72  ng/'+sLang, dVar
4c90: 73 2c 20 78 41 72 67 73 2e 6a 61 76 61 73 63 72  s, xArgs.javascr
4ca0: 69 70 74 29 0a 20 20 20 20 20 20 20 20 20 20 20  ipt).           
4cb0: 20 69 66 20 78 41 72 67 73 2e 64 69 63 74 3a 0a   if xArgs.dict:.
4cc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4cd0: 62 75 69 6c 64 44 69 63 74 69 6f 6e 61 72 79 28  buildDictionary(
4ce0: 64 56 61 72 73 2c 20 22 6d 61 69 6e 22 2c 20 78  dVars, "main", x
4cf0: 41 72 67 73 2e 6a 61 76 61 73 63 72 69 70 74 29  Args.javascript)
4d00: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
4d10: 20 69 66 20 78 41 72 67 73 2e 61 64 64 5f 63 6f   if xArgs.add_co
4d20: 6d 6d 75 6e 69 74 79 5f 64 69 63 74 69 6f 6e 61  mmunity_dictiona
4d30: 72 79 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ry:.            
4d40: 20 20 20 20 20 20 20 20 62 75 69 6c 64 44 69 63          buildDic
4d50: 74 69 6f 6e 61 72 79 28 64 56 61 72 73 2c 20 22  tionary(dVars, "
4d60: 63 6f 6d 6d 75 6e 69 74 79 22 2c 20 78 41 72 67  community", xArg
4d70: 73 2e 6a 61 76 61 73 63 72 69 70 74 29 0a 20 20  s.javascript).  
4d80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
4d90: 20 78 41 72 67 73 2e 61 64 64 5f 70 65 72 73 6f   xArgs.add_perso
4da0: 6e 61 6c 5f 64 69 63 74 69 6f 6e 61 72 79 3a 0a  nal_dictionary:.
4db0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4dc0: 20 20 20 20 62 75 69 6c 64 44 69 63 74 69 6f 6e      buildDiction
4dd0: 61 72 79 28 64 56 61 72 73 2c 20 22 70 65 72 73  ary(dVars, "pers
4de0: 6f 6e 61 6c 22 2c 20 78 41 72 67 73 2e 6a 61 76  onal", xArgs.jav
4df0: 61 73 63 72 69 70 74 29 0a 20 20 20 20 20 20 20  ascript).       
4e00: 20 20 20 20 20 69 66 20 64 61 74 61 62 75 69 6c       if databuil
4e10: 64 20 61 6e 64 20 78 41 72 67 73 2e 62 75 69 6c  d and xArgs.buil
4e20: 64 5f 64 61 74 61 5f 61 66 74 65 72 3a 0a 20 20  d_data_after:.  
4e30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 64 61                da
4e40: 74 61 62 75 69 6c 64 2e 61 66 74 65 72 28 27 67  tabuild.after('g
4e50: 63 5f 6c 61 6e 67 2f 27 2b 73 4c 61 6e 67 2c 20  c_lang/'+sLang, 
4e60: 64 56 61 72 73 2c 20 78 41 72 67 73 2e 6a 61 76  dVars, xArgs.jav
4e70: 61 73 63 72 69 70 74 29 0a 0a 20 20 20 20 20 20  ascript)..      
4e80: 20 20 20 20 20 20 23 20 63 6f 70 79 20 64 69 63        # copy dic
4e90: 74 69 6f 6e 61 72 69 65 73 20 66 72 6f 6d 20 47  tionaries from G
4ea0: 72 61 70 68 73 70 65 6c 6c 0a 20 20 20 20 20 20  raphspell.      
4eb0: 20 20 20 20 20 20 63 6f 70 79 47 72 61 70 68 73        copyGraphs
4ec0: 70 65 6c 6c 44 69 63 74 69 6f 6e 61 72 69 65 73  pellDictionaries
4ed0: 28 64 56 61 72 73 2c 20 78 41 72 67 73 2e 6a 61  (dVars, xArgs.ja
4ee0: 76 61 73 63 72 69 70 74 2c 20 78 41 72 67 73 2e  vascript, xArgs.
4ef0: 61 64 64 5f 63 6f 6d 6d 75 6e 69 74 79 5f 64 69  add_community_di
4f00: 63 74 69 6f 6e 61 72 79 2c 20 78 41 72 67 73 2e  ctionary, xArgs.
4f10: 61 64 64 5f 70 65 72 73 6f 6e 61 6c 5f 64 69 63  add_personal_dic
4f20: 74 69 6f 6e 61 72 79 29 0a 0a 20 20 20 20 20 20  tionary)..      
4f30: 20 20 20 20 20 20 23 20 6d 61 6b 65 0a 20 20 20        # make.   
4f40: 20 20 20 20 20 20 20 20 20 62 55 73 65 43 61 63           bUseCac
4f50: 68 65 20 3d 20 4e 6f 6e 65 20 20 20 20 20 20 20  he = None       
4f60: 20 20 20 20 20 23 20 77 65 20 6d 61 79 20 72 65       # we may re
4f70: 62 75 69 6c 64 20 69 66 20 69 74 e2 80 99 73 20  build if it...s 
4f80: 6e 65 63 65 73 73 61 72 79 0a 20 20 20 20 20 20  necessary.      
4f90: 20 20 20 20 20 20 69 66 20 78 41 72 67 73 2e 75        if xArgs.u
4fa0: 73 65 5f 63 61 63 68 65 3a 0a 20 20 20 20 20 20  se_cache:.      
4fb0: 20 20 20 20 20 20 20 20 20 20 62 55 73 65 43 61            bUseCa
4fc0: 63 68 65 20 3d 20 54 72 75 65 20 20 20 20 20 20  che = True      
4fd0: 20 20 23 20 77 65 20 75 73 65 20 74 68 65 20 63    # we use the c
4fe0: 61 63 68 65 20 69 66 20 69 74 20 65 78 69 73 74  ache if it exist
4ff0: 73 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  s.            if
5000: 20 78 41 72 67 73 2e 66 6f 72 63 65 5f 72 65 62   xArgs.force_reb
5010: 75 69 6c 64 3a 0a 20 20 20 20 20 20 20 20 20 20  uild:.          
5020: 20 20 20 20 20 20 62 55 73 65 43 61 63 68 65 20        bUseCache 
5030: 3d 20 46 61 6c 73 65 20 20 20 20 20 20 20 23 20  = False       # 
5040: 77 65 20 72 65 62 75 69 6c 64 0a 20 20 20 20 20  we rebuild.     
5050: 20 20 20 20 20 20 20 73 56 65 72 73 69 6f 6e 20         sVersion 
5060: 3d 20 63 72 65 61 74 65 28 73 4c 61 6e 67 2c 20  = create(sLang, 
5070: 78 43 6f 6e 66 69 67 2c 20 78 41 72 67 73 2e 69  xConfig, xArgs.i
5080: 6e 73 74 61 6c 6c 2c 20 78 41 72 67 73 2e 6a 61  nstall, xArgs.ja
5090: 76 61 73 63 72 69 70 74 2c 20 62 55 73 65 43 61  vascript, bUseCa
50a0: 63 68 65 29 0a 0a 20 20 20 20 20 20 20 20 20 20  che)..          
50b0: 20 20 23 20 74 65 73 74 73 0a 20 20 20 20 20 20    # tests.      
50c0: 20 20 20 20 20 20 69 66 20 78 41 72 67 73 2e 74        if xArgs.t
50d0: 65 73 74 73 20 6f 72 20 78 41 72 67 73 2e 70 65  ests or xArgs.pe
50e0: 72 66 20 6f 72 20 78 41 72 67 73 2e 70 65 72 66  rf or xArgs.perf
50f0: 5f 6d 65 6d 6f 3a 0a 20 20 20 20 20 20 20 20 20  _memo:.         
5100: 20 20 20 20 20 20 20 70 72 69 6e 74 28 22 3e 20         print("> 
5110: 52 75 6e 6e 69 6e 67 20 74 65 73 74 73 22 29 0a  Running tests").
5120: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5130: 74 72 79 3a 0a 20 20 20 20 20 20 20 20 20 20 20  try:.           
5140: 20 20 20 20 20 20 20 20 20 74 65 73 74 73 20 3d           tests =
5150: 20 69 6d 70 6f 72 74 6c 69 62 2e 69 6d 70 6f 72   importlib.impor
5160: 74 5f 6d 6f 64 75 6c 65 28 22 67 72 61 6d 6d 61  t_module("gramma
5170: 6c 65 63 74 65 2e 22 2b 73 4c 61 6e 67 2b 22 2e  lecte."+sLang+".
5180: 74 65 73 74 73 22 29 0a 20 20 20 20 20 20 20 20  tests").        
5190: 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69 6e              prin
51a0: 74 28 74 65 73 74 73 2e 5f 5f 66 69 6c 65 5f 5f  t(tests.__file__
51b0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
51c0: 20 20 65 78 63 65 70 74 20 49 6d 70 6f 72 74 45    except ImportE
51d0: 72 72 6f 72 3a 0a 20 20 20 20 20 20 20 20 20 20  rror:.          
51e0: 20 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 28            print(
51f0: 66 22 23 20 45 72 72 6f 72 2e 20 49 6d 70 6f 72  f"# Error. Impor
5200: 74 20 66 61 69 6c 65 64 3a 20 67 72 61 6d 6d 61  t failed: gramma
5210: 6c 65 63 74 65 2e 7b 73 4c 61 6e 67 7d 2e 74 65  lecte.{sLang}.te
5220: 73 74 73 22 29 0a 20 20 20 20 20 20 20 20 20 20  sts").          
5230: 20 20 20 20 20 20 20 20 20 20 74 72 61 63 65 62            traceb
5240: 61 63 6b 2e 70 72 69 6e 74 5f 65 78 63 28 29 0a  ack.print_exc().
5250: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5260: 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20  else:.          
5270: 20 20 20 20 20 20 20 20 20 20 69 66 20 78 41 72            if xAr
5280: 67 73 2e 74 65 73 74 73 3a 0a 20 20 20 20 20 20  gs.tests:.      
5290: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
52a0: 20 20 78 54 65 73 74 53 75 69 74 65 20 3d 20 75    xTestSuite = u
52b0: 6e 69 74 74 65 73 74 2e 54 65 73 74 4c 6f 61 64  nittest.TestLoad
52c0: 65 72 28 29 2e 6c 6f 61 64 54 65 73 74 73 46 72  er().loadTestsFr
52d0: 6f 6d 4d 6f 64 75 6c 65 28 74 65 73 74 73 29 0a  omModule(tests).
52e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
52f0: 20 20 20 20 20 20 20 20 75 6e 69 74 74 65 73 74          unittest
5300: 2e 54 65 78 74 54 65 73 74 52 75 6e 6e 65 72 28  .TextTestRunner(
5310: 29 2e 72 75 6e 28 78 54 65 73 74 53 75 69 74 65  ).run(xTestSuite
5320: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
5330: 20 20 20 20 20 20 69 66 20 78 41 72 67 73 2e 70        if xArgs.p
5340: 65 72 66 20 6f 72 20 78 41 72 67 73 2e 70 65 72  erf or xArgs.per
5350: 66 5f 6d 65 6d 6f 3a 0a 20 20 20 20 20 20 20 20  f_memo:.        
5360: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5370: 68 44 73 74 20 3d 20 6f 70 65 6e 28 22 2e 2f 67  hDst = open("./g
5380: 63 5f 6c 61 6e 67 2f 22 2b 73 4c 61 6e 67 2b 22  c_lang/"+sLang+"
5390: 2f 70 65 72 66 5f 6d 65 6d 6f 2e 74 78 74 22 2c  /perf_memo.txt",
53a0: 20 22 61 22 2c 20 65 6e 63 6f 64 69 6e 67 3d 22   "a", encoding="
53b0: 75 74 66 2d 38 22 2c 20 6e 65 77 6c 69 6e 65 3d  utf-8", newline=
53c0: 22 5c 6e 22 29 20 20 69 66 20 78 41 72 67 73 2e  "\n")  if xArgs.
53d0: 70 65 72 66 5f 6d 65 6d 6f 20 20 65 6c 73 65 20  perf_memo  else 
53e0: 4e 6f 6e 65 0a 20 20 20 20 20 20 20 20 20 20 20  None.           
53f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 74 65 73               tes
5400: 74 73 2e 70 65 72 66 28 73 56 65 72 73 69 6f 6e  ts.perf(sVersion
5410: 2c 20 68 44 73 74 29 0a 0a 20 20 20 20 20 20 20  , hDst)..       
5420: 20 20 20 20 20 23 20 4a 61 76 61 53 63 72 69 70       # JavaScrip
5430: 74 20 6c 69 6e 74 65 72 0a 20 20 20 20 20 20 20  t linter.       
5440: 20 20 20 20 20 69 66 20 78 41 72 67 73 2e 6c 69       if xArgs.li
5450: 6e 74 5f 77 65 62 5f 65 78 74 3a 0a 20 20 20 20  nt_web_ext:.    
5460: 20 20 20 20 20 20 20 20 20 20 20 20 77 69 74 68              with
5470: 20 68 65 6c 70 65 72 73 2e 43 44 28 22 5f 62 75   helpers.CD("_bu
5480: 69 6c 64 2f 77 65 62 65 78 74 2f 22 2b 73 4c 61  ild/webext/"+sLa
5490: 6e 67 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ng):.           
54a0: 20 20 20 20 20 20 20 20 20 6f 73 2e 73 79 73 74           os.syst
54b0: 65 6d 28 72 27 77 65 62 2d 65 78 74 20 6c 69 6e  em(r'web-ext lin
54c0: 74 20 2d 6f 20 74 65 78 74 27 29 0a 0a 20 20 20  t -o text')..   
54d0: 20 20 20 20 20 20 20 20 20 23 20 46 69 72 65 66           # Firef
54e0: 6f 78 0a 20 20 20 20 20 20 20 20 20 20 20 20 69  ox.            i
54f0: 66 20 78 41 72 67 73 2e 66 69 72 65 66 6f 78 3a  f xArgs.firefox:
5500: 20 20 20 20 20 20 20 20 20 20 20 23 20 46 69 72             # Fir
5510: 65 66 6f 78 20 44 65 76 65 6c 6f 70 65 72 20 65  efox Developer e
5520: 64 69 74 69 6f 6e 0a 20 20 20 20 20 20 20 20 20  dition.         
5530: 20 20 20 20 20 20 20 77 69 74 68 20 68 65 6c 70         with help
5540: 65 72 73 2e 43 44 28 22 5f 62 75 69 6c 64 2f 77  ers.CD("_build/w
5550: 65 62 65 78 74 2f 22 2b 73 4c 61 6e 67 29 3a 0a  ebext/"+sLang):.
5560: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5570: 20 20 20 20 73 70 66 46 69 72 65 66 6f 78 20 3d      spfFirefox =
5580: 20 64 56 61 72 73 5b 27 77 69 6e 5f 66 78 5f 64   dVars['win_fx_d
5590: 65 76 5f 70 61 74 68 27 5d 20 20 69 66 20 70 6c  ev_path']  if pl
55a0: 61 74 66 6f 72 6d 2e 73 79 73 74 65 6d 28 29 20  atform.system() 
55b0: 3d 3d 20 22 57 69 6e 64 6f 77 73 22 20 20 65 6c  == "Windows"  el
55c0: 73 65 20 64 56 61 72 73 5b 27 6c 69 6e 75 78 5f  se dVars['linux_
55d0: 66 78 5f 64 65 76 5f 70 61 74 68 27 5d 0a 20 20  fx_dev_path'].  
55e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
55f0: 20 20 6f 73 2e 73 79 73 74 65 6d 28 72 27 77 65    os.system(r'we
5600: 62 2d 65 78 74 20 72 75 6e 20 2d 2d 66 69 72 65  b-ext run --fire
5610: 66 6f 78 3d 22 27 20 2b 20 73 70 66 46 69 72 65  fox="' + spfFire
5620: 66 6f 78 20 2b 20 27 22 20 2d 2d 62 72 6f 77 73  fox + '" --brows
5630: 65 72 2d 63 6f 6e 73 6f 6c 65 27 29 0a 20 20 20  er-console').   
5640: 20 20 20 20 20 20 20 20 20 69 66 20 78 41 72 67           if xArg
5650: 73 2e 66 69 72 65 66 6f 78 5f 6e 69 67 68 74 6c  s.firefox_nightl
5660: 79 3a 20 20 20 23 20 46 69 72 65 66 6f 78 20 4e  y:   # Firefox N
5670: 69 67 68 74 6c 79 20 65 64 69 74 69 6f 6e 0a 20  ightly edition. 
5680: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 77                 w
5690: 69 74 68 20 68 65 6c 70 65 72 73 2e 43 44 28 22  ith helpers.CD("
56a0: 5f 62 75 69 6c 64 2f 77 65 62 65 78 74 2f 22 2b  _build/webext/"+
56b0: 73 4c 61 6e 67 29 3a 0a 20 20 20 20 20 20 20 20  sLang):.        
56c0: 20 20 20 20 20 20 20 20 20 20 20 20 73 70 66 46              spfF
56d0: 69 72 65 66 6f 78 20 3d 20 64 56 61 72 73 5b 27  irefox = dVars['
56e0: 77 69 6e 5f 66 78 5f 6e 69 67 68 74 6c 79 5f 70  win_fx_nightly_p
56f0: 61 74 68 27 5d 20 20 69 66 20 70 6c 61 74 66 6f  ath']  if platfo
5700: 72 6d 2e 73 79 73 74 65 6d 28 29 20 3d 3d 20 22  rm.system() == "
5710: 57 69 6e 64 6f 77 73 22 20 20 65 6c 73 65 20 64  Windows"  else d
5720: 56 61 72 73 5b 27 6c 69 6e 75 78 5f 66 78 5f 6e  Vars['linux_fx_n
5730: 69 67 68 74 6c 79 5f 70 61 74 68 27 5d 0a 20 20  ightly_path'].  
5740: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5750: 20 20 6f 73 2e 73 79 73 74 65 6d 28 72 27 77 65    os.system(r'we
5760: 62 2d 65 78 74 20 72 75 6e 20 2d 2d 66 69 72 65  b-ext run --fire
5770: 66 6f 78 3d 22 27 20 2b 20 73 70 66 46 69 72 65  fox="' + spfFire
5780: 66 6f 78 20 2b 20 27 22 20 2d 2d 62 72 6f 77 73  fox + '" --brows
5790: 65 72 2d 63 6f 6e 73 6f 6c 65 27 29 0a 20 20 20  er-console').   
57a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
57b0: 20 23 20 68 74 74 70 73 3a 2f 2f 67 69 74 68 75   # https://githu
57c0: 62 2e 63 6f 6d 2f 6d 6f 7a 69 6c 6c 61 2f 77 65  b.com/mozilla/we
57d0: 62 2d 65 78 74 2f 69 73 73 75 65 73 2f 39 33 32  b-ext/issues/932
57e0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
57f0: 20 20 20 20 20 23 20 6f 73 2e 73 79 73 74 65 6d       # os.system
5800: 28 72 27 77 65 62 2d 65 78 74 20 72 75 6e 20 2d  (r'web-ext run -
5810: 2d 66 69 72 65 66 6f 78 3d 22 27 20 2b 20 73 70  -firefox="' + sp
5820: 66 46 69 72 65 66 6f 78 20 2b 20 72 27 22 20 2d  fFirefox + r'" -
5830: 2d 62 72 6f 77 73 65 72 2d 63 6f 6e 73 6f 6c 65  -browser-console
5840: 20 2d 2d 66 69 72 65 66 6f 78 2d 70 72 6f 66 69   --firefox-profi
5850: 6c 65 3d 43 3a 5c 55 73 65 72 73 5c 45 41 4b 5c  le=C:\Users\EAK\
5860: 41 70 70 44 61 74 61 5c 52 6f 61 6d 69 6e 67 5c  AppData\Roaming\
5870: 4d 6f 7a 69 6c 6c 61 5c 46 69 72 65 66 6f 78 5c  Mozilla\Firefox\
5880: 50 72 6f 66 69 6c 65 73 5c 65 32 36 35 35 39 74  Profiles\e26559t
5890: 77 2e 64 65 62 75 67 20 2d 2d 6b 65 65 70 2d 70  w.debug --keep-p
58a0: 72 6f 66 69 6c 65 2d 63 68 61 6e 67 65 73 27 29  rofile-changes')
58b0: 0a 0a 20 20 20 20 20 20 20 20 20 20 20 20 23 20  ..            # 
58c0: 54 68 75 6e 64 65 72 62 69 72 64 0a 20 20 20 20  Thunderbird.    
58d0: 20 20 20 20 20 20 20 20 69 66 20 78 41 72 67 73          if xArgs
58e0: 2e 74 68 75 6e 64 65 72 62 69 72 64 3a 0a 20 20  .thunderbird:.  
58f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 70                sp
5900: 66 54 68 75 6e 64 65 72 62 69 72 64 20 3d 20 27  fThunderbird = '
5910: 22 27 2b 64 56 61 72 73 5b 27 77 69 6e 5f 74 62  "'+dVars['win_tb
5920: 5f 70 61 74 68 27 5d 2b 27 22 27 20 20 69 66 20  _path']+'"'  if 
5930: 70 6c 61 74 66 6f 72 6d 2e 73 79 73 74 65 6d 28  platform.system(
5940: 29 20 3d 3d 20 22 57 69 6e 64 6f 77 73 22 20 20  ) == "Windows"  
5950: 65 6c 73 65 20 64 56 61 72 73 5b 27 6c 69 6e 75  else dVars['linu
5960: 78 5f 74 62 5f 70 61 74 68 27 5d 0a 20 20 20 20  x_tb_path'].    
5970: 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69 6e              prin
5980: 74 28 73 70 66 54 68 75 6e 64 65 72 62 69 72 64  t(spfThunderbird
5990: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
59a0: 20 20 6f 73 2e 73 79 73 74 65 6d 28 73 70 66 54    os.system(spfT
59b0: 68 75 6e 64 65 72 62 69 72 64 20 2b 20 27 20 2d  hunderbird + ' -
59c0: 6a 73 63 6f 6e 73 6f 6c 65 20 2d 50 20 64 65 62  jsconsole -P deb
59d0: 75 67 27 29 0a 20 20 20 20 20 20 20 20 20 20 20  ug').           
59e0: 20 69 66 20 78 41 72 67 73 2e 74 68 75 6e 64 65   if xArgs.thunde
59f0: 72 62 69 72 64 5f 62 65 74 61 3a 0a 20 20 20 20  rbird_beta:.    
5a00: 20 20 20 20 20 20 20 20 20 20 20 20 73 70 66 54              spfT
5a10: 68 75 6e 64 65 72 62 69 72 64 20 3d 20 27 22 27  hunderbird = '"'
5a20: 2b 64 56 61 72 73 5b 27 77 69 6e 5f 74 62 5f 62  +dVars['win_tb_b
5a30: 65 74 61 5f 70 61 74 68 27 5d 2b 27 22 27 20 20  eta_path']+'"'  
5a40: 69 66 20 70 6c 61 74 66 6f 72 6d 2e 73 79 73 74  if platform.syst
5a50: 65 6d 28 29 20 3d 3d 20 22 57 69 6e 64 6f 77 73  em() == "Windows
5a60: 22 20 20 65 6c 73 65 20 64 56 61 72 73 5b 27 6c  "  else dVars['l
5a70: 69 6e 75 78 5f 74 62 5f 62 65 74 61 5f 70 61 74  inux_tb_beta_pat
5a80: 68 27 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20  h'].            
5a90: 20 20 20 20 70 72 69 6e 74 28 73 70 66 54 68 75      print(spfThu
5aa0: 6e 64 65 72 62 69 72 64 29 0a 20 20 20 20 20 20  nderbird).      
5ab0: 20 20 20 20 20 20 20 20 20 20 6f 73 2e 73 79 73            os.sys
5ac0: 74 65 6d 28 73 70 66 54 68 75 6e 64 65 72 62 69  tem(spfThunderbi
5ad0: 72 64 20 2b 20 27 20 2d 6a 73 63 6f 6e 73 6f 6c  rd + ' -jsconsol
5ae0: 65 20 2d 50 20 62 65 74 61 27 29 0a 20 20 20 20  e -P beta').    
5af0: 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20      else:.      
5b00: 20 20 20 20 20 20 70 72 69 6e 74 28 22 46 6f 6c        print("Fol
5b10: 64 65 72 20 6e 6f 74 20 66 6f 75 6e 64 3a 20 67  der not found: g
5b20: 63 5f 6c 61 6e 67 2f 22 2b 73 4c 61 6e 67 29 0a  c_lang/"+sLang).
5b30: 0a 20 20 20 20 6f 4e 6f 77 20 3d 20 64 61 74 65  .    oNow = date
5b40: 74 69 6d 65 2e 64 61 74 65 74 69 6d 65 2e 6e 6f  time.datetime.no
5b50: 77 28 29 0a 20 20 20 20 70 72 69 6e 74 28 22 3d  w().    print("=
5b60: 3d 3d 3d 3d 3d 3d 3d 3d 3d 3d 3d 3d 3d 20 4d 41  ============= MA
5b70: 4b 45 20 47 52 41 4d 4d 41 4c 45 43 54 45 20 5b  KE GRAMMALECTE [
5b80: 66 69 6e 69 73 68 65 64 5d 20 61 74 20 7b 30 2e  finished] at {0.
5b90: 68 6f 75 72 3a 3e 32 7d 20 68 20 7b 30 2e 6d 69  hour:>2} h {0.mi
5ba0: 6e 75 74 65 3a 3e 32 7d 20 6d 69 6e 20 7b 30 2e  nute:>2} min {0.
5bb0: 73 65 63 6f 6e 64 3a 3e 32 7d 20 73 20 3d 3d 3d  second:>2} s ===
5bc0: 3d 3d 3d 3d 3d 3d 3d 3d 3d 3d 3d 22 2e 66 6f 72  ===========".for
5bd0: 6d 61 74 28 6f 4e 6f 77 29 29 0a 0a 0a 69 66 20  mat(oNow))...if 
5be0: 5f 5f 6e 61 6d 65 5f 5f 20 3d 3d 20 27 5f 5f 6d  __name__ == '__m
5bf0: 61 69 6e 5f 5f 27 3a 0a 20 20 20 20 6d 61 69 6e  ain__':.    main
5c00: 28 29 0a                                         ().