{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" } }, "source": [ "# The `ClockExtension` Sample\n", "\n", "The `ClockExtension` sample walks you through how to create a simple .NET Interactive extension and then package it using NuGet.\n", "\n", "## 1. Build the project\n", "\n", "If you opened this notebook so that its working directory is in the `ClockExtension` project directory, then the following cell will work. Otherwise, you should first switch your working directory to the directory containing this notebook." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "dotnet_interactive": { "language": "pwsh" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "MSBuild version 17.5.0-preview-22620-02+a6f6699d1 for .NET\n", " Determining projects to restore...\n", " All projects are up-to-date for restore.\n", "C:\\Program Files\\dotnet\\sdk\\7.0.200-preview.22628.1\\Sdks\\Microsoft.NET.Sdk\\targets\\Microsoft.NET.RuntimeIdentifierInference.targets(287,5): message NETSDK1057: You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy [C:\\dev\\interactive\\samples\\extensions\\ClockExtension\\ClockExtension.csproj]\n", " ClockExtension -> C:\\dev\\interactive\\samples\\extensions\\ClockExtension\\bin\\Debug\\net7.0\\ClockExtension.dll\n", "\n", "Build succeeded.\n", " 0 Warning(s)\n", " 0 Error(s)\n", "\n", "Time Elapsed 00:00:00.97\n", "MSBuild version 17.5.0-preview-22620-02+a6f6699d1 for .NET\n", " Determining projects to restore...\n", " All projects are up-to-date for restore.\n", "C:\\Program Files\\dotnet\\sdk\\7.0.200-preview.22628.1\\Sdks\\Microsoft.NET.Sdk\\targets\\Microsoft.NET.RuntimeIdentifierInference.targets(287,5): message NETSDK1057: You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy [C:\\dev\\interactive\\samples\\extensions\\ClockExtension\\ClockExtension.csproj]\n", " ClockExtension -> C:\\dev\\interactive\\samples\\extensions\\ClockExtension\\bin\\Debug\\net7.0\\ClockExtension.dll\n", "\n", " Directory: C:\\dev\\interactive\\samples\\extensions\\ClockExtension\\bin\\Debug\n", "\n", "\u001b[32;1mMode LastWriteTime Length Name\u001b[0m\n", "\u001b[32;1m---- ------------- ------ ----\u001b[0m\n", "-a--- 1/19/2023 3:34 PM 9214 \u001b[31;1mClockExtension.1.0.0.nupkg\u001b[0m\n", "-a--- 1/19/2023 3:41 PM 9210 \u001b[31;1mClockExtension.1.0.1.nupkg\u001b[0m\n", "\n" ] } ], "source": [ "# 1. Build the project\n", "dotnet build ClockExtension\n", "\n", "# Clear any older versions of this extension package from your NuGet cache\n", "rm ~/.nuget/packages/ClockExtension -Force -Recurse -ErrorAction Ignore\n", "\n", "# Pack up the NuGet package. \n", "dotnet pack ClockExtension /p:PackageVersion=1.0.0\n", "\n", "# 3. Check that the package is there\n", "Get-ChildItem -Recurse ClockExtension*.nupkg\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" } }, "source": [ "## 2. Load the NuGet package \n", "\n", "Now we're ready to install the extension that packaged up in the NuGet package we just built. We can use the [`#i` directive](https://github.com/dotnet/interactive/blob/main/docs/nuget-overview.md) to add the build output folder to our NuGet sources.\n", "\n", "First, let's make sure the file is there like we expect after the build.\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [ { "data": { "text/plain": [ "✅ The package is there!" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "using System.IO;\n", "\n", "// Create an absolute path since #i doesn't like \n", "var debugOutputFolder = new DirectoryInfo(@\".\\ClockExtension\\bin\\Debug\\\").FullName;\n", "\n", "if (File.Exists(Path.Combine(debugOutputFolder, \"ClockExtension.1.0.0.nupkg\")))\n", "{\n", " \"✅ The package is there!\".Display();\n", "} \n", "else\n", "{\n", " \"❌ Something must have gone wrong with the build. The package isn't there.\".Display();\n", "}\n", "\n", "var nugetSource = $\"nuget:{debugOutputFolder}\";" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" } }, "source": [ "If the package is there, we can include its location as a NuGet source using the `#i` directive. The following syntax shares the `#i` argument including the `nuget:` prefix and the computed fully-qualified path." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [ { "data": { "text/html": [ "
Restore sources
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "#i @csharp:nugetSource" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" } }, "source": [ "Now that the package source is added, we can use `#r` to install the package. " ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "dotnet_interactive": { "language": "csharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [ { "data": { "text/html": [ "
Restore sources
Installed Packages
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "Loading extension script from `C:\\Users\\josequ\\.nuget\\packages\\clockextension\\1.0.0\\interactive-extensions\\dotnet\\extension.dib`" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
ClockExtension is loaded. It adds visualizations for System.DateTime and System.DateTimeOffset. Try it by running: DateTime.Now or #!clock -h
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "#r \"nuget:ClockExtension,1.0.0\"" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" } }, "source": [ "## Try the extension\n", "\n", "As you can see from the output above, the extension is able to explain a bit about what it does. So now we can try it out.\n", "\n", "It adds a custom formatter for `System.DateTime`:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "dotnet_interactive": { "language": "csharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [ { "data": { "text/html": [ "
.NET Interactive
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "DateTime.Now" ] }, { "cell_type": "markdown", "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" } }, "source": [ "The extension output also advised us to run `#!clock -h`. Extensions can add magic commands and all magic commands can provide help." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "dotnet_interactive": { "language": "csharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Description:\r\n", " Displays a clock showing the current or specified time.\r\n", "\r\n", "Usage:\r\n", " #!clock [options]\r\n", "\r\n", "Options:\r\n", " -o, --hour The position of the hour hand\r\n", " -m, --minute The position of the minute hand\r\n", " -s, --second The position of the second hand\r\n", " -?, -h, --help Show help and usage information\r\n", "\r\n", "\r\n" ] } ], "source": [ "#!clock -h" ] }, { "cell_type": "markdown", "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" } }, "source": [ "The `#!clock` magic command help explains how to use options to set the position of the hands on the clock:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "dotnet_interactive": { "language": "csharp" }, "vscode": { "languageId": "polyglot-notebook" } }, "outputs": [ { "data": { "text/html": [ "
.NET Interactive
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "#!clock --hour 12 -m 34 -s 56" ] } ], "metadata": { "kernelspec": { "display_name": ".NET (C#)", "language": "C#", "name": ".net-csharp" }, "polyglot_notebook": { "kernelInfo": { "defaultKernelName": "csharp", "items": [ { "aliases": [ "c#", "C#" ], "languageName": "C#", "name": "csharp" }, { "aliases": [], "name": ".NET" }, { "aliases": [ "f#", "F#" ], "languageName": "F#", "name": "fsharp" }, { "aliases": [], "languageName": "HTML", "name": "html" }, { "aliases": [], "languageName": "KQL", "name": "kql" }, { "aliases": [], "languageName": "Mermaid", "name": "mermaid" }, { "aliases": [ "powershell" ], "languageName": "PowerShell", "name": "pwsh" }, { "aliases": [], "languageName": "SQL", "name": "sql" }, { "aliases": [], "name": "value" }, { "aliases": [ "frontend" ], "name": "vscode" } ] } } }, "nbformat": 4, "nbformat_minor": 2 }