#!/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])