diff --git a/.gitignore b/.gitignore index 9839280..c2a9c3f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,162 @@ -*.pyc +## Python gitignore +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python build/ +develop-eggs/ dist/ -colout.egg-info/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +## Jetbrains +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# Editor-based Rest Client +.idea/httpRequests + +# SonarLint +.idea/sonarlint + +# CMake +cmake-build-*/ + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..b7997b5 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +language: python +python: + - "3.5" + - "3.6" + - "3.7" + - "3.8" + - "pypy3" +install: + - pip install . +script: + - colout --help + - echo heyoo | colout hey yellow diff --git a/MANIFEST.in b/MANIFEST.in index 04f196a..1aba38f 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1 @@ -include README.md include LICENSE diff --git a/README.md b/README.md index 187f828..10bde37 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,21 @@ -colout(1) -- Color Up Arbitrary Command Output -============================================== +colout — Color Up Arbitrary Command Output +========================================== -## SYNOPSIS +

+Colout logo +

-`colout` [-h] [-r RESOURCE] +## Synopsis -`colout` [-g] [-c] [-l min,max] [-a] [-t] [-T DIR] [-P DIR] [-d COLORMAP] [-s] [-e CHAR] [-E CHAR] [--debug] PATTERN [COLOR(S) [STYLE(S)]] +`colout [-h] [-r [RESOURCE]]` -## DESCRIPTION +`colout [-g] [-c] [-l min,max] [-a] [-t] [-T DIR] [-P DIR] [-d COLORMAP] [-s] [-e CHAR] [-E CHAR] [--debug] PATTERN [COLOR(S) [STYLE(S)]]` + +## Description `colout` read lines of text stream on the standard input and output characters matching a given regular expression *PATTERN* in given *COLOR* and *STYLE*. @@ -25,10 +33,12 @@ rainbow, random, Random, Spectrum, spectrum, scale, Scale, hash, Hash, none, an RGB hexadecimal triplet (`#11aaff`, for example) or any number between 0 and 255. Available styles are: normal, bold, faint, italic, underline, blink, -rapid\_blink, reverse, conceal or random (some styles may have no effect, depending +rapid_blink, reverse, conceal or random (some styles may have no effect, depending on your terminal). -In some case, you can indicate a foreground and a background color, by indicating boths colors separated by a period(for example: `red.blue`). You can also use this system to combine two styles (for example, for a bold style that also blinks: `bold.blink`). +In some case, you can indicate a foreground and a background color, by indicating both colors +separated by a period (for example: `red.blue`). You can also use this system to combine two styles +(for example, for a bold style that also blinks: `bold.blink`). `rainbow` will cycle over a the default colormap at each matching pattern. `Rainbow` will do the same over the default colormap for the 256-colors mode @@ -54,10 +64,10 @@ Before interpreting the matched string as a number, colout will remove any character not supposed to be used to write down numbers. This permits to apply this special color on a large group, while interpreting only its numerical part. -If the python3-pygments library is installed, you can use the name of a -syntax-coloring "lexer" as a color (for example: "Cpp", "ruby", "xml+django", etc.). +You can use the name of a syntax-coloring ["lexer"](http://pygments.org/docs/lexers/) +as a color (for example: "Cpp", "ruby", "xml+django", etc.). -If GIMP palettes files (\*.gpl) are available, you can also use their names as a +If GIMP palettes files (*.gpl) are available, you can also use their names as a colormap (see the `-P` switch below). Note that the RGB colors (either the hex triplets or the palettes's colors) will @@ -68,8 +78,7 @@ When not specified, a *COLOR* defaults to _red_ and a *STYLE* defaults to _bold_ `colout` comes with some predefined themes to rapidly color well-known outputs (see the `-t` switch below). -If the python3-pygments library is available, `colout` can be used as an interface -to it (see also the `-s` switch below). +`colout` can be used as an interface to pygments (see also the `--source` switch below). To have a list of all colors, styles, special colormaps, themes, palettes and lexers, use the `-r` switch (see below). @@ -77,37 +86,29 @@ use the `-r` switch (see below). `colout` is released under the GNU Public License v3. -## INSTALLATION +## Installation - sudo python3 setup.py install +The recomended method is using pip to install the package for the local user: -and then soft link `/usr/local/bin/colout` to your colout.py under your installation -directory, which is usually something like +```console +$ pip install --user colout +``` - /usr/local/lib/python3/dist-packages/colout-0.1-py3.egg/colout/colout.py +Another method is using [pipsi](https://github.com/mitsuhiko/pipsi) +(_pipsi is no longer maintained, _) +```console +$ pipsi install colout +``` +There is also a PPA for Ubuntu 16.04 (Xenial)/18.04 (Bionic) (@`0.6.1-3~dist7`, not actively maintained) -## OTHER INSTALLATION METHOD +```console +$ sudo add-apt-repository ppa:csaba-kertesz/random +$ sudo apt-get update +$ sudo apt-get/aptitude install colout +``` -Pypi (the Python Package Index) - - sudo pip install colout - -or - - sudo easy_install colout - -Ubuntu 13.04's ppa - - sudo add-apt-repository ppa:ciici123/colout - sudo apt-get update - sudo apt-get/aptitude install colout - -Gentoo - - sudo emerge colout - -## OPTIONS +## Options * `-h`, `--help`: Show a help message and exit @@ -119,8 +120,8 @@ Gentoo Use the given list of comma-separated colors as a colormap (cycle the colors at each match). * `-l min,max`, `--scale min,max`: - When using the 'scale' colormap, parse matches as decimal numbers (taking your locale into account) - or as arithmetic expression (like "1+2/0.9\*3") and apply the rainbow colormap linearly + When using the 'scale' colormap, parse matches as decimal numbers (taking your locale into + account) or as arithmetic expression (like "1+2/0.9*3") and apply the rainbow colormap linearly between the given min,max (0,100, by default). * `-a`, `--all`: @@ -131,10 +132,10 @@ Gentoo Interpret PATTERN as a predefined theme (perm, cmake, g++, etc.). * `-T DIR`, `--themes-dir DIR`: - Search for additional themes (colout\_\*.py files) in this directory. + Search for additional themes (colout_*.py files) in this directory. * `-P DIR`, `--palettes-dir DIR`: - Search for additional palettes (\*.gpl files) in this directory. + Search for additional palettes (*.gpl files) in this directory. * `-d COLORMAP`, `--default COLORMAP`: When using special colormaps (`random`, `scale` or `hash`), use this COLORMAP instead of the default one. @@ -144,10 +145,10 @@ Gentoo Also, external palettes are converted from RGB to 256-ANSI and will thus not work if you use them as default colormaps for a 8-colors mode special color. -* `-r TYPE(S)`, `--resources TYPE(S)`: +* `-r [TYPE(S)]`, `--resources [TYPE(S)]`: Print the names of available resources. Use a comma-separated list of resources names (styles, colors, special, themes, palettes, colormaps or lexers), - use 'all' to print everything. + use 'all' (or no argument) to print all resources. * `-s`, `--source`: Interpret PATTERN as source code readable by the Pygments library. If the first letter of PATTERN @@ -164,7 +165,7 @@ Gentoo Debug mode: print what's going on internally, if you want to check what features are available. -## REGULAR EXPRESSIONS +## Regular expressions A regular expression (or _regex_) is a pattern that describes a set of strings that matches it. @@ -174,15 +175,15 @@ that matches it. special characters that would be recognize by your shell. -## DEPENDENCIES +## Dependencies -Recommended packages: +Necessary Python modules: * `pygments` for the source code syntax coloring * `babel` for a locale-aware number parsing -## LIMITATIONS +## Limitations Don't use nested groups or colout will duplicate the corresponding input text with each matching colors. @@ -190,9 +191,9 @@ with each matching colors. Using a default colormap that is incompatible with the special colormap's mode (i.e. number of colors) will end badly. -Color pairs ("foreground.background") work in 8-colors mode for simple coloring, but may fail with `--colormap`. +Color pairs (`foreground.background`) work in 8-colors mode for simple coloring, but may fail with `--colormap`. -## EXAMPLES +## Examples ### Simple @@ -202,7 +203,7 @@ Color pairs ("foreground.background") work in 8-colors mode for simple coloring, * Color in bold violet home directories in _/etc/passwd_: `colout '/home/[a-z]+' 135 < /etc/passwd` -* Color in yellow user/groups id, in bold green name and in bold red home directories in _/etc/passwd_: +* Color in yellow user/groups id, in bold green name and in bold red home directories in `/etc/passwd`: `colout ':x:([0-9]+:[0-9]+):([^:]+).*(/home/[a-z]+)' yellow,green,red normal,bold < /etc/passwd` * Color in yellow file permissions with read rights for everyone: @@ -266,11 +267,13 @@ Color pairs ("foreground.background") work in 8-colors mode for simple coloring, The following bash function color the output of any command with the cmake and g++ themes: - function cm() - { - set -o pipefail - $@ 2>&1 | colout -t cmake | colout -t g++ - } +```bash +function cm() +{ + set -o pipefail + $@ 2>&1 | colout -t cmake | colout -t g++ +} +``` You then can use the `cm` alias as a prefix to your build command, for example: `cm make test` @@ -339,32 +342,36 @@ Take a look at the `example.gdbinit` file distributed with colout for more gdb c ### Themes You can easily add your own theme to colout. -A theme is basically a module with a function named `theme` that take the configuration context as an argument and -return back the (modified) context and a list of triplets. +A theme is basically a module with a function named `theme` that take the configuration context as +an argument and return back the (modified) context and a list of triplets. Each triplet figures the same arguments than those of the command line interface. - def theme(context): - return context,[ [regexp, colors, styles] ] +```python +def theme(context): + return context,[ [regexp, colors, styles] ] +``` -With the context dictionary at hand, you have access to the internal configuration of colout, you can thus change colormaps for -special keywords, the scale, even the available colors, styles or themes. +With the context dictionary at hand, you have access to the internal configuration of colout, you +can thus change colormaps for special keywords, the scale, even the available colors, styles or +themes. -See the cmake theme for how to modify an existing colormap if (and only if) the user didn't ask for an -alternative one. -See the ninja theme for how to extend an existing theme with more regexps and a different configuration. +See the cmake them for how to modify an existing colormap if (and only if) the user didn't ask for an alternative one. +See the ninja theme for how to extend an existing theme with more regexps and a different configuration. See the gcc theme for an example of how to use the localization of existing softwares to build translated regexp. ### Buffering -Note that when you use colout within real time streams (like `tail -f X | grep Y | colout Z`) of commands, -you may observe that the lines are printed by large chunks and not one by one, in real time. +Note that when you use colout within real time streams (like `tail -f X | grep Y | colout Z`) of +commands, you may observe that the lines are printed by large chunks and not one by one, in real +time. This is not due to colout but to the buffering behavior of your shell. + To fix that, use `stdbuf`, for example: `tail -f X | stdbuf -o0 grep Y | colout Z`. ## Authors -* nojhan : original idea, main developer, maintener. +* nojhan : original idea, main developer, maintainer. * Adrian Sadłocha * Alex Burka * Brian Foley @@ -387,3 +394,4 @@ To fix that, use `stdbuf`, for example: `tail -f X | stdbuf -o0 grep Y | colout * Piotr Staroszczyk * Scott Lawrence * Xu Di +* https://github.com/stdedos: maintainer. diff --git a/bin/colout b/bin/colout deleted file mode 100644 index 7702d17..0000000 --- a/bin/colout +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -# Copyright (c) 2013 Martin Ueding - -# Small launcher script for the main module. - -# Licence: GPL 3 - -set -e -set -u - -python3 -m colout.colout "$@" diff --git a/colout/colout.py b/colout/colout.py index 656adc7..2d51fac 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -20,6 +20,7 @@ import logging import argparse import importlib import functools +import babel.numbers as bn # set the SIGPIPE handler to kill the program instead of # ending in a write error when a broken pipe occurs @@ -30,8 +31,6 @@ signal.signal( signal.SIGPIPE, signal.SIG_DFL ) # Global variable(s) ############################################################################### -PY2 = sys.version_info.major == 2 - context = {} debug = False @@ -42,6 +41,8 @@ context["styles"] = { "reverse": 7, "conceal": 8 } +error_codes = {"UnknownColor": 1, "DuplicatedPalette": 2, "MixedModes": 3, "UnknownLexer": 4, "UnknownResource": 5} + # Available color names in 8-colors mode. eight_colors = ["black","red","green","yellow","blue","magenta","cyan","white"] # Given in that order, the ASCII code is the index. @@ -176,7 +177,7 @@ def parse_gimp_palette( filename ): palette = [] for line in lines: # skip lines with only a comment - if re.match("^\s*#.*$", line ): + if re.match(r"^\s*#.*$", line ): continue # decode the columns-ths codes. Generally [R G B] followed by a comment colors = [ int(c) for c in line.split()[:columns] ] @@ -248,13 +249,13 @@ def hex_to_rgb(h): def load_themes( themes_dir): global context logging.debug("search for themes in: %s" % themes_dir) - os.chdir( themes_dir ) sys.path.append( themes_dir ) # load available themes - for f in glob.iglob("colout_*.py"): - module = ".".join(f.split(".")[:-1]) # remove extension - name = "_".join(module.split("_")[1:]) # remove the prefix + for f in glob.iglob(os.path.join(themes_dir, "colout_*.py")): + basename = os.path.basename(f) # Remove path. + module = os.path.splitext(basename)[0] # Remove extension. + name = "_".join(module.split("_")[1:]) # Remove the 'colout_' prefix. if name in context["themes"]: raise DuplicatedTheme(name) logging.debug("load theme %s" % name) @@ -264,10 +265,9 @@ def load_themes( themes_dir): def load_palettes( palettes_dir, ignore_duplicates = True ): global context logging.debug("search for palettes in: %s" % palettes_dir) - os.chdir( palettes_dir ) # load available colormaps (GIMP palettes format) - for p in glob.iglob("*.gpl"): + for p in glob.iglob(os.path.join(palettes_dir, "*.gpl")): try: name,palette = parse_gimp_palette(p) except Exception as e: @@ -290,32 +290,41 @@ def load_lexers(): global context # load available pygments lexers lexers = [] + global get_lexer_by_name + from pygments.lexers import get_lexer_by_name + + global highlight + from pygments import highlight + + global Terminal256Formatter + from pygments.formatters import Terminal256Formatter + + global TerminalFormatter + from pygments.formatters import TerminalFormatter + + from pygments.lexers import get_all_lexers try: - global get_lexer_by_name - from pygments.lexers import get_lexer_by_name - - global highlight - from pygments import highlight - - global Terminal256Formatter - from pygments.formatters import Terminal256Formatter - - global TerminalFormatter - from pygments.formatters import TerminalFormatter - - from pygments.lexers import get_all_lexers - except ImportError: - logging.warning("the pygments module has not been found, syntax coloring is not available") - pass - else: for lexer in get_all_lexers(): - try: - lexers.append(lexer[1][0]) - except IndexError: + l = None + # If the tuple has one-word aliases + # (which are usually a better option than the long names + # for a command line argument). + if lexer[1]: + l = lexer[1][0] # Take the first one. + else: + assert(lexer[0]) + l = lexer[0] # Take the long name, which should alway exists. + if not l: logging.warning("cannot load lexer: %s" % lexer[1][0]) - pass - lexers.sort() - logging.debug("loaded %i lexers: %s" % (len(lexers), ", ".join(lexers))) + pass # Forget about this lexer. + else: + assert(" " not in l) # Should be very rare, but probably a source of bugs. + lexers.append(l) + except: + logging.warning("error while executing the pygment module, syntax coloring is not available") + + lexers.sort() + logging.debug("loaded %i lexers: %s" % (len(lexers), ", ".join(lexers))) context["lexers"] = lexers @@ -406,23 +415,11 @@ def color_scale( name, text ): nb = "".join([i for i in filter(allowed.__contains__, text)]) # interpret as decimal - # First, try with the babel module, if available - # if not, use python itself, - # if thoses fails, try to `eval` the string - # (this allow strings like "1/2+0.9*2") f = None try: - # babel is a specialized module - import babel.numbers as bn - try: - f = float(bn.parse_decimal(nb)) - except bn.NumberFormatError: - pass - except ImportError: - try: - f = float(nb) - except ValueError: - pass + f = float(bn.parse_decimal(nb)) + except bn.NumberFormatError: + pass if f is not None: # normalize with scale if it's a number f = (f - context["scale"][0]) / (context["scale"][1]-context["scale"][0]) @@ -666,20 +663,8 @@ def colorup(text, pattern, color="red", style="normal", on_groups=False, sep_lis in which case the different matching groups may be formatted differently. If there is less colors/styles than groups, the last format is used for the additional groups. - - >>> colorup("Fetchez la vache", "vache", "red", "bold") - 'Fetchez la \x1b[1;31mvache\x1b[0m' - >>> colorup("Faites chier la vache", "[Fv]a", "red", "bold") - '\x1b[1;31mFa\x1b[0mites chier la \x1b[1;31mva\x1b[0mche' - >>> colorup("Faites Chier la Vache", "[A-Z](\S+)\s", "red", "bold") - 'F\x1b[1;31maites\x1b[0m C\x1b[1;31mhier\x1b[0m la Vache' - >>> colorup("Faites Chier la Vache", "([A-Z])(\S+)\s", "red,green", "bold") - '\x1b[1;31mF\x1b[0m\x1b[1;32maites\x1b[0m \x1b[1;31mC\x1b[0m\x1b[1;32mhier\x1b[0m la Vache' - >>> colorup("Faites Chier la Vache", "([A-Z])(\S+)\s", "green") - '\x1b[0;32mF\x1b[0m\x1b[0;32maites\x1b[0m \x1b[0;32mC\x1b[0m\x1b[0;32mhier\x1b[0m la Vache' - >>> colorup("Faites Chier la Vache", "([A-Z])(\S+)\s", "blue", "bold,italic") - '\x1b[1;34mF\x1b[0m\x1b[3;34maites\x1b[0m \x1b[1;34mC\x1b[0m\x1b[3;34mhier\x1b[0m la Vache' """ + global context global debug @@ -754,9 +739,6 @@ def write(colored, stream = sys.stdout): """ Write "colored" on sys.stdout, then flush. """ - if PY2: # If Python 2.x: force unicode - if isinstance(colored, unicode): - colored = colored.encode('utf-8') try: stream.write(colored) stream.flush() @@ -827,11 +809,6 @@ def _args_parse(argv, usage=""): help="A regular expression") pygments_warn=" You can use a language name to activate syntax coloring (see `-r all` for a list)." - try: - import pygments - except ImportError: - pygments_warn=" (WARNING: python3-pygments is not available, \ - install it if you want to be able to use syntax coloring)" parser.add_argument("color", metavar="COLOR", type=str, nargs='?', default="red", @@ -851,12 +828,6 @@ def _args_parse(argv, usage=""): (cycle the colors at each match)") babel_warn=" (numbers will be parsed according to your locale)" - try: - # babel is a specialized module - import babel.numbers - except ImportError: - babel_warn=" (WARNING: python3-babel is not available, install it \ - if you want to be able to parse numbers according to your locale)" parser.add_argument("-l", "--scale", metavar="SCALE", help="When using the 'scale' colormap, parse matches as decimal numbers \ @@ -906,6 +877,10 @@ def _args_parse(argv, usage=""): parser.add_argument("--debug", action="store_true", help="Debug mode: print what's going on internally, useful if you want to check what features are available.") + # HACK: Mock up "--resources ALL" if just "--resources" on command line + if (len(sys.argv) == 2 and (sys.argv[1] in ["-r", "--resources"])): + sys.argv.append("ALL") + args = parser.parse_args() return args.pattern[0], args.color, args.style, args.groups, \ @@ -924,10 +899,8 @@ def write_all( as_all, stream_in, stream_out, function, *args ): map_write( stream_in, stream_out, function, *args ) -if __name__ == "__main__": - - error_codes = {"UnknownColor":1, "DuplicatedPalette":2, "MixedModes":3} - +def main(): + global context usage = "A regular expression based formatter that color up an arbitrary text stream." ##################### @@ -965,23 +938,17 @@ if __name__ == "__main__": # try additional directories if asked if palettes_dirs: for adir in palettes_dirs: - try: - os.chdir( adir ) - except OSError as e: - logging.warning("cannot read palettes directory %s, ignore it" % adir) - continue - else: + if os.path.isdir(adir): load_palettes( adir ) + else: + logging.warning("cannot read palettes directory %s, ignore it" % adir) if themes_dirs: for adir in themes_dirs: - try: - os.chdir( adir ) - except OSError as e: - logging.warning("cannot read themes directory %s, ignore it" % adir) - continue - else: + if os.path.isdir(adir): load_themes( adir ) + else: + logging.warning("cannot read themes directory %s, ignore it" % adir) except DuplicatedPalette as e: logging.error( "duplicated palette file name: %s" % e ) @@ -1006,33 +973,49 @@ if __name__ == "__main__": return ", ".join(sorted(l, key=lambda s: s.lower()+s)) # print("Available resources:") + resources_not_found = [] for res in asked: + resource_found = False + if "style" in res or "all" in res: print("STYLES: %s" % join_sort(context["styles"]) ) + resource_found = True if "color" in res or "all" in res: print("COLORS: %s" % join_sort(context["colors"]) ) + resource_found = True if "special" in res or "all" in res: print("SPECIAL: %s" % join_sort(["random", "Random", "scale", "Scale", "hash", "Hash", "colormap"]) ) + resource_found = True if "theme" in res or "all" in res: if len(context["themes"]) > 0: print("THEMES: %s" % join_sort(context["themes"].keys()) ) else: print("NO THEME") + resource_found = True if "colormap" in res or "all" in res: if len(context["colormaps"]) > 0: print("COLORMAPS: %s" % join_sort(context["colormaps"]) ) else: print("NO COLORMAPS") + resource_found = True if "lexer" in res or "all" in res: if len(context["lexers"]) > 0: print("SYNTAX COLORING: %s" % join_sort(context["lexers"]) ) else: print("NO SYNTAX COLORING (check that python3-pygments is installed)") + resource_found = True + + if not resource_found: + resources_not_found.append(res) + + if resources_not_found: + logging.error( "Unknown resources: %s" % ", ".join(resources_not_found) ) + sys.exit( error_codes["UnknownResource"] ) sys.exit(0) # not an error, we asked for help @@ -1072,7 +1055,9 @@ if __name__ == "__main__": # if pygments elif as_source: logging.debug("asked for lexer: %s" % pattern.lower()) - assert(pattern.lower() in context["lexers"]) + if pattern.lower() not in context["lexers"]: + logging.error("Lexer %r is not available. Run with \"--resources all\" to see the options.") + sys.exit(error_codes["UnknownLexer"]) lexer = get_lexer_by_name(pattern.lower()) # Python => 256 colors, python => 8 colors ask_256 = pattern[0].isupper() @@ -1105,3 +1090,6 @@ if __name__ == "__main__": + " Check the following 'color:mode' pairs: %s." % e ) sys.exit( error_codes["MixedModes"] ) + +if __name__ == "__main__": + main() diff --git a/colout/colout_catch2.py b/colout/colout_catch2.py new file mode 100644 index 0000000..e67d86a --- /dev/null +++ b/colout/colout_catch2.py @@ -0,0 +1,23 @@ +def theme(context): + + return context,[ + ["^ (Start)(.*): (.*):(.*)$", "yellow", "normal,normal,normal,bold"], # Test start. + # path file ext:line : + ["^(tests): (/.*?)/([^/:]+):([0-9]+): (.*)", "yellow,none,white,yellow,red", "bold,normal,bold,normal,bold"], + ["(`)(.*)('.*)", "red,Cpp,red", "bold,normal,bold"], + [r"^\.+$", "yellow", "bold"], + ["^=+$", "yellow", "bold"], + ["(/.*?)/([^/:]+):([0-9]+): (FAILED):", "white,white,yellow,red", "normal,bold,normal,bold"], + [r"(REQUIRE\(|CHECK\(|REQUIRE_THAT\()(.*)(\))$","yellow,Cpp,yellow","bold,normal,bold"], + # Hide uninteresting stuff: + ["[0-9]+/[0-9]+ Test.*","blue"], + ["^Filters:.*","blue"], + ["^Randomness seeded to:.*","blue"], + ["^tests is a Catch2.*","blue"], + ["^Run with.*", "blue"], + ["^~+$","blue"], + ["^-+$","blue"], + [r"^\s*(Scenario:|Given:|When:|Then:).*","blue"], + ["^(/.*?)/([^/:]+):([0-9]+)", "blue"], + ["^(test cases|assertions)(.*)", "blue"], + ] diff --git a/colout/colout_clang.py b/colout/colout_clang.py deleted file mode 120000 index 2df53b5..0000000 --- a/colout/colout_clang.py +++ /dev/null @@ -1 +0,0 @@ -colout_g++.py \ No newline at end of file diff --git a/colout/colout_clang.py b/colout/colout_clang.py new file mode 100644 index 0000000..a5525ef --- /dev/null +++ b/colout/colout_clang.py @@ -0,0 +1,85 @@ +#encoding: utf-8 + +def default_gettext( msg ): + return msg + +def theme(context): + import os + import gettext + import locale + + section="blue" + + # get g++ version + gv = os.popen("g++ -dumpversion").read().strip() + + # get the current translations of gcc + try: + t = gettext.translation("gcc-"+gv) + except IOError: + _ = default_gettext + else: + _ = t.gettext + # _("msg") will return the given message, translated + + # if the locale is unicode + enc = locale.getpreferredencoding() + if "UTF" in enc: + # gcc will use unicode quotes + qo = "[‘`]" + qc = "[’']" + else: + # rather than ascii ones + qo = "['`]" + qc = "'" + + return context,[ + # Command line + [ r"[/\s]([cg]\+\+-*[0-9]*\.*[0-9]*)", "white", "bold" ], + [ r"\s(\-D)(\s*[^\s]+)", "none,green", "normal,bold" ], + [ r"\s(-g)", "green", "normal" ], + [ r"\s-O[0-4]", "green", "normal" ], + [ r"\s-[Wf][^\s]*", "magenta", "normal" ], + [ r"\s-pedantic", "magenta", "normal" ], + [ r"\s(-I)(/*[^\s]+/)([^/\s]+)", "none,blue", "normal,normal,bold" ], + [ r"\s(-L)(/*[^\s]+/)([^/\s]+)", "none,cyan", "normal,normal,bold" ], + [ r"\s(-l)([^/\s]+)", "none,cyan", "normal,bold" ], + [ r"\s-[oc]", "red", "bold" ], + [ r"\s(-+std(?:lib)?)=?([^\s]+)", "red", "normal,bold" ], + + # Important messages + [ _("error: "), "red", "bold" ], + [ _("fatal error: "), "red", "bold" ], + [ _("warning: "), "magenta", "bold" ], + [ _("undefined reference to "), "red", "bold" ], + # [-Wflag] + [ r"\[-W.*\]", "magenta"], + + # Highlight message start: + # path file ext : line : col … + [ "(/.*?)/([^/:]+): (In .*)"+qo, + section, + "normal,normal,bold" ], + + [ "(/.*?)/([^/:]+): (At .*)", + section, + "normal,normal,bold" ], + + [ _("In file included from"), section ], + + # Highlight locations: + # path file ext : line : col … + [ "(/.*?)/([^/:]+):([0-9]+):*([0-9]*)(.*)", + "none,white,yellow,none,none", + "normal,normal,normal,normal" ], + + # source code in single quotes + [ qo+"(.*?)"+qc, "Cpp", "monokai" ], + + # source code after a "note: candidate are/is:" + [ _("note: ")+"((?!.*("+qo+"|"+qc+")).*)$", "Cpp", "monokai" ], + # [ _("note: ")+"(candidate:)(.*)$", "green,Cpp", "normal,monokai" ], + # after the code part, to avoid matching ANSI escape chars + [ _("note: "), "green", "normal" ] + ] + diff --git a/colout/colout_cmake.py b/colout/colout_cmake.py index 252fc2f..66ab5a8 100644 --- a/colout/colout_cmake.py +++ b/colout/colout_cmake.py @@ -25,8 +25,9 @@ def theme(context): [ "^-- Configuring incomplete, errors occurred!", "red" ], [ "^--.*", performing ], # Errors - [ "CMake Error:", "red" ], - [ "CMake Warning", "yellow" ], + [ "CMake Error", "red" ], + [ "CMake Warning", "magenta" ], + [ "CMake Deprecation Warning", "magenta" ], # Scan [ "^(Scanning dependencies of target)(.*)$", performing, "normal,bold" ], @@ -35,20 +36,20 @@ def theme(context): [ "^(Linking .* )(library|executable) (.*)$", untimed, "normal,normal,bold" ], # [percent] Creating something - [ "^\[\s*[0-9/]+%?\]\s(.*Creating.*)$", + [ r"^\[\s*[0-9/]+%?\]\s(.*Creating.*)$", performing, "normal" ], # [percent] Built - [ "^\[\s*[0-9/]+%?\]\s(Built target)(\s.*)$", + [ r"^\[\s*[0-9/]+%?\]\s(Built target)(\s.*)$", performed, "normal,bold" ], # [percent] Building - [ "^\[\s*[0-9/]+%?\]\s(Building \w* object)\s+(.*)(\.dir)(.*/)([-\w]+).c.*.o$", + [ r"^\[\s*[0-9/]+%?\]\s(Building \w* object)\s+(.*)(\.dir)(.*/)([-\w]+).c.*.o$", performing+","+performing+","+performing+",Hash,"+performing, "normal,normal,normal,normal,bold"], # [percent] Generating - [ "^\[\s*[0-9/]+%?\]\s(Generating)(\s+.*)$", + [ r"^\[\s*[0-9/]+%?\]\s(Generating)(\s+.*)$", performing, "normal,bold"], # make errors - [ "make\[[0-9]+\].*", "yellow"], - [ "(make: \*\*\* \[.+\] )(.* [0-9]+)", "red", "normal,bold"], + [ r"make\[[0-9]+\].*", "yellow"], + [ r"(make: \*\*\* \[.+\] )(.* [0-9]+)", "red", "normal,bold"], # progress percentage (make) - [ "^(\[\s*[0-9]+%\])","Scale" ] + [ r"^(\[\s*[0-9]+%\])","Scale" ] ] diff --git a/colout/colout_configure.py b/colout/colout_configure.py index 2f5e2b7..63e63a4 100644 --- a/colout/colout_configure.py +++ b/colout/colout_configure.py @@ -11,6 +11,6 @@ def theme(context): ["^(config.status:) (creating|linking)(.*)", "cyan,blue","normal,normal,bold"], ["^(config.status:) (executing )(.*)", "cyan,green","normal,normal,bold"], ["^(config.status:) (.*)(is unchanged)", "cyan,green","normal,normal,bold"], - ["^\s*(Build.*)(yes)$","green", "normal,bold"], - ["^\s*(Build.*)(no)$","yellow", "normal,bold"], + [r"^\s*(Build.*)(yes)$","green", "normal,bold"], + [r"^\s*(Build.*)(no)$","yellow", "normal,bold"], ] diff --git a/colout/colout_ctest.py b/colout/colout_ctest.py index ba7e56e..f2dd372 100644 --- a/colout/colout_ctest.py +++ b/colout/colout_ctest.py @@ -2,6 +2,7 @@ def theme(context): # CTest theme: passed="green" + notrun="yellow" notpassed="red" # If the user do not ask for his own colormap @@ -12,6 +13,7 @@ def theme(context): return context,[ # Passed - [ "^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+\s+(Passed)", "blue,"+passed], - [ "^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+(\*{3}.*)\s+.*", "blue,"+notpassed] + [ r"^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+\s+(Passed)", "blue,"+passed], + [ r"^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+(\*{3}Not Run.*)\s+.*", "blue,"+notrun], + [ r"^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+(.*\*{3}.*)\s+.*", "blue,"+notpassed], ] diff --git a/colout/colout_django.py b/colout/colout_django.py new file mode 100644 index 0000000..fcacc00 --- /dev/null +++ b/colout/colout_django.py @@ -0,0 +1,36 @@ + +def theme(context): + return context,[ + # Waiting + ["^Waiting for .*$", "red", "bold"], + [".*Sending.*", "green"], + # Watches + [r"^(Watching) (\S*) (.*)", "yellow", "bold,bold,normal"], + [".*reloading.$","yellow"], + # File from python/lib + [r"^(File) (/.*/lib/python[^/]*/site-packages/)([^/]*)\S* (first seen) (with mtime [0-9]*.*)$", + "blue,blue,white,blue,blue", "bold,normal,bold,bold,normal"], + # File from app (last 3 name highlighted) + [r"^(File) (/\S*/)(\S*/\S*/)(\S*) (first seen) (with mtime [0-9]*.*)$", + "magenta,magenta,white,white,magenta,magenta", "bold,normal,normal,bold,bold,normal"], + # SQL + ["(.*)(SELECT)(.*)(FROM)(.*)", + "green", "normal,bold,normal,bold,normal"], + ["(.*)(SELECT)(.*)(FROM)(.*)(WHERE)(.*)", + "green", "normal,bold,normal,bold,normal,bold,normal"], + # HTTP + [r"\"(GET) (\S*) (HTTP\S*)\" ([0-9]+) (.*)$", + "green,white,green,green,green", "bold,bold,normal,bold,normal"], + # Errors + ["(Exception) (while .*) '(.*)' (in) (.*) '(.*)'", "red,red,white,red,red,white", "bold,normal,bold,bold,normal,bold"], + ["(.*Error): (.*) '(.*)'", "red,red,white", "bold,normal,bold"], + [r"(django[^:\s]*)\.([^.:\s]*): (.*)", "red","normal,bold,normal"], + ["Traceback.*:","yellow"], + ["During handling.*","yellow"], + # File, line, in + [ + r"^\s{2}(File \")(/*.*?/)*([^/:]+)(\", line) ([0-9]+)(, in) (.*)$", + "blue, none, white,blue, yellow,blue", + "normal,normal,bold, normal,normal,bold" + ], + ] diff --git a/colout/colout_g++.py b/colout/colout_g++.py index c4abe03..a5525ef 100644 --- a/colout/colout_g++.py +++ b/colout/colout_g++.py @@ -35,17 +35,17 @@ def theme(context): return context,[ # Command line - [ "[/\s]([cg]\+\+-*[0-9]*\.*[0-9]*)", "white", "bold" ], - [ "\s(\-D)(\s*[^\s]+)", "none,green", "normal,bold" ], - [ "\s(-g)", "green", "normal" ], - [ "\s-O[0-4]", "green", "normal" ], - [ "\s-[Wf][^\s]*", "magenta", "normal" ], - [ "\s-pedantic", "magenta", "normal" ], - [ "\s(-I)(/*[^\s]+/)([^/\s]+)", "none,blue", "normal,normal,bold" ], - [ "\s(-L)(/*[^\s]+/)([^/\s]+)", "none,cyan", "normal,normal,bold" ], - [ "\s(-l)([^/\s]+)", "none,cyan", "normal,bold" ], - [ "\s-[oc]", "red", "bold" ], - [ "\s(-+std(?:lib)?)=?([^\s]+)", "red", "normal,bold" ], + [ r"[/\s]([cg]\+\+-*[0-9]*\.*[0-9]*)", "white", "bold" ], + [ r"\s(\-D)(\s*[^\s]+)", "none,green", "normal,bold" ], + [ r"\s(-g)", "green", "normal" ], + [ r"\s-O[0-4]", "green", "normal" ], + [ r"\s-[Wf][^\s]*", "magenta", "normal" ], + [ r"\s-pedantic", "magenta", "normal" ], + [ r"\s(-I)(/*[^\s]+/)([^/\s]+)", "none,blue", "normal,normal,bold" ], + [ r"\s(-L)(/*[^\s]+/)([^/\s]+)", "none,cyan", "normal,normal,bold" ], + [ r"\s(-l)([^/\s]+)", "none,cyan", "normal,bold" ], + [ r"\s-[oc]", "red", "bold" ], + [ r"\s(-+std(?:lib)?)=?([^\s]+)", "red", "normal,bold" ], # Important messages [ _("error: "), "red", "bold" ], @@ -53,7 +53,7 @@ def theme(context): [ _("warning: "), "magenta", "bold" ], [ _("undefined reference to "), "red", "bold" ], # [-Wflag] - [ "\[-W.*\]", "magenta"], + [ r"\[-W.*\]", "magenta"], # Highlight message start: # path file ext : line : col … diff --git a/colout/colout_javac.py b/colout/colout_javac.py index 0acaba0..92e5a2c 100644 --- a/colout/colout_javac.py +++ b/colout/colout_javac.py @@ -3,13 +3,13 @@ def theme(context): style="monokai" return context,[ - [ "^(.*\.java):([0-9]+):\s*(warning:.*)$", "white,yellow,magenta", "normal,normal,bold" ], - [ "^(.*\.java):([0-9]+):(.*)$", "white,yellow,red", "normal,normal,bold" ], - [ "^(symbol|location)\s*:\s*(.*)$", "blue,Java", "bold,"+style ], - [ "^(found)\s*:\s*(.*)", "red,Java", "bold,"+style ], - [ "^(required)\s*:\s*(.*)", "green,Java", "bold,"+style ], - [ "^\s*\^$", "cyan", "bold" ], - [ "^\s+.*$", "Java", style ], + [ r"^(.*\.java):([0-9]+):\s*(warning:.*)$", "white,yellow,magenta", "normal,normal,bold" ], + [ r"^(.*\.java):([0-9]+):(.*)$", "white,yellow,red", "normal,normal,bold" ], + [ r"^(symbol|location)\s*:\s*(.*)$", "blue,Java", "bold,"+style ], + [ r"^(found)\s*:\s*(.*)", "red,Java", "bold,"+style ], + [ r"^(required)\s*:\s*(.*)", "green,Java", "bold,"+style ], + [ r"^\s*\^$", "cyan", "bold" ], + [ r"^\s+.*$", "Java", style ], [ "[0-9]+ error[s]*", "red", "bold" ], [ "[0-9]+ warning[s]*", "magenta", "bold" ], ] diff --git a/colout/colout_json.py b/colout/colout_json.py index 62ddee4..2f9898e 100644 --- a/colout/colout_json.py +++ b/colout/colout_json.py @@ -3,10 +3,10 @@ def theme(context): # This theme expect a formatted JSON input, with items spread across lines. # See tools like "python -m json.tool" or "json_xs" return context,[ - [ '[\[\]{}],*\s*\n' ], + [ r'[\[\]{}],*\s*\n' ], [ '" (:) ', "yellow" ], - [ '[\]}"](,)', "yellow" ], - [ "\"(-*[0-9]+\.*[0-9]*e*-*[0-9]*)\"", "blue" ], + [ r'[\]}"](,)', "yellow" ], + [ r"\"(-*[0-9]+\.*[0-9]*e*-*[0-9]*)\"", "blue" ], [ '"(.*)"', "green" ], [ """["']""", "cyan" ] ] diff --git a/colout/colout_latex.py b/colout/colout_latex.py index c19287f..5567fbd 100644 --- a/colout/colout_latex.py +++ b/colout/colout_latex.py @@ -7,19 +7,20 @@ def theme(context): "magenta,magenta,white,magenta", "normal,bold,normal" ], ["(LaTeX Warning): (.*)", "magenta", "normal,bold" ], ["(LaTeX Error): (.*)", "red", "normal,bold" ], - ["^(.*\.tex):([0-9]+): (.*)", "white,yellow,red", "normal,normal,bold" ], + [r"^(.*\.tex):([0-9]+): (.*)", "white,yellow,red", "normal,normal,bold" ], # ["on (page [0-9]+)", "yellow", "normal" ], ["on input (line [0-9]+)", "yellow", "normal" ], ["^! .*$", "red", "bold"], - ["(.*erfull) ([^\s]+).* in [^\s]+ at (lines [0-9]+--[0-9]+)", + [r"(.*erfull) ([^\s]+).* in [^\s]+ at (lines [0-9]+--[0-9]+)", "magenta,magenta,yellow", "normal"], - ["\\[^\s]+\s", "white", "bold"], - ["^l\.([0-9]+) (.*)", "yellow,tex"], - ["^\s+(.*)", "tex"], - ["(Output written on) (.*) \(([0-9]+ pages), [0-9]+ bytes\).", + [r"\\[^\s]+\s", "white", "bold"], + [r"^l\.([0-9]+) (.*)", "yellow,tex"], + [r"^\s+(.*)", "tex"], + [r"(Output written on) (.*) \(([0-9]+ pages), [0-9]+ bytes\).", "blue,white,blue", "normal,bold,normal"], ["WARNING.*", "magenta", "normal"], - ["warning.*", "magenta", "normal"], + ["[wW]arning.*", "magenta", "normal"], + ["No pages of output", "red", "bold"], # BiBTeX ["^(I couldn't) (.*)", "red", "normal,bold"], diff --git a/colout/colout_ninja.py b/colout/colout_ninja.py index 1d416c9..34dd9ec 100644 --- a/colout/colout_ninja.py +++ b/colout/colout_ninja.py @@ -11,9 +11,9 @@ def theme(context): context["scale"] = (0,1) # Link (ninja) - th.append( [ "^\[[0-9/]+\]\s?(Linking .* )(library|executable) (.*/)*(.+(\.[aso]+)*)$", + th.append( [ r"^\[[0-9/]+\]\s?(Linking .* )(library|executable) (.*/)*(.+(\.[aso]+)*)$", "blue", "normal,normal,bold" ] ) # progress percentage (ninja) - th.append( [ "^(\[[0-9]+/[0-9]+\])","Scale" ] ) + th.append( [ r"^(\[[0-9]+/[0-9]+\])","Scale" ] ) return context,th diff --git a/colout/colout_perm.py b/colout/colout_perm.py index ffcb2a5..048230c 100644 --- a/colout/colout_perm.py +++ b/colout/colout_perm.py @@ -1,7 +1,7 @@ def theme(context): p="([-rwxsStT])" - reg="^([-dpcCDlMmpPs?])"+p*9+"\s.*$" + reg=r"^([-dpcCDlMmpPs?])"+p*9+r"\s.*$" colors="blue"+",green"*3+",yellow"*3+",red"*3 styles="normal"+ ",normal,italic,bold"*3 return context,[ [reg, colors, styles] ] diff --git a/colout/colout_python.py b/colout/colout_python.py index 3623d04..40e4b34 100644 --- a/colout/colout_python.py +++ b/colout/colout_python.py @@ -5,16 +5,16 @@ def theme(context): ["^Traceback .*$", "blue" ], # File, line, in [ - "^\s{2}(File \")(/*.*?/)*([^/:]+)(\", line) ([0-9]+)(, in) (.*)$", + r"^\s{2}(File \")(/*.*?/)*([^/:]+)(\", line) ([0-9]+)(, in) (.*)$", "blue, none, white,blue, yellow,blue", "normal,normal,bold, normal,normal,bold" ], - # ["^\s{2}File \"(.*)\", line ([0-9]+), in (.*)$", "white,yellow,white", "normal,normal,bold" ], + # [r"^\s{2}File \"(.*)\", line ([0-9]+), in (.*)$", "white,yellow,white", "normal,normal,bold" ], # Error name ["^([A-Za-z]*Error):*", "red", "bold" ], ["^([A-Za-z]*Exception):*", "red", "bold" ], # any quoted things - ["Error.*['\"](.*)['\"]", "magenta" ], + [r"Error.*['\"](.*)['\"]", "magenta" ], # python code - ["^\s{4}.*$", "Python", "monokai" ], + [r"^\s{4}.*$", "Python", "monokai" ], ] diff --git a/colout/colout_slurm.py b/colout/colout_slurm.py new file mode 100644 index 0000000..9f5af8d --- /dev/null +++ b/colout/colout_slurm.py @@ -0,0 +1,117 @@ + +def theme(context): + # SLURM's states (from squeue manual). + + col_width = 9 + + COMPLETED =r"\bCOMPLETED" + PENDING =r"\bPENDING" + RUNNING =r"\bRUNNING" + CONFIGURING =r"\bCONFIGURING" + COMPLETING =r"\bCOMPLETING" + FAILED =r"\bFAILED" + DEADLINE =r"\bDEADLINE" + OUT_OF_MEMORY=r"\bOUT_OF_MEMORY" + TIMEOUT =r"\bTIMEOUT" + CANCELLED =r"\bCANCELLED" + BOOT_FAIL =r"\bBOOT_FAIL" + NODE_FAIL =r"\bNODE_FAIL" + PREEMPTED =r"\bPREEMPTED" + RESV_DEL_HOLD=r"\bRESV_DEL_HOLD" + REQUEUE_FED =r"\bREQUEUE_FED" + REQUEUE_HOLD =r"\bREQUEUE_HOLD" + REQUEUED =r"\bREQUEUED" + RESIZING =r"\bRESIZING" + REVOKED =r"\bREVOKED" + SIGNALING =r"\bSIGNALING" + SPECIAL_EXIT =r"\bSPECIAL_EXIT" + STAGE_OUT =r"\bSTAGE_OUT" + STOPPED =r"\bSTOPPED" + SUSPENDED =r"\bSUSPENDED" + + return context,[ + + ## No problem: greens + + #Job has terminated all processes on all nodes with an exit code of zero. + [r"\bCD\b", "22"], + [COMPLETED[0:col_width]+r"\w*\b", "22"], + #Job is awaiting resource allocation. + [r"\bPD\b", "28"], + [PENDING[0:col_width]+r"\w*\b", "28"], + #Job currently has an allocation. + [r"\bR\b", "34"], + [RUNNING[0:col_width]+r"\w*\b", "34"], + #Job has been allocated resources, but are waiting for them to become ready for use (e.g. booting). + [r"\bCF\b", "58"], + [CONFIGURING[0:col_width]+r"\w*\b", "58"], + #Job is in the process of completing. Some processes on some nodes may still be active. + [r"\bCG\b", "23"], + [COMPLETING[0:col_width]+r"\w*\b", "23"], + + ## Problem for the user: bold reds + + #Job terminated with non-zero exit code or other failure condition. + [r"\bF\b", "196"], + [FAILED[0:col_width]+r"\w*\b", "196", "bold"], + #Job terminated on deadline. + [r"\bDL\b", "160"], + [DEADLINE[0:col_width]+r"\w*\b", "160", "bold"], + #Job experienced out of memory error. + [r"\bOO\b", "197"], + [OUT_OF_MEMORY[0:col_width]+r"\w*\b", "197", "bold"], + #Job terminated upon reaching its time limit. + [r"\bTO\b", "161"], + [TIMEOUT[0:col_width]+r"\w*\b", "161", "bold"], + + ## Problem for the sysadmin: oranges + + #Job was explicitly cancelled by the user or system administrator. The job may or may not have been initiated. + [r"\bCA\b", "202"], + [CANCELLED[0:col_width]+r"\w*\b", "202", "bold"], + #Job terminated due to launch failure, typically due to a hardware failure (e.g. unable to boot the node or block and the job can not be requeued). + [r"\bBF\b", "166"], + [BOOT_FAIL[0:col_width]+r"\w*\b", "166"], + #Job terminated due to failure of one or more allocated nodes. + [r"\bNF\b", "208"], + [NODE_FAIL[0:col_width]+r"\w*\b", "208"], + + ## Non-blocking events: blues + + #Job terminated due to preemption. + [r"\bPR\b", "105"], + [PREEMPTED[0:col_width]+r"\w*\b", "105", "bold"], + #Job is being held after requested reservation was deleted. + [r"\bRD\b", "25"], + [RESV_DEL_HOLD[0:col_width]+r"\w*\b", "25"], + #Job is being requeued by a federation. + [r"\bRF\b", "26"], + [REQUEUE_FED[0:col_width]+r"\w*\b", "26"], + #Held job is being requeued. + [r"\bRH\b", "27"], + [REQUEUE_HOLD[0:col_width]+r"\w*\b", "27"], + #Completing job is being requeued. + [r"\bRQ\b", "31"], + [REQUEUED[0:col_width]+r"\w*\b", "31"], + #Job is about to change size. + [r"\bRS\b", "32"], + [RESIZING[0:col_width]+r"\w*\b", "32"], + #Sibling was removed from cluster due to other cluster starting the job. + [r"\bRV\b", "33"], + [REVOKED[0:col_width]+r"\w*\b", "33"], + #Job is being signaled. + [r"\bSI\b", "37"], + [SIGNALING[0:col_width]+r"\w*\b", "37"], + #The job was requeued in a special state. This state can be set by users, typically in EpilogSlurmctld, if the job has terminated with a particular exit value. + [r"\bSE\b", "38"], + [SPECIAL_EXIT[0:col_width]+r"\w*\b", "38"], + #Job is staging out files. + [r"\bSO\b", "39"], + [STAGE_OUT[0:col_width]+r"\w*\b", "39"], + #Job has an allocation, but execution has been stopped with SIGSTOP signal. CPUS have been retained by this job. + [r"\bST\b", "44"], + [STOPPED[0:col_width]+r"\w*\b", "44"], + #Job has an allocation, but execution has been suspended and CPUs have been released for other jobs. + [r"\bS\b", "45"], + [SUSPENDED[0:col_width]+r"\w*\b", "45"], + ] diff --git a/colout/colout_valgrind.py b/colout/colout_valgrind.py index fe95982..7fc33a2 100644 --- a/colout/colout_valgrind.py +++ b/colout/colout_valgrind.py @@ -4,30 +4,30 @@ def theme(context): return context, [ # section title - ["^(==[0-9]+==\s{1})(Memcheck|Copyright|Using)(.*)$","blue",""], - ["^(==[0-9]+==\s{1})(Warning)(.*)$","magenta",""], - ["^(==[0-9]+==\s{1}Command: )(\S*)(.*)$","green,white","normal,bold,normal"], - ["^(==[0-9]+==\s{1})(HEAP SUMMARY:)(.*)$","green",""], - ["^(==[0-9]+==\s{1})(All heap blocks were freed)(.*)$","green",""], - ["^(==[0-9]+==\s{1})(.*[rR]erun.*)$","blue",""], - ["^(==[0-9]+==\s{1})(Use --.*)$","blue",""], - ["^(==[0-9]+==\s{1}\S+.*)$","red",""], + [r"^(==[0-9]+==\s{1})(Memcheck|Copyright|Using)(.*)$","blue",""], + [r"^(==[0-9]+==\s{1})(Warning)(.*)$","magenta",""], + [r"^(==[0-9]+==\s{1}Command: )(\S*)(.*)$","green,white","normal,bold,normal"], + [r"^(==[0-9]+==\s{1})(HEAP SUMMARY:)(.*)$","green",""], + [r"^(==[0-9]+==\s{1})(All heap blocks were freed)(.*)$","green",""], + [r"^(==[0-9]+==\s{1})(.*[rR]erun.*)$","blue",""], + [r"^(==[0-9]+==\s{1})(Use --.*)$","blue",""], + [r"^(==[0-9]+==\s{1}\S+.*)$","red",""], # section explanation - ["^==[0-9]+==\s{2}(\S+.*)$","orange",""], + [r"^==[0-9]+==\s{2}(\S+.*)$","orange",""], # locations adresses - ["^==[0-9]+==\s{4}([atby]{2}) (0x0): (\?{3})", + [r"^==[0-9]+==\s{4}([atby]{2}) (0x0): (\?{3})", "blue,yellow,red", "normal,normal,bold"], - ["^==[0-9]+==\s{4}([atby]{2}) (0x)([^:]*:) (\S+)", + [r"^==[0-9]+==\s{4}([atby]{2}) (0x)([^:]*:) (\S+)", "blue,blue,blue,none", "normal"], # locations: library - ["\(in (.*)\)", "cyan", "normal"], + [r"\(in (.*)\)", "cyan", "normal"], # locations: file - ["\(([^\.]*\.[^:]+):([0-9]+)\)", "white,yellow", "bold,normal"], + [r"\(([^\.]*\.[^:]+):([0-9]+)\)", "white,yellow", "bold,normal"], # leak summary - ["^==[0-9]+==\s{4}(definitely lost): .* (in) .*","red","bold"], - ["^==[0-9]+==\s{4}(indirectly lost): .* (in) .*","orange","bold"], - ["^==[0-9]+==\s{6}(possibly lost): .* (in) .*","yellow","bold"], - ["^==[0-9]+==\s{4}(still reachable): .* (in) .*","green","bold"], - ["^==[0-9]+==\s{9}(suppressed): .* (in) .*","cyan","bold"], + [r"^==[0-9]+==\s{4}(definitely lost): .* (in) .*","red","bold"], + [r"^==[0-9]+==\s{4}(indirectly lost): .* (in) .*","orange","bold"], + [r"^==[0-9]+==\s{6}(possibly lost): .* (in) .*","yellow","bold"], + [r"^==[0-9]+==\s{4}(still reachable): .* (in) .*","green","bold"], + [r"^==[0-9]+==\s{9}(suppressed): .* (in) .*","cyan","bold"], ] diff --git a/colout/colout_vivado.py b/colout/colout_vivado.py new file mode 100644 index 0000000..aa74216 --- /dev/null +++ b/colout/colout_vivado.py @@ -0,0 +1,26 @@ + +def theme(context): + # Theme for coloring AMD/Xilinx Vivado IDE synthesis and implementation output + return context,[ + [ r"^\s*\*+.+$", "green" ], + [ "^#.+", "green" ], + + [ "^.+ Checksum: .+$", "green" ], + + [ r"^.+Time \(s\).+", "green" ], + [ r"^Time \(s\).+", "green" ], + + [ r"Estimated Timing Summary \|.+\|.+\|", "cyan", "bold" ], + [ r"Intermediate Timing Summary \|.+\|.+\|", "cyan", "bold" ], + + [ "^INFO:", "white", "bold" ], + [ "^WARNING:.+$", "yellow" ], + [ "^CRITICAL WARNING:.+$", "red" ], + [ "^ERROR:.+$", "red" ], + + [ "^Phase [0-9]+.[0-9]+.[0-9]+.[0-9]+.+$", "magenta", "bold" ], + [ "^Phase [0-9]+.[0-9]+.[0-9]+.+$", "magenta", "bold" ], + [ "^Phase [0-9]+.[0-9]+.+$", "magenta", "bold" ], + [ "^Phase [0-9]+.+$", "magenta", "bold" ] + ] + diff --git a/colout_logo.svg b/colout_logo.svg new file mode 100644 index 0000000..8db7984 --- /dev/null +++ b/colout_logo.svg @@ -0,0 +1,612 @@ + + + + + colout logo + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + colout logo + 2022-08-31 + + + nojhan + + + + + + diff --git a/requirements-build.txt b/requirements-build.txt new file mode 100644 index 0000000..d50412d --- /dev/null +++ b/requirements-build.txt @@ -0,0 +1,3 @@ +tox +tox-wheel +twine diff --git a/setup.py b/setup.py index a79d0cf..6bf5211 100644 --- a/setup.py +++ b/setup.py @@ -9,25 +9,49 @@ except ImportError: from distutils.core import setup if sys.argv[-1] == 'publish': - os.system('python3 setup.py sdist upload') + os.system('python setup.py bdist_wheel --universal upload') sys.exit() packages = ['colout'] -requires = ['argparse; python_version < "2.7"', 'pygments', 'babel'] +requires = ['pygments', 'babel'] + +setup_requires = ['setuptools_scm'] + +classifiers = """ +Environment :: Console +Development Status :: 5 - Production/Stable +License :: OSI Approved :: GNU General Public License v3 (GPLv3) +Operating System :: POSIX +Operating System :: POSIX :: Linux +Programming Language :: Python :: 3 +Programming Language :: Python :: 3.5 +Programming Language :: Python :: 3.6 +Programming Language :: Python :: 3.7 +Programming Language :: Python :: 3.8 +Topic :: Utilities +Topic :: Text Processing +Topic :: Text Processing :: Filters +""".strip().split('\n') setup( name='colout', - version='0.6', + use_scm_version=True, + classifiers=classifiers, description='Color Up Arbitrary Command Output.', - long_description=open('README.md').read(), + entry_points={ + 'console_scripts': ['colout=colout.colout:main'], + }, + long_description=open(os.path.join(os.path.dirname(__file__), 'README.md')).read(), + long_description_content_type='text/markdown;variant=CommonMark', author='nojhan', author_email='nojhan@nojhan.net', url='http://nojhan.github.com/colout/', packages=packages, package_data={'': ['LICENSE', 'README.md']}, package_dir={'colout': 'colout'}, - scripts=['bin/colout'], + python_requires='>=3.5', + setup_requires=setup_requires, include_package_data=True, install_requires=requires, license='GPLv3', diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..ff4e1ca --- /dev/null +++ b/tox.ini @@ -0,0 +1,15 @@ +[tox] +envlist=py35,py36,py37,py38,cov + +[testenv] +wheel = true +deps= + pytest + pytest-cov + pytest-xdist +setenv= + py{35,36,37,38}: COVERAGE_FILE=.coverage.{envname} +commands= + py{35,36,37,38}: python -m pytest --cov=colout --cov-report=term-missing --no-cov-on-fail + cov: coverage combine + cov: coverage html --fail-under=85