Giter VIP home page Giter VIP logo

pygments-ansi-color's Introduction

pygments-ansi-color

build status pre-commit.ci status PyPI version

An ANSI color-code highlighting lexer for Pygments.

Basic usage

  1. Install pygments-ansi-color:

    $ pip install pygments-ansi-color
    
  2. pygments-ansi-color is not magic (yet?), so you need to choose an exising Pygments style, which will be used as a base for your own style.

    For example, let's choose pygments.styles.xcode.XcodeStyle, which looks great to use. And then we will augment this reference style with pygments-ansi-color's color tokens thanks to the color_tokens function, to make our final MyStyle custom style.

    Here is how the code looks like:

    from pygments_ansi_color import color_tokens
    
    class MyStyle(pygments.styles.xcode.XcodeStyle):
        styles = dict(pygments.styles.xcode.XcodeStyle.styles)
        styles.update(color_tokens())

    That's all the custom code you need to integrate with pygments-ansi-color.

  3. Now you can highlight your content with the dedicated ANSI lexer and your custom style, with the Pygments regular API:

    import pygments
    import pygments.formatters
    import pygments.lexers
    
    lexer = pygments.lexers.get_lexer_by_name('ansi-color')
    formatter = pygments.formatters.HtmlFormatter(style=MyStyle)
    print(pygments.highlight('your text', lexer, formatter))

Design

We had to configure above a custom Pygments style with the appropriate color tokens. That's because existing Pygments lexers are built around contextual tokens (think Comment or Punctuation) rather than actual colors.

In the case of ANSI escape sequences, colors have no context beyond the color themselves; we'd always want a red rendered as red, regardless of your particular theme.

Custom theme

By default, pygments-ansi-color maps ANSI codes to its own set of colors. They have been carefully crafted for readability, and are loosely based on the color scheme used by iTerm2 .

Default colors are hard-coded by the pygments_ansi_color.DEFAULT_STYLE constant as such:

  • #000000 Black: #000000
  • #ef2929 Red: #ef2929
  • #8ae234 Green: #8ae234
  • #fce94f Yellow: #fce94f
  • #3465a4 Blue: #3465a4
  • #c509c5 Magenta: #c509c5
  • #34e2e2 Cyan: #34e2e2
  • #f5f5f5 White: #f5f5f5
  • #676767 BrightBlack: #676767
  • #ff6d67 BrightRed: #ff6d67
  • #5ff967 BrightGreen: #5ff967
  • #fefb67 BrightYellow: #fefb67
  • #6871ff BrightBlue: #6871ff
  • #ff76ff BrightMagenta: #ff76ff
  • #5ffdff BrightCyan: #5ffdff
  • #feffff BrightWhite: #feffff

Still, you may want to use your own colors, to tweak the rendering to your background color, or to match your own theme.

For that you can override each color individually, by passing them as arguments to the color_tokens function:

from pygments_ansi_color import color_tokens

class MyStyle(pygments.styles.xcode.XcodeStyle):
   styles = dict(pygments.styles.xcode.XcodeStyle.styles)
   styles.update(color_tokens(
      fg_colors={'Cyan': '#00ffff', 'BrightCyan': '#00ffff'},
      bg_colors={'BrightWhite': '#000000'},
   ))

Used by

You can see an example on fluffy, the project that this lexer was originally developed for.

The colors are defined as part of your Pygments style and can be changed.

Optional: Enable "256 color" support

This library supports rendering terminal output using 256 color (8-bit) ANSI color codes. However, because of limitations in Pygments tokens, this is an opt-in feature which requires patching the formatter you're using.

The reason this requires patching the Pygments formatter is that Pygments does not support multiple tokens on a single piece of text, requiring us to "compose" a single state (which is a tuple of (bold enabled, fg color, bg color)) into a single token like Color.Bold.FGColor.BGColor. We then need to output the styles for this token in the CSS.

In the default mode where we only support the standard 8 colors (plus 1 for no color), we need 2 × 9 × 9 - 1 = 161 tokens, which is reasonable to contain in one CSS file. With 256 colors (plus the standard 8, plus 1 for no color), though, we'd need 2 × 265 × 265 - 1 = 140,449 tokens defined in CSS. This makes the CSS too large to be practical.

