From e87e5b2208ed79c5e371a7fb86c5e0185cbc6888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Tue, 4 May 2021 17:12:52 +0300 Subject: [PATCH] cmd: add optional silent fail mode on no specific lexer Makes use of chroma easier in/as less(1) preprocessors. https://manpages.debian.org/less#INPUT_PREPROCESSOR export LESSOPEN='| p() { chroma --fail "$1" || cat "$1"; }; p "%s"' https://manpages.debian.org/lesspipe#USER_DEFINED_FILTERS ln -s ~/go/bin/chroma ~/.lessfilter --- README.md | 18 ++++++++++++++++++ cmd/chroma/main.go | 9 +++++++++ 2 files changed, 27 insertions(+) diff --git a/README.md b/README.md index e276bfa..5f0bce7 100644 --- a/README.md +++ b/README.md @@ -255,6 +255,24 @@ A command-line interface to Chroma is included. It can be installed with: go get -u github.com/alecthomas/chroma/cmd/chroma ``` +The CLI can be used as a preprocessor to colorise output of `less(1)`, +see documentation for the `LESSOPEN` environment variable. + +The `--fail` flag can be used to suppress output and return with exit status +1 to facilitate falling back to some other preprocessor in case chroma +does not resolve a specific lexer to use for the given file. For example: + +```shell +export LESSOPEN='| p() { chroma --fail "$1" || cat "$1"; }; p "%s"' +``` + +Replace `cat` with your favourite fallback preprocessor. + +When invoked as `.lessfilter`, the `--fail` flag is automatically turned +on under the hood for easy integration with [lesspipe shipping with +Debian and derivatives](https://manpages.debian.org/lesspipe#USER_DEFINED_FILTERS); +for that setup the `chroma` executable can be just symlinked to `~/.lessfilter`. + ## What's missing compared to Pygments? diff --git a/cmd/chroma/main.go b/cmd/chroma/main.go index 038f8e3..4d1c189 100644 --- a/cmd/chroma/main.go +++ b/cmd/chroma/main.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "os" "os/signal" + "path" "runtime" "runtime/pprof" "sort" @@ -43,6 +44,7 @@ command, for Go. Trace bool `help:"Trace lexer states as they are traversed."` Check bool `help:"Do not format, check for tokenisation errors instead."` Filename string `help:"Filename to use for selecting a lexer when reading from stdin."` + Fail bool `help:"Exit silently with status 1 if no specific lexer was found."` Lexer string `help:"Lexer to use when formatting." default:"autodetect" short:"l" enum:"${lexers}"` Style string `help:"Style to use for formatting." default:"swapoff" short:"s" enum:"${styles}"` @@ -105,6 +107,10 @@ func main() { }() defer pprof.StopCPUProfile() } + if path.Base(os.Args[0]) == ".lessfilter" { + // https://manpages.debian.org/lesspipe#USER_DEFINED_FILTERS + cli.Fail = true + } var out io.Writer = os.Stdout if runtime.GOOS == "windows" && isatty.IsTerminal(os.Stdout.Fd()) { @@ -238,6 +244,9 @@ func listAll() { func lex(ctx *kong.Context, path string, contents string) chroma.Iterator { lexer := selexer(path, contents) if lexer == nil { + if cli.Fail { + ctx.Exit(1) + } lexer = lexers.Fallback } if rel, ok := lexer.(*chroma.RegexLexer); ok {