#!/usr/bin/env python2
# -*- coding: utf-8 -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
"""%(name)s: Gestion d'un fichier tiddlywiki.html
USAGE
%(name)s [-f tiddlywiki.html] action [options]
"""
try: True, False
except NameError: True, False = 1, 0
import re, types
from os import path
from time import localtime
from iso8859 import quote_entity, unquote_entity
__all__ = ["ensure_unicode", "Tiddler", "TiddlyWiki", "list_tiddlers", "replace_tiddler", "delete_tiddler"]
# XXX à configurer
ARGS_ENCODING="latin-1"
######################################################################
# Classes et constantes de base
RE_TAG = re.compile(r'<([^ >]+)')
RE_ENDTAG = re.compile(r'([^ ]+)>')
RE_SOMETHING = re.compile(r'\S')
RE_ATTR1 = re.compile(r'([^= ]+)="([^"]*)"')
RE_ATTR2 = re.compile(r"([^= ]+)='([^']*)'")
def parseDiv(data):
attrs = {}
text = ''
# Parser
': raise ValueError("Attendu >")
data = data[1:]
# Texte
pos = data.find("<")
if pos == -1: raise ValueError("Impossible de trouver le tag de fin")
text = unquote_entity(data[:pos])
data = data[pos:]
# Tag fermant
if data[:6] != '
': raise ValueError("Attendu ")
data = data[6:]
return attrs, text, data
def ensure_unicode(data):
if data is None: return None
elif type(data) is types.UnicodeType: return data
else: return unicode(data, ARGS_ENCODING)
def quote_nl(text):
text = text.replace("\n", "\\n")
return text
def unquote_nl(text):
text = text.replace("\\n", "\n")
return text
def get_now():
"""Retourner la date actuelle dans le format attendu par le champ modified
"""
t = localtime()
return '%04i%02i%02i%02i%02i' % t[0:5]
class Tiddler:
def __init__(self, tiddler=None, text=None, tags=None, modifier=None, modified=None, line=None):
self.tiddler = ensure_unicode(tiddler)
self.text = ensure_unicode(text)
self.tags = ensure_unicode(tags)
self.modifier = ensure_unicode(modifier)
self.modified = ensure_unicode(modified)
if line is not None: parse(line)
def is_valid(self):
"""Retourner True si ce Tiddler est valide
"""
return self.tiddler is not None
def parse(self, line):
"""Charger un Tiddler depuis line, et retourner le reste de la chaine qui n'a pas été parsé
"""
attrs, text, line = parseDiv(ensure_unicode(line))
if text is not None:
self.tiddler = attrs["tiddler"]
self.modified = attrs["modified"]
self.modifier = attrs["modifier"]
self.tags = attrs["tags"]
self.text = unquote_nl(text)
return line
def to_line(self):
"""Retourner ce tiddler sous forme de ligne
"""
if not self.is_valid(): die("Il faut spécifier l'id du tiddler")
line = u''
line += quote_nl(quote_entity(self.text))
line += u'
'
return line
RE_SPACES = re.compile("\s+")
def tags_contains(self, tag):
return tag in self.RE_SPACES.split(self.tags)
class TiddlyWiki:
def __init__(self, twfile=None):
self.twfile = None
self.prefix = None
self.suffix = None
self.tsmap = None
self.tslist = None
if twfile is not None: self.load(twfile)
RE_MAGIC = re.compile(r'