To make 256-color support realistic, we patch Pygments' HTML formatter so that it places a class for each part of the state tuple independently. This means you need only 1 + 265 + 265 = 531 CSS classes to support all possibilities.

If you'd like to enable 256-color support, you'll need to do two things:

  1. When calling color_tokens, pass enable_256color=True:

    styles.update(color_tokens(enable_256color=True))

    This change is what causes your CSS to have the appropriate classes in it.

  2. When constructing your formatter, use the ExtendedColorHtmlFormatterMixin mixin, like this:

    from pygments.formatters import HtmlFormatter
    from pygments_ansi_color import ExtendedColorHtmlFormatterMixin
    
    ...
    
    class MyFormatter(ExtendedColorHtmlFormatterMixin, HtmlFormatter):
        pass
    
    ...
    
    formatter = pygments.formatter.HtmlFormatter(style=MyStyle)

    This change is what causes the rendered HTML to have the right class names.

Once these two changes have been made, you can use pygments-ansi-color as normal.

pygments-ansi-color's People

Contributors

asottile avatar chriskuehl avatar jonatanschroeder avatar kdeldycke avatar pre-commit-ci[bot] avatar ssbarnea avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

pygments-ansi-color's Issues

Lack of ANSI hyperlink support (OSC Sequence Support)

Over the last decade most terminals added support for ANSI-hyperlinks, which is a small extension of ANSI that allows inclusion of links by applications.

A good resource about this can be found https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda which also includes a bit of history and also the good old https://en.wikipedia.org/wiki/ANSI_escape_code#OSC_(Operating_System_Command)_sequences -- thes extensions are also called OSC sequences.

To give some insights (from what I often use):

  • iTerm full support
  • vscode terminal full support (since around november 2022 if I remember well, as they upgraded the xterm.js version they use)
  • macos terminal does not render clickable link but it does process the escape codes correctly, so not really breaking the rendering.

The biggest problem with pygments-ansi-color is that it does break the rendering by not following the specification for ANSI escape codes. Even if a terminal is unable to process some codes, it should still be able to ignore them, something that is not happening with this library.

I guess that this could be better fixed in two stages, one that would first make it properly ignore the hyperlink codes, and a second one that would keep render them as links.

RFE: is it possible to start making github releases?🤔

Is it possible next time on release new version make the github release to have entry on https://github.com/chriskuehl/pygments-ansi-color/releases? 🤔

I'm asking because only on make gh release is spread notification about new release to those who have set watch->releases.
My automation process those notification trying make preliminary automated upgrade of building packages which allow save some time on maintaining packaging procedures.

More about gh releases is possible to find on
https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository
https://github.com/marketplace/actions/github-release
https://pgjones.dev/blog/trusted-plublishing-2023/

`AnsiHtmlFormatter` and ANSI-aware shell-like lexers

After a year of usage in my Click Extra project and lots of pain trying to integrate it with Click, Sphinx and Furo, I finally reached a point where my stack of monkey-patch work as intended and validates my efforts.

So now I'm wondering if there are some stuff worth contributing back to pygments-ansi-color. Namely:

ExtendedColorHtmlFormatterMixin is broken in pygments 2.7.3

$ python3 t.py 
<div class="pc-highlight my-2 p-2 d-inline-block mw-100 rounded"><pre><span></span><span class=" -Color -Color-Bold"> -C-BoldBOLDED</span>UNBOLDED
</pre></div>

$ cat t.py 
import pygments.lexers
from pygments.formatters import HtmlFormatter
from pygments_ansi_color import ExtendedColorHtmlFormatterMixin


class ColorHtmlFormatter(ExtendedColorHtmlFormatterMixin, HtmlFormatter):
    pass


def _highlight(s: str) -> str:
    lexer = pygments.lexers.get_lexer_by_name('ansi-color')
    cssclass = 'pc-highlight my-2 p-2 d-inline-block mw-100 rounded'
    formatter = ColorHtmlFormatter(cssclass=cssclass)
    return pygments.highlight(s, lexer, formatter)


def main():
    print(_highlight('\033[1mBOLDED\033[mUNBOLDED'))


if __name__ == '__main__':
    exit(main())

I'll see what I can do to fix it 🤔

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.