Eine der schöneren Libraries die Python zu bieten hat ist sicherlich die Syntax-Highlighting-Library Pygments: Damit wird es sehr einfach möglich, eine Quellcodedatei nicht einfach nur als Textdatei anzuzeigen, sondern mit Markierungen für Klassennamen, Schlüsselwörter, Variablennamen und andere Syntaxelemente zu versehen. Dies sieht dann beispielsweise so aus wie bei meinen Models für PowerDNS.

Pygments benutzt dazu zwei Kernelemente, einen Lexer und einen Formatter. Der Lexer liest den Quellcode ein, analysiert ihn und identifiziert Syntaxelemente. Der Formatter nutzt diese Information, um die Quellcode-Datei, versehen mit verschiedenen Annotationen, im gewünschten Zielformat auszugeben.

Dabei gibt’s Lexer für alle nur erdenklichen Sprachen:

In [1]: from pygments.lexers import                                              
Display all 200 possibilities? (y or n)                                          
ABAPLexer                 GroffLexer                RagelObjectiveCLexer         
ActionScript3Lexer        HaskellLexer              RagelRubyLexer               
ActionScriptLexer         HtmlDjangoLexer           RawTokenLexer                
AntlrActionScriptLexer    HtmlGenshiLexer           RebolLexer                   
AntlrCSharpLexer          HtmlLexer                 RedcodeLexer                 
AntlrCppLexer             HtmlPhpLexer              RhtmlLexer                   
AntlrJavaLexer            HtmlSmartyLexer           RstLexer                     
AntlrLexer                IniLexer                  RubyConsoleLexer             
AntlrObjectiveCLexer      IoLexer                   RubyLexer                    
AntlrPerlLexer            IrcLogsLexer              SLexer                       
AntlrPythonLexer          JavaLexer                 ScalaLexer                   
AntlrRubyLexer            JavascriptDjangoLexer     SchemeLexer                  
ApacheConfLexer           JavascriptErbLexer        SmalltalkLexer               
AppleScriptLexer          JavascriptGenshiLexer     SmartyLexer                  
AsymptoteLexer            JavascriptLexer           SourcesListLexer             
BBCodeLexer               JavascriptPhpLexer        SqlLexer                     
BaseMakefileLexer         JavascriptSmartyLexer     SqliteConsoleLexer           
BashLexer                 JspLexer                  SquidConfLexer               
BashSessionLexer          LEXERS                    TclLexer                     
BatchLexer                LighttpdConfLexer         TcshLexer                    
BefungeLexer              LiterateHaskellLexer      TexLexer                     
BooLexer                  LlvmLexer                 TextLexer                    
BrainfuckLexer            LogtalkLexer              ValaLexer                    
CLexer                    LuaLexer                  VbNetAspxLexer               
CMakeLexer                MOOCodeLexer              VbNetLexer                   
CObjdumpLexer             MakefileLexer             VimLexer                     
CSharpAspxLexer           MakoCssLexer              XmlDjangoLexer               
CSharpLexer               MakoHtmlLexer             XmlErbLexer
CheetahHtmlLexer          MakoJavascriptLexer       XmlLexer
CheetahJavascriptLexer    MakoLexer                 XmlPhpLexer
CheetahLexer              MakoXmlLexer              XmlSmartyLexer
CheetahXmlLexer           MatlabLexer               XsltLexer
ClassNotFound             MatlabSessionLexer        YamlLexer
ClojureLexer              MiniDLexer                _asybuiltins
CommonLispLexer           ModelicaLexer             _automodule
CppLexer                  MoinWikiLexer             _clbuiltins
CppObjdumpLexer           MuPADLexer                _iter_lexerclasses
CssDjangoLexer            MxmlLexer                 _lexer_cache
CssErbLexer               MySqlLexer                _load_lexers
CssGenshiLexer            MyghtyCssLexer            _luabuiltins
CssLexer                  MyghtyHtmlLexer           _mapping
CssPhpLexer               MyghtyJavascriptLexer     _phpbuiltins
CssSmartyLexer            MyghtyLexer               _vimbuiltins
CythonLexer               MyghtyXmlLexer            agile
DLexer                    NasmLexer                 asm
DObjdumpLexer             NewspeakLexer             basename
DarcsPatchLexer           NginxConfLexer            bytes
DebianControlLexer        NumPyLexer                compiled
DelphiLexer               ObjdumpLexer              dotnet
DiffLexer                 ObjectiveCLexer           find_lexer_class
DjangoLexer               OcamlLexer                find_plugin_lexers
DylanLexer                OocLexer                  fnmatch
ErbLexer                  PerlLexer                 functional
ErlangLexer               PhpLexer                  get_all_lexers
ErlangShellLexer          PovrayLexer               get_lexer_by_name
EvoqueHtmlLexer           PrologLexer               get_lexer_for_filename
EvoqueLexer               Python3Lexer              get_lexer_for_mimetype
EvoqueXmlLexer            Python3TracebackLexer     guess_lexer
FortranLexer              PythonConsoleLexer        guess_lexer_for_filename
GLShaderLexer             PythonLexer               math
GasLexer                  PythonTracebackLexer      other
GenshiLexer               RagelCLexer               parsers
GenshiTextLexer           RagelCppLexer             special
GettextLexer              RagelDLexer               templates
GherkinLexer              RagelEmbeddedLexer        text
GnuplotLexer              RagelJavaLexer            web
GoLexer                   RagelLexer

Auch bei den Formattern bleiben keine Wünsche offen, da ist von HTML über BBCode bis hin zu LaTeX alles zu haben.

Um eine Datei zu formatieren, reicht dann einfach sowas:

from pygments            import highlight
from pygments.lexers     import get_lexer_for_filename, ClassNotFound
from pygments.formatters import HtmlFormatter

try:
    lexer = get_lexer_for_filename( filename )

except ClassNotFound:
    print "Lexer nicht gefunden..."

else:
    formatter = HtmlFormatter()
    highlighted_code = highlight( code, lexer, formatter )

Das war’s, den Rest macht Pygments. Bequemer geht’s kaum. :)

Hinweis für Django-Nutzer:

Wenn du vorhast Pygments zu benutzen um Code auf einer Webseite zu highlighten, wirst du eine CSS-Datei mit Definitionen für Elemente ausliefern müssen, die Pygments zum Highlighten benutzt. Das geht am einfachsten indem du eine View schreibst, die diese Datei generiert, und auf diese View verlinkst:

def pygmentstyles( request ):
    from pygments.formatters import HtmlFormatter
    return HttpResponse( HtmlFormatter().get_style_defs('.highlight'), 'text/css' )
Add post to: Delicious Reddit Slashdot Digg Technorati Google