Parent directory

colorize.plugin.zsh

4483 bytes
  1# Easier alias to use the plugin
  2alias ccat="colorize_cat"
  3alias cless="colorize_less"
  4
  5# '$0:A' gets the absolute path of this file
  6ZSH_COLORIZE_PLUGIN_PATH=$0:A
  7
  8colorize_check_requirements() {
  9    local -a available_tools
 10    available_tools=("chroma" "pygmentize")
 11
 12    if [ -z "$ZSH_COLORIZE_TOOL" ]; then
 13        if (( $+commands[pygmentize] )); then
 14            ZSH_COLORIZE_TOOL="pygmentize"
 15        elif (( $+commands[chroma] )); then
 16            ZSH_COLORIZE_TOOL="chroma"
 17        else
 18            echo "Neither 'pygments' nor 'chroma' is installed!" >&2
 19            return 1
 20        fi
 21    fi
 22
 23    if [[ ${available_tools[(Ie)$ZSH_COLORIZE_TOOL]} -eq 0 ]]; then
 24        echo "ZSH_COLORIZE_TOOL '$ZSH_COLORIZE_TOOL' not recognized. Available options are 'pygmentize' and 'chroma'." >&2
 25        return 1
 26    elif ! (( $+commands[$ZSH_COLORIZE_TOOL] )); then
 27        echo "Package '$ZSH_COLORIZE_TOOL' is not installed!" >&2
 28        return 1
 29    fi
 30}
 31
 32colorize_cat() {
 33    if ! colorize_check_requirements; then
 34        return 1
 35    fi
 36
 37    # If the environment variable ZSH_COLORIZE_STYLE
 38    # is set, use that theme instead. Otherwise,
 39    # use the default.
 40    if [ -z "$ZSH_COLORIZE_STYLE" ]; then
 41        # Both pygmentize & chroma support 'emacs'
 42        ZSH_COLORIZE_STYLE="emacs"
 43    fi
 44
 45    # Use stdin if stdin is not attached to a terminal.
 46    if [ ! -t 0 ]; then
 47        if [[ "$ZSH_COLORIZE_TOOL" == "pygmentize" ]]; then
 48            pygmentize -O style="$ZSH_COLORIZE_STYLE" -g
 49        else
 50            chroma --style="$ZSH_COLORIZE_STYLE" --formatter="${ZSH_COLORIZE_CHROMA_FORMATTER:-terminal}" "$@"
 51        fi
 52        return $?
 53    fi
 54
 55    # Guess lexer from file extension, or guess it from file contents if unsuccessful.
 56    local FNAME lexer
 57    for FNAME in "$@"; do
 58        if [[ "$ZSH_COLORIZE_TOOL" == "pygmentize" ]]; then
 59            lexer=$(pygmentize -N "$FNAME")
 60            if [[ $lexer != text ]]; then
 61                pygmentize -O style="$ZSH_COLORIZE_STYLE" -l "$lexer" "$FNAME"
 62            else
 63                pygmentize -O style="$ZSH_COLORIZE_STYLE" -g "$FNAME"
 64            fi
 65        else
 66            chroma --style="$ZSH_COLORIZE_STYLE" --formatter="${ZSH_COLORIZE_CHROMA_FORMATTER:-terminal}" "$FNAME"
 67        fi
 68    done
 69}
 70
 71# The less option 'F - Forward forever; like "tail -f".' will not work in this implementation
 72# caused by the lack of the ability to follow the file within pygmentize.
 73colorize_less() {
 74    if ! colorize_check_requirements; then
 75        return 1
 76    fi
 77
 78    _cless() {
 79        # LESS="-R $LESS" enables raw ANSI colors, while maintain already set options.
 80        local LESS="-R $LESS"
 81
 82        # This variable tells less to pipe every file through the specified command
 83        # (see the man page of less INPUT PREPROCESSOR).
 84        # 'zsh -ic "colorize_cat %s 2> /dev/null"' would not work for huge files like
 85        # the ~/.zsh_history. For such files the tty of the preprocessor will be suspended.
 86        # Therefore we must source this file to make colorize_cat available in the
 87        # preprocessor without the interactive mode.
 88        # `2>/dev/null` will suppress the error for large files 'broken pipe' of the python
 89        # script pygmentize, which will show up if less has not fully "loaded the file"
 90        # (e.g. when not scrolled to the bottom) while already the next file will be displayed.
 91        local LESSOPEN="| zsh -c 'source \"$ZSH_COLORIZE_PLUGIN_PATH\"; \
 92        ZSH_COLORIZE_TOOL=$ZSH_COLORIZE_TOOL ZSH_COLORIZE_STYLE=$ZSH_COLORIZE_STYLE \
 93        colorize_cat %s 2> /dev/null'"
 94
 95        # LESSCLOSE will be set to prevent any errors by executing a user script
 96        # which assumes that his LESSOPEN has been executed.
 97        local LESSCLOSE=""
 98
 99        LESS="$LESS" LESSOPEN="$LESSOPEN" LESSCLOSE="$LESSCLOSE" command less "$@"
100    }
101
102    if [ -t 0 ]; then
103        _cless "$@"
104    else
105        # The input is not associated with a terminal, therefore colorize_cat will
106        # colorize this input and pass it to less.
107        # Less has now to decide what to use. If any files have been provided, less
108        # will ignore the input by default, otherwise the colorized input will be used.
109        # If files have been supplied and the input has been redirected, this will
110        # lead to unnecessary overhead, but retains the ability to use the less options
111        # without checking for them inside this script.
112        colorize_cat | _cless "$@"
113    fi
114}