You can create extensions for .NET Interactive in order to create custom experiences including custom visualizations, new magic commands, new subkernels supporting additional languages, and more. Extensions can be distributed using NuGet packages. The extension is activated when the package is loaded by .NET Interactive using #r nuget
.
The simplest way to create an extension is to add a file called extension.dib
into a NuGet package and build the package so that extension.dib
is placed in a folder inside the package called interactive-extensions\dotnet
.
When a package is loaded using #r nuget
, if that file is found inside the package, then it will be run the code in extension.dib
after referencing your packages library (assuming the package contains a library). Because .dib
files support multiple languages, your extension can run code using any of the supported .NET Interactive languages, or even load new kernels with additional languages. The most common approach, though, and the one detailed below, is to use extension.dib
to simply call a method in your library.
The ClockExtension sample illustrates this approach. There's also walkthrough in the form of a notebook that shows you how to build and install it.
Here are most important details of the sample project:
-
The project contains a public
Load
method containing code to extend .NET Interactive. This can be any public method. Taking aKernel
parameter makes it straightforward to write tests for your extension code. -
The
extension.dib
file contains code to call this method, passing in the root kernel. (Note that this code doesn't containusing
directives so as not to clutter up the notebook user's IntelliSense.)#!csharp ClockExtension.ClockKernelExtension.Load(Microsoft.DotNet.Interactive.KernelInvocationContext.Current.HandlingKernel.RootKernel);
-
ClockExtension.csproj
includes a reference to theextension.dib
file that places it in the correct location in the NuGet package:<ItemGroup> <None Include="extension.dib" Pack="true" PackagePath="interactive-extensions/dotnet" /> </ItemGroup>
Give the sample notebook a try to see it working end to end on your machine.
Here are some of the more common things you might want to do when extending .NET Interactive.
You can add to the set of magic commands available in your notebooks. A magic command is defined using System.CommandLine to parse the user's input as well as provide help and completions. A System.CommandLine.Command
is used to define a magic command. The handler you define for the command will be invoked when the user runs the magic command.
Here's an example from the ClockExtension
sample, showing how to define the #!clock
magic command:
public class ClockKernelExtension : IKernelExtension
{
public async Task OnLoadAsync(Kernel kernel)
{
// ...
var hourOption = new Option<int>(new[] { "-o", "--hour" },
"The position of the hour hand");
var minuteOption = new Option<int>(new[] { "-m", "--minute" },
"The position of the minute hand");
var secondOption = new Option<int>(new[] { "-s", "--second" },
"The position of the second hand");
var clockCommand = new Command("#!clock", "Displays a clock showing the current or specified time.")
{
hourOption,
minuteOption,
secondOption
};
//...
kernel.AddDirective(clockCommand);
// ...
}
}
Once the Command
has been added using Kernel.AddDirective
, it's available in the kernel and ready to be used.
System.CommandLine allows users to get help for a magic command just like they can get help on in a command line app. For example, to get help for the #!clock
magic command, you can run #!clock -h
. That produces the following output:
Description:
Displays a clock showing the current or specified time.
Usage:
#!clock [options]
Options:
-o, --hour <hour> The position of the hour hand
-m, --minute <minute> The position of the minute hand
-s, --second <second> The position of the second hand
-?, -h, --help Show help and usage information
By calling the #!clock
magic command, you can draw a lovely purple clock using SVG with the hands at the positions specified:
The extension also changes the default formatting for the System.DateTime
type. This feature is the basis for creating custom visualizations for any .NET type. Before installing the extension, the default output just used the DateTime.ToString
method:
After installing the extension, we get the much more appealing clock drawing, with the hands set to the current time:
The code that does this is also found in the sample's Load
method:
Formatter.Register<DateTime>((date, writer) =>
{
writer.Write(date.DrawSvgClock());
}, "text/html");
The Formatter
API can be used to customize the output for a given .NET type (System.DateTime
) for a mime type ("txt/html"
).