nutools/lib/pyulib/migrate/tasks2/TiddlyWiki.py

941 lines
31 KiB
Python
Executable File

#!/usr/bin/env python
# -*- coding: utf-8 -*-
u"""%(scriptname)s: gérer un TiddlyWiki
USAGE
%(scriptname)s [options] addtext|addfile|remove|list|edit
OPTIONS
-c twrc
Charger le fichier de configuration twrc au lieu de la valeur par
défaut (~/.utools/twrc)
-f twfile.html
Utiliser twfile.html au lieu de chercher un fichier par défaut dans le
répertoire courant. Les noms considérés par défaut sont TODO.html,
project_wiki.html et TiddlyWiki.html"""
__all__ = ('Tiddler', 'TiddlyWiki', 'TwCLI')
import os, sys, re
from os import path
from getopt import getopt
from time import localtime
from types import IntType, LongType, StringTypes
from xml.dom.minidom import parseString
from pyutools.config import ShConfigFile
from pyutools.dates import datef, TW_DATEF
from pyutools.iso8859 import quote_attr, quote_html, unquote_but_html
from pyutools import scriptdir, scriptname, dict, isnum, isstr, isseq
from pyutools import get_stdin_encoding, get_editor_encoding
from pyutools import ensure_unicode, uprint, enote, eerror, die, get_colored
from pyutools import edit_template
_marker = []
TW_PARAM_PATTERN = re.compile(
r'(?:' +
r'(?:"((?:(?:\\")|[^"])+)")|' + # "value"
r"(?:'((?:(?:\\')|[^'])+)')|" + # 'value'
r'(?:\[\[(.*?)\]\])|' + # [[space separated values]]
r'(?:(\{\{.*?\}\}))|' + # {{braced values}}
r'(?:([^"' + "'" + r'\s]\S*))|' + # value
r'(?:"")|' + # ""
r"(?:'')" + # ''
r')'
)
def twParseParams(s):
params = []
for a, b, c, d, e in TW_PARAM_PATTERN.findall(s):
value = a or b or c or d or e
if value: params.append(value)
return params
def twParseTags(s):
tags = {}
for tag in twParseParams(s):
tags[tag] = None
return tags.keys()
TW_BRACED_VALUE = re.compile(r'\{\{.*\}\}$')
TW_VALUE = re.compile(r'[^"' + "'" + r'\s]\S*$')
def twFormatTags(tags):
ss = []
for tag in tags:
if TW_BRACED_VALUE.match(tag): ss.append(tag)
elif TW_VALUE.match(tag): ss.append(tag)
else: ss.append("[[%s]]" % tag)
return " ".join(ss)
class Tiddler:
parent = None # Instance de TiddlyWiki parent de ce Tiddler
title = u''
modifier = u''
creation_date = None
modification_date = None
tags = None
attrs = None
changecount = 0
text = u''
modified = False
def __init__(self, element=None, parent=None):
self.creation_date = self.modification_date = datef(TW_DATEF)
self.tags = []
self.attrs = {}
if parent is not None:
self.parent = parent
if element is not None:
self._parseElement(element)
ATTRS = ['title', 'modifier', 'modification_date', 'tags', 'creation_date', 'changecount']
ATTRS1_MAP = {'tiddler': 'title', 'modified': 'modification_date'}
ATTRS1_REVMAP = {'title': 'tiddler', 'modification_date': 'modified', 'creation_date': None, 'changecount': None}
ATTRS2_MAP = {'modified': 'modification_date', 'created': 'creation_date'}
ATTRS2_REVMAP = {'modification_date': 'modified', 'creation_date': 'created'}
def __unquote1(self, s):
s = s.replace('\\n', '\n')
return s
def __quote1(self, s):
s = s.replace('\n', '\\n')
return s
def __parseElement1(self, div, attrs):
if attrs is not None:
for i in range(attrs.length):
name = div.attributes.item(i).name
value = div.attributes.item(i).value
name = self.ATTRS1_MAP.get(name, name)
if name == 'tags': # cas particulier
value = twParseTags(value)
if name in self.ATTRS: setattr(self, name, value)
else: self.attrs[name] = value
textNode = div.firstChild
if textNode is not None:
self.text = self.__unquote1(textNode.data)
def __formatElement1(self):
s = u'<div'
for name in self.ATTRS:
value = getattr(self, name)
name = self.ATTRS1_REVMAP.get(name, name)
if name is None: continue
if name == 'tags': value = twFormatTags(value)
s += ' %s="%s"' % (name, quote_attr(unicode(value)))
for name, value in self.attrs.items():
s += ' %s="%s"' % (name, quote_attr(unicode(value)))
s += '>'
s += quote_html(self.__quote1(self.text))
s += '</div>'
return s
def __parseElement2(self, div, attrs):
if attrs is not None:
for i in range(attrs.length):
name = attrs.item(i).name
value = div.attributes.item(i).value
name = self.ATTRS2_MAP.get(name, name)
if name == 'tags': # cas particulier
value = twParseTags(value)
if name in self.ATTRS: setattr(self, name, value)
else: self.attrs[name] = value
textNode = div.getElementsByTagName('pre')[0].firstChild
if textNode is not None:
self.text = textNode.data
def __formatElement2(self):
s = u'<div'
for name in self.ATTRS:
value = getattr(self, name)
name = self.ATTRS2_REVMAP.get(name, name)
if name is None: continue
if name == 'tags': value = twFormatTags(value)
s += ' %s="%s"' % (name, quote_attr(unicode(value)))
for name, value in self.attrs.items():
s += ' %s="%s"' % (name, quote_attr(unicode(value)))
s += '>\n<pre>'
s += quote_html(self.text)
s += '</pre>\n</div>'
return s
def _parseElement(self, div, version=None):
attrs = div.attributes
if version is None:
if attrs.getNamedItem('title') is not None: version = 2
else: version = 1
if self.parent is not None:
self.parent.set_version(version)
if version == 2: return self.__parseElement2(div, attrs)
elif version == 1: return self.__parseElement1(div, attrs)
def _formatElement(self, version=None):
if version is None and self.parent is not None:
version = self.parent.get_version()
if version == 2: return self.__formatElement2()
elif version == 1: return self.__formatElement1()
def is_modified(self):
return self.modified
def set_modified(self):
self.modification_date = datef(TW_DATEF)
self.changecount = int(self.changecount) + 1
self.modified = False
def get_changecount(self):
return self.changecount
def set_changecount(self, changecount):
if changecount != self.changecount:
self.changecount = int(changecount)
self.modified = True
def get_title(self):
return self.title
def set_title(self, title):
if title != self.title:
self.title = ensure_unicode(title)
self.modified = True
def get_modifier(self):
return self.modifier
def set_modifier(self, modifier):
if modifier != self.modifier:
self.modifier = modifier
self.modified = True
def get_creation_date(self):
return self.creation_date
def set_creation_date(self, creation_date):
if creation_date != self.creation_date:
self.creation_date = creation_date
self.modified = True
def get_modification_date(self):
return self.modification_date
def set_modification_date(self, modification_date):
if modification_date != self.modification_date:
self.modification_date = modification_date
self.modified = True
def get_tags(self):
return self.tags
def set_tags(self, tags):
if type(tags) in StringTypes: tags = twParseTags(tags)
if set(tags) != set(self.tags):
self.tags = tags
self.modified = True
def add_tag(self, tag):
if tag not in self.tags:
self.tags.append(tag)
self.modified = True
def remove_tag(self, tag):
if tag in self.tags:
self.tags.remove(tag)
self.modified = True
def get_attrs(self):
return self.attrs
def set_attrs(self, attrs):
if attrs != self.attrs:
self.attrs = attrs
self.modified = True
def get_text(self):
return self.text
def set_text(self, text):
if text != self.text:
self.text = ensure_unicode(text)
self.modified = True
def __repr__(self):#XXX
s = self.get_title()
if self.get_tags():
s += "[%s]" % ",".join(self.get_tags())
return s
class TiddlyWiki:
DEFAULT_NAMES = ('TODO.html', 'project_wiki.html', 'TiddlyWiki.html')
DEFAULT_NAME = DEFAULT_NAMES[1]
valid = False
file = pf = dirname = filename = None
version = 2
byname = None
tiddlers = None
def __init__(self, src=None, raise_exception=False, default_names=None):
self.byname = {}
self.tiddlers = []
if default_names is None:
default_names = self.DEFAULT_NAMES
if src is None:
for name in default_names:
if path.exists(name):
src = name
break
elif path.isdir(src):
dir = src
src = None
for name in default_names:
pf = path.join(dir, name)
if path.exists(pf):
src = pf
break
if src is None:
if raise_exception:
raise IOError("Impossible de trouver un TiddlyWiki par défaut")
self.__update_file(self.DEFAULT_NAME)
else:
self.__update_file(src)
self.load(raise_exception=raise_exception)
def __update_file(self, file):
self.file = file
self.pf = path.abspath(self.file)
self.dirname, self.filename = path.split(self.pf)
MAGIC_PATTERN = re.compile(r'<!--\nTiddlyWiki')
START_SAVE_AREA = '<div id="storeArea">'
END_SAVE_AREA = '<!--POST-STOREAREA-->'
START_DIV = '<div '
END_DIV = '</div>'
def __load_prefix_and_suffix(self, pf, raise_exception=True):
try:
inf = open(pf, 'rb')
try:
data = inf.read()
finally:
inf.close()
## Vérifier qu'il s'agit bien d'un tiddlywiki
if not self.MAGIC_PATTERN.search(data):
raise ValueError("Fichier de format incorrect: ce n'est pas un tiddlywiki: %s" % self.file)
## Vérifier la présence du storeArea
# début
pos = data.find(self.START_SAVE_AREA)
if pos == -1:
raise ValueError("%s: Impossible de trouver la zone de stockage" % self.file)
pos += len(self.START_SAVE_AREA)
self.prefix = data[:pos]
data = data[pos:]
# fin
pos = 0
while True:
poss = data.find(self.START_DIV, pos)
pose = data.find(self.END_DIV, pos)
if pose == -1:
raise ValueError("%s: erreur de format à %i" % (self.file, pos))
if poss != -1 and poss < pose:
# <div....</div>
pos = pose + len(self.END_DIV)
else:
# end_save_area
break
pos = data.find(self.END_DIV, pos)
if pos == -1:
raise ValueError("%s: Impossible de trouver la fin de la zone de stockage" % self.file)
self.suffix = data[pos:]
data = data[:pos]
return True, data
except:
if raise_exception: raise
return False, None
def load(self, file=None, raise_exception=True):
if file is not None: self.__update_file(file)
self.valid = False
data = self.__load_prefix_and_suffix(self.pf, raise_exception)[1]
# charger les données
self.valid = True
self.byname = {}
self.tiddlers = []
data = self.START_SAVE_AREA + data + self.END_DIV
data = unquote_but_html(data, "utf-8") # HACK: nécessaire car minidom
# ne supporte pas les entities. utf-8 est codé en dur parce qu'on sait que
# TiddlyWiki enregistre dans ce codec.
dom = parseString(data)
for node in dom.documentElement.getElementsByTagName('div'):
self.add(Tiddler(element=node, parent=self))
return True
def is_valid(self):
return self.valid
def save(self, file=None, templatefile=None, set_modified=True, raise_exception=True):
if templatefile is None and self.file is None:
templatefile = path.join(path.split(__file__)[0], 'empty.html')
if templatefile is None:
if not hasattr(self, 'prefix') or not hasattr(self, 'suffix'):
raise IOError("Etat inconsistant: il faut le préfixe et le suffixe")
else:
self.__load_prefix_and_suffix(templatefile, raise_exception)
if file is not None: self.__update_file(file)
tmppf = self.pf + '.tmp'
try:
outf = open(tmppf, 'wb')
try:
outf.write(self.prefix)
for tiddler in self.tiddlers:
if tiddler.is_modified() and set_modified:
tiddler.set_modified()
outf.write(tiddler._formatElement().encode("utf-8"))
outf.write("\n")
outf.write(self.suffix)
finally:
outf.close()
os.rename(tmppf, self.pf)
except:
if raise_exception: raise
def set_version(self, version):
self.version = version
def get_version(self):
return self.version
def __len__(self):
return len(self.tiddlers)
def has_key(self, title):
return self.byname.has_key(title)
def __getitem__(self, indexOrTitle, default=_marker):
if isnum(indexOrTitle):
return self.tiddlers[indexOrTitle]
else:
if default is _marker: return self.byname[indexOrTitle]
else: return self.byname.get(indexOrTitle, default)
get = __getitem__
def add(self, tiddler):
if not isinstance(tiddler, Tiddler):
raise ValueError("value doit être une instance de Tiddler")
title = tiddler.get_title()
if title in self.byname:
del self.tiddlers[self.byname[title]]
tiddler.parent = self
self.tiddlers.append(tiddler)
self.byname[title] = tiddler
def __delitem__(self, indexOrTitle):
if isnum(indexOrTitle):
tiddler = self.tiddlers[indexOrTitle]
index = indexOrTitle
else:
tiddler = self.byname[indexOrTitle]
index = self.tiddlers.index(tiddler)
del self.byname[tiddler.get_title()]
del self.tiddlers[index]
def __repr__(self):
return repr(map(lambda t: t.get_title(), self.tiddlers))
################################################################################
class TwrcFile(ShConfigFile):
TWRC = "twrc"
def __init__(self, file=None, raise_exception=True):
if file is None:
testdir = path.join(scriptdir, "test")
utoolsrcdir = path.join(path.expanduser("~"), ".utools")
if path.isdir(testdir): file = path.join(testdir, self.TWRC)
else: file = path.join(utoolsrcdir, self.TWRC)
raise_exception = False
ShConfigFile.__init__(self, file=file, raise_exception=raise_exception)
DEFAULT_NAMES = "default_names"
MODIFIER = "modifier"
def __p(self, p, refdir=None):
if refdir is not None:
if not path.isdir(refdir): refdir = path.split(refdir)[0]
p = path.normpath(path.expanduser(p))
if refdir is not None:
p = path.join(refdir, p)
return p
COMMA_PATTERN = re.compile(r'\s*,\s*')
def __vs(self, vs):
if isstr(vs): vs = self.COMMA_PATTERN.split(vs)
return tuple(vs)
def __csv(self, csv):
if isseq(csv): csv = ','.join(csv)
return ensure_unicode(csv)
def get_default_names(self):
if self.has_key(self.DEFAULT_NAMES): return self.__vs(self[self.DEFAULT_NAMES])
else: return TiddlyWiki.DEFAULT_NAMES
def set_default_names(self, default_names=None):
if default_names is None:
if self.has_key(self.DEFAULT_NAMES): del self[self.DEFAULT_NAMES]
else:
self[self.DEFAULT_NAMES] = self.__csv(default_names)
def get_modifier(self):
if self.has_key(self.MODIFIER): return self[self.MODIFIER]
else: return os.environ.get('USER', 'TiddlyWiki.py')
def set_modifier(self, modifier=None):
if modifier is None:
if self.has_key(self.MODIFIER): del self[self.MODIFIER]
else:
self[self.MODIFIER] = modifier
class TwCLI:
twrc = None
def __newTiddlyWiki(self, file=None):
return TiddlyWiki(file, default_names=self.twrc.get_default_names(), raise_exception=True)
twfile = None
def __twfile(self):
if self.twfile is None:
self.twfile = self.__newTiddlyWiki()
return self.twfile
def __init__(self, twrc=None):
if not isinstance(twrc, TwrcFile):
twrc = TwrcFile(twrc)
self.twrc = twrc
CONFOPT = 'c:f:'
CONFLOPT = ['config=', 'file=']
def is_global_option(self, opt, value):
if opt in ('-c', '--config'):
self.twrc = TwrcFile(value)
elif opt in ('-f', '--file'):
self.twfile = self.__newTiddlyWiki(value)
else:
return False
return True
def ADDTEXT(self,
title=None, text=None,
modifier=None,
set_tags=None, add_tags=None, remove_tags=None,
encoding=None,
argv=(), scriptname=None,
**kw):
u"""%(scriptname)s: Créer ou mettre à jour un tiddler
USAGE
%(scriptname)s [options] title
OPTIONS
-m text
Si le texte du tiddler est spécifié, on ne lance pas d'éditeur
-u modifier
Spécifier le nom de l'utilisateur qui fait la modification. Par défaut,
il s'agit de $USER
-t tag
tag: ajouter un tag, -tag: enlever un tag
-e encoding
Spécifier l'encoding du titre et du texte s'il sont spécifiés sur la
ligne de commande. Par défaut, on considère que les données sont
encodées en %(default_encoding)s"""
default_encoding = get_stdin_encoding()
opts, argv = getopt(argv,
self.CONFOPT + 'hm:u:t:e:',
self.CONFLOPT + ['help', 'text=', 'modifier=', 'tag=', 'encoding='])
for opt, value in opts:
if self.is_global_option(opt, value):
pass
elif opt in ('-h', '--help'):
uprint(self.LIST.__doc__ % locals())
sys.exit(0)
elif opt in ('-m', '--text'):
text = value
elif opt in ('-u', '--modifier'):
modifier = value
elif opt in ('-t', '--tag'):
if value.startswith('-'):
if remove_tags is None: remove_tags = []
remove_tags.append(value[1:])
else:
if value.startswith('+'): value = value[1:]
if add_tags is None: add_tags = []
add_tags.append(value)
elif opt in ('-e', '--encoding'):
encoding = value
if title is None:
if not argv:
raise ValueError("Il faut spécifier un titre pour le nouveau tiddler")
title = argv[0]
edit = False
if text is None:
text = ''
edit = True
if modifier is None:
modifier = self.twrc.get_modifier()
if encoding is None:
encoding = default_encoding
title = ensure_unicode(title, encoding)
text = ensure_unicode(text, encoding)
twfile = self.__twfile()
new_tiddler = False
tiddler = twfile.get(title, None)
if tiddler is None:
new_tiddler = True
tiddler = Tiddler()
twfile.add(tiddler)
tiddler.set_title(title)
tiddler.set_text(text)
tiddler.set_modifier(modifier)
if set_tags is not None:
tiddler.set_tags(set_tags)
if add_tags is not None:
for tag in add_tags:
tiddler.add_tag(tag)
if remove_tags is not None:
for tag in remove_tags:
tiddler.remove_tag(tag)
if tiddler.is_modified():
twfile.save()
if edit:
self.EDIT(tiddler=tiddler)
else:
if new_tiddler: enote(u"Ajout d'un nouveau tiddler '%s'" % title)
else: enote(u"Mise à jour du tiddler '%s'" % title)
def ADDFILE(self,
file=None, title=None,
modifier=None,
set_tags=None, add_tags=None, remove_tags=None,
encoding=None,
argv=(), scriptname=None,
**kw):
u"""%(scriptname)s: Créer ou mettre à jour un tiddler à partir d'un fichier
USAGE
%(scriptname)s [options] /path/to/file
OPTIONS
-n title
Spécifier le titre du tiddler. Par défaut, il s'agit du nom du fichier
-u modifier
Spécifier le nom de l'utilisateur qui fait la modification. Par défaut,
il s'agit de $USER
-t tag
Ajouter un tag
Si le fichier a l'extension .js, on ajoute automatiquement le tag
systemConfig, sauf si un tag est spécifié
-e encoding
Spécifier l'encoding du fichier. Par défaut, on lit en %(default_encoding)s"""
default_encoding = get_editor_encoding()
opts, argv = getopt(argv,
self.CONFOPT + 'hn:u:t:e:',
self.CONFLOPT + ['help', 'title=', 'modifier=', 'tag=', 'encoding='])
for opt, value in opts:
if self.is_global_option(opt, value):
pass
elif opt in ('-h', '--help'):
uprint(self.LIST.__doc__ % locals())
sys.exit(0)
elif opt in ('-n', '--title'):
title = value
elif opt in ('-u', '--modifier'):
modifier = value
elif opt in ('-t', '--tag'):
if value.startswith('-'):
if remove_tags is None: remove_tags = []
remove_tags.append(value[1:])
else:
if value.startswith('+'): value = value[1:]
if add_tags is None: add_tags = []
add_tags.append(value)
elif opt in ('-e', '--encoding'):
encoding = value
if file is None:
if not argv:
raise ValueError("Il faut spécifier un fichier à importer")
file = argv[0]
if not path.exists(file):
raise IOError("Fichier inexistant: %s" % file)
if title is None:
title = file
if modifier is None:
modifier = os.environ.get('USER', 'TiddlyWiki.py')
if path.splitext(file)[1] == '.js':
if set_tags is not None:
set_tags.append('systemConfig')
else:
if add_tags is None: add_tags = []
add_tags.append('systemConfig')
if encoding is None:
encoding = defaut_encoding
inf = open(file, 'rb')
try:
text = ensure_unicode(inf.read(), encoding)
finally:
inf.close()
twfile = self.__twfile()
new_tiddler = False
tiddler = twfile.get(title, None)
if tiddler is None:
new_tiddler = True
tiddler = Tiddler()
twfile.add(tiddler)
tiddler.set_title(title)
tiddler.set_modifier(modifier)
if set_tags is not None:
tiddler.set_tags(set_tags)
if add_tags is not None:
for tag in add_tags:
tiddler.add_tag(tag)
if remove_tags is not None:
for tag in remove_tags:
tiddler.remove_tag(tag)
tiddler.set_text(text)
if tiddler.is_modified():
twfile.save()
if new_tiddler: enote(u"Ajout d'un nouveau tiddler '%s'" % title)
else: enote(u"Mise à jour du tiddler '%s'" % title)
def REMOVE(self,
title=None,
argv=(), scriptname=None,
**kw):
u"""%(scriptname)s: Supprimer un tiddler
USAGE
%(scriptname)s title"""
opts, argv = getopt(argv,
self.CONFOPT + 'hn:',
self.CONFLOPT + ['help', 'title='])
for opt, value in opts:
if self.is_global_option(opt, value):
pass
elif opt in ('-h', '--help'):
uprint(self.LIST.__doc__ % locals())
sys.exit(0)
elif opt in ('-n', '--title'):
title = value
if title is None:
if not argv:
raise ValueError("Il faut spécifier le tiddler à supprimer")
title = argv[0]
twfile = self.__twfile()
if twfile.has_key(title):
del twfile[title]
twfile.save()
enote(u"Suppression du tiddler '%s'" % title)
def LIST(self,
showtext=False,
argv=(), scriptname=None,
**kw):
u"""%(scriptname)s: Lister les tiddlers
USAGE
%(scriptname)s
OPTIONS
-l Afficher aussi le contenu des tiddlers"""
opts, argv = getopt(argv,
self.CONFOPT + 'hl',
self.CONFLOPT + ['help', 'show-text'])
for opt, value in opts:
if self.is_global_option(opt, value):
pass
elif opt in ('-h', '--help'):
uprint(self.LIST.__doc__ % locals())
sys.exit(0)
elif opt in ('-l', '--show-text'):
showtext = True
twfile = self.__twfile()
if showtext:
for tiddler in twfile:
title = get_colored(u'>>> ' + tiddler.get_title(), 'b')
if tiddler.get_tags():
title += " [%s]" % ', '.join(map(lambda t: get_colored(tiddler, 'y'), tiddler.get_tags()))
uprint(title)
text = tiddler.get_text()
if text: uprint(text)
else:
for tiddler in twfile:
uprint(tiddler.get_title())
EDIT_TEMPLATE = u"""
EDIT: ----------------------------------------------------------------
EDIT: Saisissez ou modifiez le titre et le corps du tiddler.
EDIT:
EDIT: - Les lignes commencant par 'EDIT:' seront supprimées automatiquement
EDIT: - La ligne tags: peut être modifiée si nécessaire.
EDIT:
EDIT: ----------------------------------------------------------------"""
TAGS_PATTERN = re.compile(r'##\s*tags:\s*')
def __nblines(self, s):
lines = s.split("\n")
nblines = len(lines)
if not lines[-1]: nblines -= 1
return nblines
def EDIT(self,
title=None,
tiddler=None,
argv=(), scriptname=None,
**kw):
u"""%(scriptname)s: Editer un tiddler
USAGE
%(scriptname)s title"""
opts, argv = getopt(argv,
self.CONFOPT + 'h',
self.CONFLOPT + ['help'])
for opt, value in opts:
if self.is_global_option(opt, value):
pass
elif opt in ('-h', '--help'):
uprint(self.LIST.__doc__ % locals())
sys.exit(0)
twfile = self.__twfile()
if tiddler is None:
if title is None:
if not argv:
raise ValueError("Il faut spécifier le tiddler à éditer")
title = argv[0]
tiddler = twfile.get(title, None)
if tiddler is None:
raise ValueError("Tiddler non trouvé: %s" % title)
template = u""
template += u"## tags: %s\n" % twFormatTags(tiddler.get_tags())
template += u"\n"
title = tiddler.get_title()
template += u"%s\n" % title
setline = self.__nblines(template)
setcol = len(title)
text = tiddler.get_text()
if text: template += u"\n%s\n" % text
template += self.EDIT_TEMPLATE
lines = edit_template(template, 'EDIT:', setline, setcol).split('\n')
new_tags = []
parsing_tags = True
skip_empty = True
text = []
for line in lines:
if skip_empty and not line: continue
if parsing_tags:
mot = self.TAGS_PATTERN.match(line)
if mot is not None:
new_tags.extend(twParseTags(line[mot.end():]))
continue
else:
parsing_tags = False
skip_empty = False
text.append(line)
text = "\n".join(text)
pos = text.find('\n\n')
if pos == -1:
title = text.replace('\n', ' ')
text = u''
else:
title = text[:pos].replace('\n', ' ')
text = text[pos + 2:]
tiddler.set_tags(new_tags)
tiddler.set_title(title)
tiddler.set_text(text)
if tiddler.is_modified():
twfile.save()
enote(u"Mise à jour du tiddler '%s'" % title)
################################################################################
if __name__ == '__main__':
debug = False
action = None
argv = sys.argv[1:]
twCLI = TwCLI()
# Essayer de determiner l'action avec le nom du script
if scriptname in ('twa', ):
action = 'addtext'
elif scriptname in ('twf', ):
action = 'addfile'
elif scriptname in ('twl', 'twll',):
if scriptname == 'twll': argv.insert(0, '-l')
action = 'list'
elif scriptname in ('twe', ):
action = 'edit'
if action is None:
opts, argv = getopt(argv,
TwCLI.CONFOPT + 'hD',
TwCLI.CONFLOPT + ['help', 'debug'])
for opt, value in opts:
if opt in ('-h', '--help'):
uprint(__doc__ % dict(scriptname=scriptname))
sys.exit(0)
elif twCLI.is_global_option(opt, value):
pass
elif opt in ('-D', '--debug'):
debug = True
if not argv:
uprint(__doc__ % dict(scriptname=scriptname))
sys.exit(0)
action, argv = argv[0], argv[1:]
if action in ('addtext', 'add', 'a'):
action = 'addtext'
elif action in ('addfile', 'file', 'f'):
action = 'addfile'
elif action in ('remove', 'r'):
action = 'remove'
elif action in ('list', 'l', 'll'):
if action == 'll': argv.insert(0, '-l')
action = 'list'
elif action in ('edit', 'e'):
action = 'edit'
else:
eerror("Action inconnue: %s" % action)
sys.exit(1)
if scriptname in ('TiddlyWiki.py', 'tw'):
# pour l'affichage de l'aide
scriptname = '%s %s' % (scriptname, action)
try:
apply(getattr(twCLI, action.upper()), (), {'argv': argv, 'scriptname': scriptname})
except Exception, e:
if debug:
eerror(e[0])
import traceback
traceback.print_exc()
else:
die(e[0])