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.
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()