From 4593ad8f8e3849b901f6f04d1b4da6690bab2b29 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 12 Apr 2017 06:14:09 +0400 Subject: [PATCH] ajout de tailor.py: affichage d'un fichier en mettant en surbrillance certains patterns --- tailor.py | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100755 tailor.py diff --git a/tailor.py b/tailor.py new file mode 100755 index 0000000..c3249fd --- /dev/null +++ b/tailor.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python +# -*- coding: utf-8 mode: python -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 + +u"""Afficher des lignes en mettant en surbrillance certains patterns""" + +import sys, subprocess, re +from collections import OrderedDict + +def bluef(line, *ignored): return '\x1B[34m%s\x1B[0m' % line +def greenf(line, *ignored): return '\x1B[32m%s\x1B[0m' % line +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), + ('yellow', yellowf), + ('red', redf), + ('none', nonef), +]) +FORMAT_ALIASES = { + 'b': 'blue', + 'g': 'green', + 'y': 'yellow', + 'r': 'red', + '': 'none', +} + +def strip_nl(s): + if s is None: return None + elif s.endswith("\r\n"): s = s[:-2] + elif s.endswith("\n"): s = s[:-1] + elif s.endswith("\r"): s = s[:-1] + return s + +def run_tailor(inputfile=None, patterns=None): + if inputfile is None: + def next_line(): + while True: + try: line = sys.stdin.readline() + except: break + if line == '': break + yield line + else: + def next_line(): + p = subprocess.Popen( + ['tail', '-f', inputfile], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + while True: + try: line = p.stdout.readline() + except: break + if line == '': break + yield line + if patterns is None: patterns = DEFAULT_PATTERNS + + for line in next_line(): + line = nonef(strip_nl(line)) + func = False + mo = None + for p, f in patterns.items(): + if p is None: + func = f + mo = None + break + mo = re.search(p, line) + if mo is not None: + func = f + break + if func is not False: + line = func(line, mo) + sys.stdout.write(line) + sys.stdout.write('\n') + +if __name__ == '__main__': + from argparse import ArgumentParser, RawTextHelpFormatter + AP = ArgumentParser( + formatter_class=RawTextHelpFormatter, + usage=u"%(prog)s [-f INPUTFILE]", + description=__doc__, + ) + AP.set_defaults(inputfile=None, patterns=None, defaults=True) + AP.add_argument('-f', '--follow', dest='inputfile', + help=u"Spécifier un fichier dont il faut suivre le contenu") + AP.add_argument('-e', '--pattern', action='append', dest='patterns', metavar='PATTERN:FORMAT', + help=u"""\ +Ajouter une spécification de pattern et le format dans lequel il doit être affiché +Les formats valides sont: %s +Le format par défaut est red""" % ', '.join(FORMATS.keys())) + AP.add_argument('-z', '--no-defaults', action='store_const', dest='defaults', const=False, + help=u"Ne pas ajouter les patterns par défaut") + o = AP.parse_args() + + if o.patterns is None: + patterns = DEFAULT_PATTERNS + else: + patterns = OrderedDict() + for pf in o.patterns: + mo = re.match('(.*):([a-zA-Z]*)$', pf) + if mo is not None: + p = mo.group(1) + of = mo.group(2) + else: + p = pf + of = 'red' + f = of.lower() + f = FORMAT_ALIASES.get(f, f) + if f not in FORMATS: + raise ValueError("%s: format invalide" % of) + patterns[p] = FORMATS[f] + if o.defaults: patterns.update(DEFAULT_PATTERNS) + + run_tailor(o.inputfile, patterns)