diff --git a/.gitignore b/.gitignore
index c2a9c3f..9839280 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,162 +1,4 @@
-## Python gitignore
-# Byte-compiled / optimized / DLL files
-__pycache__/
-*.py[cod]
-*$py.class
-
-# C extensions
-*.so
-
-# Distribution / packaging
-.Python
+*.pyc
build/
-develop-eggs/
dist/
-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
+colout.egg-info/
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index b7997b5..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-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
deleted file mode 100644
index 1aba38f..0000000
--- a/MANIFEST.in
+++ /dev/null
@@ -1 +0,0 @@
-include LICENSE
diff --git a/README.md b/README.md
index 10bde37..065af82 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,16 @@
-colout — Color Up Arbitrary Command Output
-==========================================
+colout(1) -- Color Up Arbitrary Command Output
+==============================================
-
-
-
+## SYNOPSIS
-## Synopsis
+`colout` [-h] [-r RESOURCE]
-`colout [-h] [-r [RESOURCE]]`
+`colout` [-g] [-c] [-l min,max] [-a] [-t] [-T DIR] [-P DIR] [-d COLORMAP] [-s] [--debug] PATTERN [COLOR(S) [STYLE(S)]]
-`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
+## 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*.
+matching a given regular expression *PATTERN* in given and *STYLE*.
If groups are specified in the regular expression pattern, only them are taken
into account, else the whole matching pattern is colored.
@@ -33,13 +25,9 @@ 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 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
(this requires a terminal that supports the 256 color escape sequences).
@@ -64,10 +52,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.
-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 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.).
-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
@@ -78,7 +66,8 @@ 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).
-`colout` can be used as an interface to pygments (see also the `--source` switch below).
+If the python3-pygments library is available, `colout` can be used as an interface
+to it (see also the `-s` switch below).
To have a list of all colors, styles, special colormaps, themes, palettes and lexers,
use the `-r` switch (see below).
@@ -86,29 +75,37 @@ use the `-r` switch (see below).
`colout` is released under the GNU Public License v3.
-## Installation
+## INSTALLATION
-The recomended method is using pip to install the package for the local user:
+ sudo python3 setup.py install
-```console
-$ pip install --user colout
-```
+and then soft link `/usr/local/bin/colout` to your colout.py under your installation
+directory, which is usually something like
-Another method is using [pipsi](https://github.com/mitsuhiko/pipsi)
-(_pipsi is no longer maintained, _)
-```console
-$ pipsi install colout
-```
+ /usr/local/lib/python3/dist-packages/colout-0.1-py3.egg/colout/colout.py
-There is also a PPA for Ubuntu 16.04 (Xenial)/18.04 (Bionic) (@`0.6.1-3~dist7`, not actively maintained)
-```console
-$ sudo add-apt-repository ppa:csaba-kertesz/random
-$ sudo apt-get update
-$ sudo apt-get/aptitude install colout
-```
+## OTHER INSTALLATION METHOD
-## Options
+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
* `-h`, `--help`:
Show a help message and exit
@@ -120,9 +117,8 @@ $ sudo apt-get/aptitude install colout
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
- between the given min,max (0,100, by default).
+ When using the 'scale' colormap, parse matches as decimal numbers (taking your locale into account)
+ and apply the rainbow colormap linearly between the given min,max (0,100, by default).
* `-a`, `--all`:
Color the whole input at once instead of line per line
@@ -132,10 +128,10 @@ $ sudo apt-get/aptitude install colout
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.
@@ -145,27 +141,21 @@ $ sudo apt-get/aptitude install colout
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' (or no argument) to print all resources.
+ use 'all' to print everything.
* `-s`, `--source`:
Interpret PATTERN as source code readable by the Pygments library. If the first letter of PATTERN
is upper case, use the 256 color mode, if it is lower case, use the 8 colors mode.
In 256 color mode, interpret COLOR as a Pygments style (e.g. "default").
-* `-e CHAR`, `--sep-list CHAR`:
- Use this character as a separator for list of colors/resources/numbers (instead of comma).
-
-* `-E CHAR`, `--sep-pair CHAR`:
- Use this character as a separator for foreground/background pairs (instead of period).
-
* `--debug`:
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.
@@ -175,25 +165,25 @@ that matches it.
special characters that would be recognize by your shell.
-## Dependencies
+## DEPENDENCIES
-Necessary Python modules:
+Recommended packages:
+* `argparse` for a usable arguments parsing
* `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.
Using a default colormap that is incompatible with the special colormap's mode
-(i.e. number of colors) will end badly.
+will end badly.
-Color pairs (`foreground.background`) work in 8-colors mode for simple coloring, but may fail with `--colormap`.
-## Examples
+## EXAMPLES
### Simple
@@ -203,7 +193,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:
@@ -267,131 +257,31 @@ 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:
-```bash
-function cm()
-{
- set -o pipefail
- $@ 2>&1 | colout -t cmake | colout -t g++
-}
-```
+ 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`
-### GDB integration
-
-You can use `colout` within the GNU debuger (`gbd`) to color its output.
-For example, the following script `.gdbinit` configuration will color
-the output of the backtrace command:
-
-```gdb
-set confirm off
-
-# Don't wrap line or the coloring regexp won't work.
-set width 0
-
-# Create a named pipe to get outputs from gdb
-shell test -e /tmp/coloutPipe && rm /tmp/coloutPipe
-shell mkfifo /tmp/coloutPipe
-
-define logging_on
- # Instead of printing on stdout only, log everything...
- set logging redirect on
- # ... in our named pipe.
- set logging on /tmp/coloutPipe
-end
-
-define logging_off
- set logging off
- set logging redirect off
- # Because both gdb and our commands are writing on the same pipe at the same
- # time, it is more than probable that gdb will end before our (higher level)
- # commands. The gdb prompt will thus render before the result of the command,
- # which is highly akward. To prevent this, we need to wait before displaying
- # the prompt again. The more your commands are complex, the higher you will
- # need to set this.
- shell sleep 0.4s
-end
-
-define hook-backtrace
- # Note: match path = [path]file[.ext] = (.*/)?(?:$|(.+?)(?:(\.[^.]*)|))
- # This line color highlights:
- # – lines that link to source code,
- # – function call in green,
- # – arguments names in yellow, values in magenta,
- # — the parent directory in bold red (assuming that the debug session would be in a "project/build/" directory).
- shell cat /tmp/coloutPipe | colout "^(#)([0-9]+)\s+(0x\S+ )*(in )*(.*) (\(.*\)) (at) (.*/)?(?:$|(.+?)(?:(\.[^.]*)|)):([0-9]+)" red,red,blue,red,green,magenta,red,none,white,white,yellow normal,bold,normal,normal,normal,normal,normal,bold,bold,bold | colout "([\w\s]*?)(=)([^,]*?)([,\)])" yellow,blue,magenta,blue normal | colout "/($(basename $(dirname $(pwd))))/" red bold &
- logging_on
-end
-define hookpost-backtrace
- logging_off
-end
-
-# Don't forget to clean the adhoc pipe.
-define hook-quit
- set confirm off
- shell rm -f /tmp/coloutPipe
-end
-```
-
-Take a look at the `example.gdbinit` file distributed with colout for more gdb commands.
-
-
-
### 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.
-```python
-def theme(context):
- return context,[ [regexp, colors, styles] ]
-```
+ 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 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 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 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.
-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, maintainer.
-* Adrian Sadłocha
-* Alex Burka
-* Brian Foley
-* Charles Lewis
-* DainDwarf
-* Dimitri Merejkowsky
-* Dong Wei Ming
-* Fabien MARTY
-* Jason Green
-* John Anderson
-* Jonathan Poelen
-* Louis-Kenzo Furuya Cahier
-* Mantas
-* Martin Ueding
-* Nicolas Pouillard
-* Nurono
-* Oliver Bristow
-* orzrd <61966225@qq.com>
-* Philippe Daouadi
-* Piotr Staroszczyk
-* Scott Lawrence
-* Xu Di
-* https://github.com/stdedos: maintainer.
diff --git a/bin/colout b/bin/colout
new file mode 100644
index 0000000..7702d17
--- /dev/null
+++ b/bin/colout
@@ -0,0 +1,11 @@
+#!/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 2d51fac..fcc899d 100755
--- a/colout/colout.py
+++ b/colout/colout.py
@@ -1,26 +1,22 @@
#!/usr/bin/env python3
#encoding: utf-8
-# Color Up Arbitrary Command Output
+# Color Up Arbitrary Command Ouput
# Licensed under the GPL version 3
# 2012 (c) nojhan
-import os
-import re
import sys
-import copy
+import re
+import random
+import os
import glob
import math
-import pprint
-import random
+import importlib
+import logging
import signal
import string
import hashlib
-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
@@ -41,23 +37,11 @@ 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.
-eight_color_codes = {n:i for i,n in enumerate(eight_colors)}
-# One can add synonyms.
-eight_color_codes["orange"] = eight_color_codes["yellow"]
-eight_color_codes["purple"] = eight_color_codes["magenta"]
-
-# Foreground colors has a special "none" item.
-# Note: use copy to avoid having the same reference over fore/background.
-context["colors"] = copy.copy(eight_color_codes)
-context["colors"]["none"] = -1
-
-# Background has the same colors than foreground, but without the none code.
-context["backgrounds"] = copy.copy(eight_color_codes)
+# Available color names in 8-colors mode
+context["colors"] = {
+ "black": 0, "red": 1, "green": 2, "yellow": 3, "orange":3, "blue": 4,
+ "magenta": 5, "purple": 5, "cyan": 6, "white": 7, "none": -1
+}
context["themes"] = {}
@@ -93,11 +77,6 @@ context["scale"] = (0,100)
context["lexers"] = []
-# Character use as a delimiter
-# between foreground and background.
-context["sep_pair"]="."
-context["sep_list"]=","
-
class UnknownColor(Exception):
pass
@@ -107,27 +86,13 @@ class DuplicatedPalette(Exception):
class DuplicatedTheme(Exception):
pass
-class MixedModes(Exception):
- pass
-
###############################################################################
# Ressource parsing helpers
###############################################################################
-def make_colormap( colors, sep_list = context["sep_list"] ):
- cmap = colors.split(sep_list)
- # Check unicity of mode.
- modes = [mode(c) for c in cmap]
- if len(uniq(modes)) > 1:
- # Format a list of color:mode, for error display.
- raise MixedModes(", ".join(["%s:%s" % cm for cm in zip(cmap,modes)]))
-
- return cmap
-
-
-def set_special_colormaps( cmap, sep_list = context["sep_list"] ):
+def set_special_colormaps( cmap ):
"""Change all the special colors to a single colormap (which must be a list of colors)."""
global context
context["colormaps"]["scale"] = cmap
@@ -136,10 +101,10 @@ def set_special_colormaps( cmap, sep_list = context["sep_list"] ):
context["colormaps"]["Hash"] = cmap
context["colormaps"]["default"] = cmap
context["colormaps"]["Default"] = cmap
- context["colormaps"]["random"] = cmap
- context["colormaps"]["Random"] = cmap
+ context["colormaps"]["random"] = cmap
+ context["colormaps"]["Random"] = cmap
context["user_defined_colormaps"] = True
- logging.debug("user-defined special colormap: %s" % sep_list.join([str(i) for i in cmap]) )
+ logging.debug("user-defined special colormap: %s" % ",".join([str(i) for i in cmap]) )
def parse_gimp_palette( filename ):
@@ -177,7 +142,7 @@ def parse_gimp_palette( filename ):
palette = []
for line in lines:
# skip lines with only a comment
- if re.match(r"^\s*#.*$", line ):
+ if re.match("^\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] ]
@@ -249,13 +214,12 @@ def hex_to_rgb(h):
def load_themes( themes_dir):
global context
logging.debug("search for themes in: %s" % themes_dir)
- sys.path.append( themes_dir )
+ os.chdir( themes_dir )
# load available themes
- 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.
+ for f in glob.iglob("colout_*.py"):
+ module = ".".join(f.split(".")[:-1]) # remove extension
+ name = "_".join(module.split("_")[1:]) # remove the prefix
if name in context["themes"]:
raise DuplicatedTheme(name)
logging.debug("load theme %s" % name)
@@ -265,9 +229,10 @@ 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(os.path.join(palettes_dir, "*.gpl")):
+ for p in glob.iglob("*.gpl"):
try:
name,palette = parse_gimp_palette(p)
except Exception as e:
@@ -290,41 +255,33 @@ 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:
- for lexer in get_all_lexers():
- 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 # 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")
+ global get_lexer_by_name
+ from pygments.lexers import get_lexer_by_name
- lexers.sort()
- logging.debug("loaded %i lexers: %s" % (len(lexers), ", ".join(lexers)))
+ 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:
+ logging.warning("cannot load lexer: %s" % lexer[1][0])
+ pass
+ else:
+ logging.debug("loaded lexer %s" % lexer[1][0])
+ lexers.sort()
context["lexers"] = lexers
@@ -366,17 +323,17 @@ def mode( color ):
raise UnknownColor(color)
-def next_in_map( name ):
+def next_in_map( color ):
global context
# loop over indices in colormap
- return (context["colormap_idx"]+1) % len(context["colormaps"][name])
+ return (context["colormap_idx"]+1) % len(context["colormaps"][color])
def color_random( color ):
global context
m = mode(color)
if m == 8:
- color_name = random.choice(list(context["colormaps"]["random"]))
+ color_name = random.choice(context["colormaps"]["random"])
color_code = context["colors"][color_name]
color_code = str(30 + color_code)
@@ -415,11 +372,23 @@ 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:
- f = float(bn.parse_decimal(nb))
- except bn.NumberFormatError:
- pass
+ # 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
if f is not None:
# normalize with scale if it's a number
f = (f - context["scale"][0]) / (context["scale"][1]-context["scale"][0])
@@ -473,7 +442,7 @@ def color_hash( name, text ):
def color_map(name):
global context
# current color
- color = context["colormaps"][name][ context["colormap_idx"] ]
+ color = context["colormaps"][name][context["colormap_idx"]]
m = mode(color)
if m == 8:
@@ -483,9 +452,9 @@ def color_map(name):
assert( 0 <= color_nb <= 255 )
color_code = str(color_nb)
- context["colormap_idx"] = next_in_map(name)
+ context["colormap_idx"] = next_in_map(color)
- return color,color_code
+ return color_code
def color_lexer( name, style, text ):
@@ -509,14 +478,10 @@ def color_lexer( name, style, text ):
return "<"+name+">"+ highlight(text, lexer, formatter)[:-1] + ""+name+">"
-def colorin(text, color="red", style="normal", sep_pair=context["sep_pair"]):
+def colorin(text, color="red", style="normal"):
"""
Return the given text, surrounded by the given color ASCII markers.
- The given color may be either a single name, encoding the foreground color,
- or a pair of names, delimited by the given sep_pair,
- encoding foreground and background, e.g. "red.blue".
-
If the given color is a name that exists in available colors,
a 8-colors mode is assumed, else, a 256-colors mode.
@@ -541,24 +506,18 @@ def colorin(text, color="red", style="normal", sep_pair=context["sep_pair"]):
color_code = ""
style_code = ""
- background_code = ""
- style_codes = []
# Convert the style code
if style == "random" or style == "Random":
style = random.choice(list(context["styles"].keys()))
else:
- styles = style.split(sep_pair)
- for astyle in styles:
- if astyle in context["styles"]:
- style_codes.append(str(context["styles"][astyle]))
- style_code = ";".join(style_codes)
+ if style in context["styles"]:
+ style_code = str(context["styles"][style])
- color_pair = color.strip().split(sep_pair)
- color = color_pair[0]
- background = color_pair[1] if len(color_pair) == 2 else "none"
+ color = color.strip()
+ m = mode(color)
- if color == "none" and background == "none":
+ if color == "none":
# if no color, style cannot be applied
if not debug:
return text
@@ -575,10 +534,10 @@ def colorin(text, color="red", style="normal", sep_pair=context["sep_pair"]):
elif color.lower() == "hash":
color_code = color_hash( color, text )
- # The user can change the "colormap" variable to its favorite one before calling colorin.
+ # Really useful only when using colout as a library
+ # thus you can change the "colormap" variable to your favorite one before calling colorin
elif color == "colormap":
- # "default" should have been set to the user-defined colormap.
- color,color_code = color_map("default")
+ color_code = color_map(color)
# Registered colormaps should be tested after special colors,
# because special tags are also registered as colormaps,
@@ -611,28 +570,14 @@ def colorin(text, color="red", style="normal", sep_pair=context["sep_pair"]):
else:
raise UnknownColor(color)
- m = mode(color)
-
- if background in context["backgrounds"] and m == 8:
- background_code = endmarks[m] + str(40 + context["backgrounds"][background])
- elif background == "none":
- background_code = ""
- else:
- raise UnknownColor(background)
-
if color_code is not None:
if not debug:
- return start + style_code + endmarks[m] + color_code + background_code + "m" + text + stop
+ return start + style_code + endmarks[m] + color_code + "m" + text + stop
else:
- return start + style_code + endmarks[m] + color_code + background_code + "m" \
- + "" \
+ return start + style_code + endmarks[m] + color_code + "m" \
+ + "" \
+ text + "" + stop
else:
if not debug:
@@ -654,7 +599,7 @@ def colorout(text, match, prev_end, color="red", style="normal", group=0):
return colored_text, end
-def colorup(text, pattern, color="red", style="normal", on_groups=False, sep_list=context["sep_list"]):
+def colorup(text, pattern, color="red", style="normal", on_groups=False):
"""
Color up every characters that match the given regexp patterns.
If groups are specified, only color up them and not the whole pattern.
@@ -663,8 +608,20 @@ 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
@@ -690,11 +647,11 @@ def colorup(text, pattern, color="red", style="normal", on_groups=False, sep_lis
# Build a list of colors that match the number of grouped,
# if there is not enough colors, duplicate the last one.
- colors_l = color.split(sep_list)
+ colors_l = color.split(",")
group_colors = colors_l + [colors_l[-1]] * (nb_groups - len(colors_l))
# Same for styles
- styles_l = style.split(sep_list)
+ styles_l = style.split(",")
group_styles = styles_l + [styles_l[-1]] * (nb_groups - len(styles_l))
# If we want to iterate colormaps on groups instead of patterns
@@ -774,7 +731,7 @@ def map_write( stream_in, stream_out, function, *args ):
write( function(item, *args), stream_out )
-def colorgen(stream, pattern, color="red", style="normal", on_groups=False, sep_list=context["sep_list"]):
+def colorgen(stream, pattern, color="red", style="normal", on_groups=False):
"""
A generator that colors the items given in an iterable input.
@@ -790,14 +747,71 @@ def colorgen(stream, pattern, color="red", style="normal", on_groups=False, sep_
break
if not item:
break
- yield colorup(item, pattern, color, style, on_groups, sep_list)
+ yield colorup(item, pattern, color, style, on_groups)
######################
# Command line tools #
######################
-def _args_parse(argv, usage=""):
+def __args_dirty__(argv, usage=""):
+ """
+ Roughly extract options from the command line arguments.
+ To be used only when argparse is not available.
+
+ Returns a tuple of (pattern,color,style,on_stderr).
+
+ >>> colout.__args_dirty__(["colout","pattern"],"usage")
+ ('pattern', 'red', 'normal', False)
+ >>> colout.__args_dirty__(["colout","pattern","colors","styles"],"usage")
+ ('pattern', 'colors', 'styles', False)
+ >>> colout.__args_dirty__(["colout","pattern","colors","styles","True"],"usage")
+ ('pattern', 'colors', 'styles', True)
+ """
+
+ # Use a dirty argument picker
+ # Check for bad usage or an help flag
+ if len(argv) < 2 \
+ or len(argv) > 10 \
+ or argv[1] == "--help" \
+ or argv[1] == "-h":
+ print(usage+"\n")
+ print("Usage:", argv[0], " [