Pygments Syntax Highlighting using the Silverlight DLR


An interactive demonstration of the pygments syntax highlighting python module in the browsers using the Silverlight Dynamic Language Runtime.

The sample code below is the code that drives this sample.

I blogged about writing the initial sample, then about updating the application to use a background thread to do the processing.

Language

Code

Preview

Loading Silverlight Application
from System.Windows import Application
from System.Windows.Controls import UserControl
from System.Windows.Browser import HtmlPage
from System import EventHandler
from System.ComponentModel import BackgroundWorker, DoWorkEventHandler


class App:
    
    def __init__(self):

        # HTML DOM elements
        self.input = HtmlPage.Document.GetElementById("input")
        self.source = HtmlPage.Document.GetElementById("output")
        self.language = HtmlPage.Document.GetElementById("lang")
        self.message = HtmlPage.Document.GetElementById("load_message")
        self.message_element = HtmlPage.Document.GetElementById("loading")
        
        # start initial pygmentize    
        self.start_pygmentize()
        
        # register events
        self.input.AttachEvent('onkeyup', EventHandler( self.update_handler )) 
        self.language.AttachEvent('onchange', EventHandler( self.update_handler ))

    
    def show_message(self, message):
        
        self.message.SetProperty("innerHTML",message)
        self.message_element.SetStyleAttribute("display", "block");
    
    
    def hide_message(self):

        self.message.SetProperty("innerHTML","")
        self.message_element.SetStyleAttribute("display", "none");

    
    def start_pygmentize(self):
        
        # update application state
        self.input_changed = False        
        self.pygmentizing = True
        self.show_message("pygmentizing..")
        
        # get paremters
        input = self.input.GetProperty("value")
        language = self.language.value
       
        # setup background worker
        worker = BackgroundWorker()
        worker.DoWork += DoWorkEventHandler(self.worker)
        worker.RunWorkerCompleted += self.complete
        
        # start the worker
        worker.RunWorkerAsync( (input,language) )


    def worker(self, sender, e):
        
        # do work off UI thread. 
        e.Result = self.pygmentize_text(e.Argument[0],e.Argument[1])
        

    # handle language or input changes by pygmentizing 
    def update_handler(self, sender, e):
        
        if self.pygmentizing:
        
            # worker is in progress, so note just note input had change
            self.input_changed = True
        
        else:
        
            # worker is idle, so start it
            self.start_pygmentize()
                
    def pygmentize_text(self, text, language):
        # attempt to pygmentize input with current language 
        try:

            from pygments import highlight
            from pygments.lexers import get_lexer_by_name
            from pygments.formatters import HtmlFormatter
                
            lexer = get_lexer_by_name( language, stripall=True)
            formatter = HtmlFormatter(linenos=False, cssclass="source")
            markup = highlight(text, lexer, formatter)

            return markup

        except:

            return "Error Generating Markup"    
    
    def complete(self, sender, e):

        if e.Error:

            # handle errors/exceptions in worker
            self.source.SetProperty("innerHTML",e.Error.Message)
        
        else: 
        
            # show the result
            self.source.SetProperty("innerHTML",e.Result)
        
        if self.input_changed:
 
            # input has changed, starty pygmentize again
            self.start_pygmentize()
       
        else:
            
            # no work queued
            self.pygmentizing = False
            self.hide_message()

            
# Do it!    
App()
       
Get Microsoft Silverlight