Most of the information I ended up using came from a few links in the end:
The Python Powered Turtle – shows how to add scripting support with IronPython
NuGet your Avalon – gives details on easily adding AvalonEdit via NuGet
Python.xshd – Is a file used to add syntax highlighting to AvalonEdit
NOTE: I won’t pretend to know Python/IronPython so I’m not sure how great the Syntax Highlighting is, but it’s better than nothing. Eg I did notice it highlighted the Add method of an ObservableCollection<T> I had, which didn’t seem right.
Anyway, if you don’t want to read the other links and figure things out for yourself it comes down to relatively few lines of code to get everything working once you’ve installed IronPython, added the relevant references to your project, and installed/referenced AvalonEdit (via NuGet).
First the XAML. Just add a reference to the namespace:
xmlns:avalonedit="http://icsharpcode.net/sharpdevelop/avalonedit"
Then add your control for the editor:<avalonedit:TextEditor Name="CodeTextEditor" FontFamily="Consolas" FontSize="10pt" ShowLineNumbers="True"/>
By adding ShowLineNumbers the user will have an easy reference if the script throws an error.Now in the code behind we have…
A few using statements:
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
using IronPython.Hosting;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Highlighting.Xshd;
using System.Xml;
The first 3 are for IronPython, the later 3 are used for AvalonEdit (System.Xml for the XmlTextReader).We need a couple of fields in our MainWindow:
private ScriptEngine _engine; private ScriptScope _scope;Then we hook things up in our Window_Initialized handler (NOT in the constructor like so many bad examples show you, since any exception thrown would get swallowed by a XAML parser exception):
private void Window_Initialized(object sender, EventArgs e) { _engine = Python.CreateEngine(); _scope = _engine.CreateScope(); var runtime = _engine.Runtime; runtime.LoadAssembly(typeof(String).Assembly); runtime.LoadAssembly(typeof(Uri).Assembly); runtime.LoadAssembly( typeof(Source).Assembly ); const string sampleScript = @"from RCS.Uppercut.Entities import * myText = 'ROCK' uc.SetSourceLabel(2,'ON') uc.Sources[0].Label= myText uc.Sources[0].IsOnProgram = 1 uc.Sources[1].IsOnPreview = 1 for source in uc.Sources: source.Label = 'IN' + source.Id.ToString('d2') if ( source.IsOnProgram): source.Label += ' True' else: source.Label += ' False' newSource = Source() newSource.Id = len(uc.Sources) + 1 newSource.Label = 'NewSource' uc.Sources.Add( newSource )"; CodeTextEditor.Text = sampleScript; CodeTextEditor.SyntaxHighlighting = HighlightingLoader.Load( new XmlTextReader( "ICSharpCode.PythonBinding.Resources.Python.xshd" ), HighlightingManager.Instance ); }I’ve left some of my test script in there for you to see how I’ve used a custom type (RCS.Uppercut.Entities.Source).
And finally the code to execute our script in the button click event handler:
private void ExecuteButton_Click(object sender, RoutedEventArgs e) { _scope.SetVariable( "uc", UppercutService ); var code = CodeTextEditor.Text; try { var source = _engine.CreateScriptSourceFromString( code, SourceCodeKind.Statements ); source.Execute( _scope ); } catch ( Exception ex ) { var eo = _engine.GetService<ExceptionOperations>(); var error = eo.FormatException( ex ); MessageBox.Show( error, "There was an Error", MessageBoxButton.OK, MessageBoxImage.Error ); } }Yes it’s really THAT simple!
The end result for my test app can be seen below with a before/after shot:
5 comments:
The xshd file is no longer available?
Updated the link to Python.xshd to a file hosted on my public Dropbox.
Thank you for this info John, I was exactly looking for a way to highlight python with AvalonEdit.
Can I still get the xshd?
Thanks!
Rory
Rory the updated link (click Python.xshd) should work?
Post a Comment