diff --git a/tailor.py b/tailor.py index 4620f62..88c1d1a 100755 --- a/tailor.py +++ b/tailor.py @@ -12,12 +12,6 @@ def yellowf(line, *ignored): return '\x1B[33m%s\x1B[0m' % line def redf(line, *ignored): return '\x1B[31m%s\x1B[0m' % line def nonef(line, *ignored): return re.sub('\x1B\[.*?m', '', line) -DEFAULT_PATTERNS = OrderedDict([ - (r'(?i)error', redf), - (r'(?i)warn(ing)?', yellowf), - (r'(?i)info', bluef), - (None, nonef), -]) FORMATS = OrderedDict([ ('blue', bluef), ('green', greenf), @@ -33,6 +27,29 @@ FORMAT_ALIASES = { '': 'none', } +APACHE_PATTERNS = OrderedDict([ + (r'(?i)error', redf), + (r'(?i)warn(ing)?', yellowf), + (r'(?i)info', bluef), + (None, nonef), +]) +PHP_PATTERNS = OrderedDict([ + (r'(?i)php notice', redf), + (r'(?i)php warning', yellowf), + (None, nonef), +]) + +PRESETS = { + 'apache': ('/var/log/apache2/error.log', True, APACHE_PATTERNS), + 'php': ('/var/log/apache2/error.log', True, PHP_PATTERNS), +} +PRESET_ALIASES = { + 'a': 'apache', + 'p': 'php', +} + +DEFAULT_PATTERNS = APACHE_PATTERNS + def strip_nl(s): if s is None: return None elif s.endswith("\r\n"): s = s[:-2] @@ -118,37 +135,51 @@ if __name__ == '__main__': else: texts.extend(super(FancyHelpFormatter, self)._split_lines(line, width)) return texts + + pattern_vars = dict(formats=', '.join(FORMATS.keys())) + pattern_help = u"""\ +Ajouter une spécification de pattern et le format dans lequel il doit être affiché. +Le format par défaut est red. Les formats valides sont: +>>> %(formats)s +Les lignes qui ne correspondent à aucun pattern ne sont pas affichées.""" % pattern_vars + default_patterns = [u"%s:%s" % (p or '', f.__name__[:-1]) for (p, f) in DEFAULT_PATTERNS.items()] + no_defaults_vars = dict(default_patterns='\n'.join([u">>> %s" % pattern for pattern in default_patterns])) + no_defaults_help = u"""\ +Ne pas ajouter les patterns par défaut. Sans cette option, les patterns par défaut sont: +%(default_patterns)s""" % no_defaults_vars + follow_help = u"""Suivre le contenu du fichier spécifié""" + presets_help = u"""Utiliser un ensemble prédéfini de paramètres. +Si cette option est utilisée, les autres options sont ignorées sauf --pattern qui peut être utilisé pour insérer des motifs avant les motifs par défaut du préréglage. +>>>Les valeurs valides sont apache et php. +Ces deux préréglages ont en commun de suivre le fichier /var/log/apache2/error.log en mettant en surbrillance les lignes intéressantes.""" + inputfile_help = u"""\ +Fichier à afficher ou dont il faut suivre le contenu. +Si cet argument n'est pas spécifié, l'entrée standard est utilisée comme source""" + AP = ArgumentParser( usage=u"%(prog)s [-f] [INPUTFILE]", description=__doc__, formatter_class=FancyHelpFormatter, ) - AP.set_defaults(inputfile=None, follow=False, patterns=None, defaults=True) - pattern_help = u"""\ -Ajouter une spécification de pattern et le format dans lequel il doit être affiché. -Le format par défaut est red. Les formats valides sont: ->>> %(formats)s""" % { - 'formats': ', '.join(FORMATS.keys()), -} - AP.add_argument('-e', '--pattern', action='append', dest='patterns', metavar='PATTERN:FORMAT', - help=pattern_help) - default_patterns = [u"%s:%s" % (p or '', f.__name__[:-1]) for (p, f) in DEFAULT_PATTERNS.items()] - no_defaults_help = u"""\ -Ne pas ajouter les patterns par défaut. Sans cette option, les patterns par défaut sont: -%(default_patterns)s""" % { - 'default_patterns': '\n'.join([u">>> %s" % pattern for pattern in default_patterns]), -} - AP.add_argument('-z', '--no-defaults', action='store_false', dest='defaults', - help=no_defaults_help) - AP.add_argument('-f', '--follow', action='store_true', dest='follow', - help=u"Suivre le contenu du fichier spécifié") - AP.add_argument('inputfile', metavar='INPUTFILE', nargs='?', - help=u"Fichier qu'il faut afficher ou dont il faut suivre le contenu") + AP.set_defaults(inputfile=None, follow=False, patterns=None, defaults=True, presets=None) + AP.add_argument('-e', '--pattern', action='append', dest='patterns', metavar='PATTERN:FORMAT', help=pattern_help) + AP.add_argument('-z', '--no-defaults', action='store_false', dest='defaults', help=no_defaults_help) + AP.add_argument('-f', '--follow', action='store_true', dest='follow', help=follow_help) + AP.add_argument('-p', '--presets', action='store', dest='presets', help=presets_help) + AP.add_argument('inputfile', metavar='INPUTFILE', nargs='?', help=inputfile_help) o = AP.parse_args() - if o.patterns is None: - patterns = DEFAULT_PATTERNS + if o.presets is not None: + presets = PRESET_ALIASES.get(o.presets, o.presets) + if presets not in PRESETS: + raise ValueError("%s: argument invalide" % presets) + inputfile, follow, patterns = PRESETS.get(presets) else: + inputfile, follow, patterns = o.inputfile, o.follow, o.patterns + + if patterns is None: + patterns = DEFAULT_PATTERNS + elif o.patterns is not None: patterns = OrderedDict() for pf in o.patterns: mo = re.match('(.*):([a-zA-Z]*)$', pf) @@ -168,4 +199,4 @@ Ne pas ajouter les patterns par défaut. Sans cette option, les patterns par dé for p, f in DEFAULT_PATTERNS.items(): patterns.setdefault(p, f) - run_tailor(o.inputfile, o.follow, patterns) + run_tailor(inputfile, follow, patterns)