changeset 65:5e5feacb730d

abandon regexp, work with lisparser output
author Henry S. Thompson <ht@inf.ed.ac.uk>
date Thu, 14 Dec 2023 16:43:54 +0000
parents fff2fa031ed7
children 53c37a02d471
files repair.py
diffstat 1 files changed, 80 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/repair.py	Thu Dec 14 11:43:44 2023 +0000
+++ b/repair.py	Thu Dec 14 16:43:54 2023 +0000
@@ -1,31 +1,49 @@
+#!/usr/bin/python3
+import sys
+
 import lisparser
 
 def readAlist(fn):
   with open(fn,'r') as f:
     sline = f.readline()
-    alines = [l for l in f if (L:=l).startswith("(")]
-  return sline, alist(alines), L
+    alines = (l for l in f if (L:=l).startswith("("))
+    return sline, alist(alines), L
 
+# alist fields are: group, rank, read, [marks, [method, [params]]]
+#                   string  int [list]  [plist]  expr    plist                                                     
 def alist(lines):
   res = {}
   for l in lines:
     ll = lisparser.get_ast(lisparser.normalize_str(l))[0]
     k = ll.pop(0)
-    n = ll.pop(0)
-    t = ll.pop(0)
-    if ll:
-      pp = ll.pop(0)
-      if pp[0] == '(':
-        pp = dict((a[0],a[1:]) for a in pp)
-      # Otherwise only "nil", I think, so pass through
-    else:
-      pp = None
-    res[eval(k)]=(n, t, pp, ll)
+    n = int(ll.pop(0))
+    res[eval(k)]=[n]+al2p(ll)
   return res
 
-# alist fields are: group, rank, read, marks, method, params
-                                                    
-def p2l(pl, f, top = False):
+def al2p(ll):
+  '''handle read (list or nil), maybe marks (plist or nil), usually method,
+     maybe params (plist)'''
+  res=[ll.pop(0)] # read
+  if ll:
+    marks = ll.pop(0)
+    if marks != 'nil':
+      marks = dict((e[0],e[1:]) for e in marks)
+    res.append(marks)
+  else:
+    return res
+  if ll:
+    res.append(ll.pop(0)) # method
+  else:
+    return res
+  if ll:
+    res.append(dict((e[0],e[1:]) for e in ll.pop(0))) # params
+  else:
+    return res
+  if ll:
+    raise ValueError("too many args: %s"%ll)
+  return res
+    
+def p2l(pl, f):
   if isinstance(pl,list) or isinstance(pl,tuple):
     if len(pl) == 0:
       f.write('nil')
@@ -41,49 +59,33 @@
           space = True
       f.write(')')
   elif isinstance(pl,dict):
-    if top:
-      f.write("(setq gnus-newsrc-alist '(\n")
+    f.write('(')
     space = False
     for k, v in pl.items():
       if space:
-        f.write('%s('%('\n' if top else ' '))
-      else:
-        f.write('(' if top else '((')
-        space = True
-      if top:
-        f.write('"%s"'%k)
-        for e in v[:3]: # v is [n, t, pp, ll], pp may be None
-          if e:
-            f.write(' ')
-            p2l(e,f)
-        # ll may be empty
-        for e in v[3]:
-          if e:
-            f.write(' ')
-            p2l(e,f)
+        f.write(' (')
       else:
-        f.write(k)
-        for e in v:
-          f.write(' ')
-          p2l(e,f)
-      f.write(')')
-    if top:
-      f.write('\n))\n')
-    else:
+        f.write('(')
+        space = True
+      f.write(k)
+      for e in v:
+        f.write(' ')
+        p2l(e,f)
       f.write(')')
-  elif isinstance(pl,str):
-    if pl in ['.','nil']:
-      f.write(pl)
-    else:
-      try:
-        int(pl)
-        f.write(pl)
-      except ValueError:
-        f.write(pl)
+    f.write(')')
+#   elif isinstance(pl,str):
+#     if pl in ['.','nil']:
+#       f.write(pl)
+#     else:
+#       try:
+#         int(pl)
+#         f.write(pl)
+#       except ValueError:
+#         f.write(pl)
   else:
     f.write(pl)
 
-def merge(gnus, mail):
+def merge(gnus, mail, out):
   '''
    rank, read, marks, method, params
    
@@ -96,12 +98,32 @@
            if mail is nil, use gnus
            otherwise use mail
    marks: merge unseen keys, unequal values for same key prefer gnus
-          EXCEPT bogus, w3c-ac-forum, handle by hand
+          EXCEPT bogus, w3c-ac-forum, handle by hand DONE
    method: change "ht" to "nnml+ht", flag anything else
-           FIX group-2002-07 in gnus by hand
-   params: TBD
+           FIX group-2002-07 in gnus by hand DONE
+   params: merge by keys
+''' # '
+  global g, m
+  g1, g, g2 = readAlist(gnus)
+  _, m, _ = readAlist(mail)
+  with open(out, "w") as outf:
+    outf.write(g1)
+    for k, v in g.items():
+      if k in m:
+        return
+        res = mergeOne(v, m[k])
+      else:
+        res = v
+      outf.write('("%s" '%k)
+      outf.write(str(res[0])) # rank
+      for v in res[1:]:
+        outf.write(' ')
+        p2l(v,outf)
+      outf.write(')\n')
+    outf.write(g2)
 
-
+def stale():
+  '''
 
  Comparison tool:
 
@@ -116,3 +138,7 @@
  fgrep -hf shared {gnus,mail}/alist.fixed | sed 's/ \([0-9]\) '"$P1 $P2 / \1     \2      \5      /;s/\(.*${T}.*${T}.*${T}\)$MA $P2/\1\2${T}\4/"
    paste <(cat shared) <(fgrep -f shared mail/alist.fixed | sed 's/ \([0-9]\) '"$P $P/ \1  \2      \5      /g" | cut -f 3)  <(fgrep -f shared gnus/alist.fixed | sed 's/ \([0-9]\) '"$P $P/ \1     \2      \5      /g" | cut -f 3) | { IFS='       ' ; while read gn g m; do if [ "$g" != "$m" ]; then printf "=----%s------\n%s\n%s\n" "$gn" "$g" "$m"; fi; done ; } | less
 '''
+
+if __name__ == '__main__':
+  merge(*sys.argv[1:])
+