### Initialize Project Dependencies (Windows) Source: https://github.com/devtoys-app/devtoys/blob/main/CONTRIBUTING.md Restores all project dependencies using the init.ps1 script. This should be run after cloning the repository and installing Nuke.Build. ```powershell .\init.ps1 ``` -------------------------------- ### Declaring a GUI Tool Source: https://context7.com/devtoys-app/devtoys/llms.txt This example demonstrates how to declare a GUI tool by implementing the `IGuiTool` interface and using `ToolDisplayInformationAttribute` for metadata. It shows how to define UI elements using a fluent API and handle text input changes. ```APIDOC ## Declaring a GUI Tool — `IGuiTool` + `[ToolDisplayInformationAttribute]` ### Description The primary interface for tools with a visual interface. Implement `IGuiTool`, export it with `[Export(typeof(IGuiTool))]`, and decorate with metadata attributes. The single required member `View` returns a `UIToolView` built with the `GUI` fluent helpers. ```csharp using System.ComponentModel.Composition; using DevToys.Api; using static DevToys.Api.GUI; [Export(typeof(IGuiTool))] [Name("MyBase64Tool")] [ToolDisplayInformation( IconFontName = "FluentSystemIcons", IconGlyph = '\uF020', GroupName = PredefinedCommonToolGroupNames.EncodersDecoders, ResourceManagerAssemblyIdentifier = nameof(MyAssemblyIdentifier), ResourceManagerBaseName = "MyExtension.Strings", ShortDisplayTitleResourceName = nameof(Strings.ShortTitle), LongDisplayTitleResourceName = nameof(Strings.LongTitle), DescriptionResourceName = nameof(Strings.Description), SearchKeywordsResourceName = nameof(Strings.SearchKeywords))] [AcceptedDataTypeName(PredefinedCommonDataTypeNames.Text)] // enables Smart Detection [Order(Before = "SomeOtherTool")] // optional ordering internal sealed class Base64GuiTool : IGuiTool { // Injected by MEF [Import] private ISettingsProvider _settingsProvider = null!; private static readonly SettingDefinition _encodeMode = new("encodeMode", defaultValue: true); private readonly IUIMultiLineTextInput _inputEditor = MultiLineTextInput("input"); private readonly IUIMultiLineTextInput _outputEditor = MultiLineTextInput("output"); public UIToolView View => new UIToolView( SplitGrid() .Vertical() .WithLeftPaneChild( _inputEditor .Title("Input") .Extendable() .OnTextChanged(OnInputChanged)) .WithRightPaneChild( _outputEditor .Title("Output") .ReadOnly() .Extendable())); public void OnDataReceived(string dataTypeName, object? parsedData) { if (dataTypeName == PredefinedCommonDataTypeNames.Text && parsedData is string text) _inputEditor.Text(text); } private ValueTask OnInputChanged(string value) { bool encode = _settingsProvider.GetSetting(_encodeMode); _outputEditor.Text(encode ? Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(value)) : System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(value))); return ValueTask.CompletedTask; } } // Required companion: tells MEF where to find string resources [Export(typeof(IResourceAssemblyIdentifier))] [Name(nameof(MyAssemblyIdentifier))] public sealed class MyAssemblyIdentifier : IResourceAssemblyIdentifier { } ``` ``` -------------------------------- ### Install Nuke.Build Global Tool (Windows) Source: https://github.com/devtoys-app/devtoys/blob/main/CONTRIBUTING.md Installs the Nuke.Build command-line tooling globally on Windows. This is a prerequisite for building the project. ```powershell dotnet tool install Nuke.GlobalTool --global ``` -------------------------------- ### Initialize Project Dependencies (macOS) Source: https://github.com/devtoys-app/devtoys/blob/main/CONTRIBUTING.md Restores all project dependencies using the init.sh script. This should be run after cloning the repository and installing Nuke.Build. ```bash sh init.sh ``` -------------------------------- ### Restore Project Dependencies Source: https://github.com/devtoys-app/devtoys/blob/main/CONTRIBUTING.md Restores all project dependencies using the init.sh script. This command should be run after installing Nuke.Build. ```bash bash init.sh ``` -------------------------------- ### Install Rosetta 2 (macOS Apple Silicon) Source: https://github.com/devtoys-app/devtoys/blob/main/CONTRIBUTING.md Installs Rosetta 2 translation environment on Mac computers with Apple silicon processors. This is required for running x86_64 applications. ```bash softwareupdate --install-rosetta ``` -------------------------------- ### Declare a GUI Tool with `IGuiTool` Source: https://context7.com/devtoys-app/devtoys/llms.txt Implement `IGuiTool` to create a graphical tool. Use `[Export(typeof(IGuiTool))]` and `[ToolDisplayInformationAttribute]` for metadata. The `View` property defines the UI declaratively using the `GUI` fluent API. This example shows a Base64 encoder/decoder tool. ```csharp using System.ComponentModel.Composition; using DevToys.Api; using static DevToys.Api.GUI; [Export(typeof(IGuiTool))] [Name("MyBase64Tool")] [ToolDisplayInformation( IconFontName = "FluentSystemIcons", IconGlyph = '\uF020', GroupName = PredefinedCommonToolGroupNames.EncodersDecoders, ResourceManagerAssemblyIdentifier = nameof(MyAssemblyIdentifier), ResourceManagerBaseName = "MyExtension.Strings", ShortDisplayTitleResourceName = nameof(Strings.ShortTitle), LongDisplayTitleResourceName = nameof(Strings.LongTitle), DescriptionResourceName = nameof(Strings.Description), SearchKeywordsResourceName = nameof(Strings.SearchKeywords))] [AcceptedDataTypeName(PredefinedCommonDataTypeNames.Text)] // enables Smart Detection [Order(Before = "SomeOtherTool")] // optional ordering internal sealed class Base64GuiTool : IGuiTool { // Injected by MEF [Import] private ISettingsProvider _settingsProvider = null!; private static readonly SettingDefinition _encodeMode = new("encodeMode", defaultValue: true); private readonly IUIMultiLineTextInput _inputEditor = MultiLineTextInput("input"); private readonly IUIMultiLineTextInput _outputEditor = MultiLineTextInput("output"); public UIToolView View => new UIToolView( SplitGrid() .Vertical() .WithLeftPaneChild( _inputEditor .Title("Input") .Extendable() .OnTextChanged(OnInputChanged)) .WithRightPaneChild( _outputEditor .Title("Output") .ReadOnly() .Extendable())); public void OnDataReceived(string dataTypeName, object? parsedData) { if (dataTypeName == PredefinedCommonDataTypeNames.Text && parsedData is string text) _inputEditor.Text(text); } private ValueTask OnInputChanged(string value) { bool encode = _settingsProvider.GetSetting(_encodeMode); _outputEditor.Text(encode ? Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(value)) : System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(value))); return ValueTask.CompletedTask; } } ``` ```csharp // Required companion: tells MEF where to find string resources [Export(typeof(IResourceAssemblyIdentifier))] [Name(nameof(MyAssemblyIdentifier))] public sealed class MyAssemblyIdentifier : IResourceAssemblyIdentifier { } ``` -------------------------------- ### Text Input Controls: Multi-line, Single-line, and Diff Source: https://context7.com/devtoys-app/devtoys/llms.txt Provides examples for creating multi-line, single-line, and diff text input fields using the Monaco Editor. Configure features like syntax highlighting, extendability, line numbers, text wrapping, and hover tooltips. Includes event handling for text changes. ```csharp using static DevToys.Api.GUI; // ── Multi-line editor with JSON syntax highlighting ─────────────────────────── IUIMultiLineTextInput jsonEditor = MultiLineTextInput("json-input", "json") // "json" activates Monaco's JSON language .Title("JSON Input") .Extendable() // user can expand to full-screen .AlwaysShowLineNumber() .NeverWrap() .Highlight( new UIHighlightedTextSpan(0, 5, UIHighlightedTextSpanColor.Error), new UIHighlightedTextSpan(10, 8, UIHighlightedTextSpanColor.Warning)) .HoverTooltip(new UIHoverTooltip(0, 5, "Unexpected token here")) .OnTextChanged((string newText) => { // Validate and react — runs on every keystroke bool valid = TryParseJson(newText, out _); return ValueTask.CompletedTask; }); // ── Single-line with extra command-bar button ───────────────────────────────── IUISingleLineTextInput urlInput = SingleLineTextInput("url-input") .Title("URL") .Editable() .CanCopyWhenEditable() .CommandBarExtraContent( Button("open-btn").Icon("FluentSystemIcons", '\uF6B7').OnClick(OpenInBrowser)) .OnTextChanged(OnUrlChanged); // ── Diff view ───────────────────────────────────────────────────────────────── IUIDiffTextInput differ = DiffTextInput("diff") .Title("Compare") .Extendable() .SplitView() // side-by-side (InlineView() for unified) .OriginalText("Hello, World!") .ModifiedText("Hello, DevToys!"); ValueTask OpenInBrowser() { /* ... */ return ValueTask.CompletedTask; } ValueTask OnUrlChanged(string v) { return ValueTask.CompletedTask; } ``` -------------------------------- ### Create and Bind Settings UI - C# Source: https://context7.com/devtoys-app/devtoys/llms.txt Shows how to create settings rows with titles, descriptions, and icons, and bind them to setting definitions using Handle(). Supports boolean switches and enum dropdowns with custom callbacks. ```csharp using static DevToys.Api.GUI; // Boolean setting → automatically creates and binds a Switch IUISetting indentSetting = Setting("indent") .Title("Indent output") .Description("Pretty-print the output with indentation.") .Icon("FluentSystemIcons", '\uF4A8') .Handle( _settingsProvider, _indentJsonSetting, // SettingDefinition stateDescriptionWhenOn: "Enabled", stateDescriptionWhenOff: "Disabled", onToggled: (bool value) => { RefreshOutput(); return ValueTask.CompletedTask; }); // Enum setting → automatically creates and binds a SelectDropDownList IUISetting indentSizeSetting = Setting("indent-size") .Title("Indent size") .Handle( _settingsProvider, _indentSizeSetting, // SettingDefinition (enum) onOptionSelected: (IndentSize size) => { RefreshOutput(); return ValueTask.CompletedTask; }, Item("2 spaces", IndentSize.Two), Item("4 spaces", IndentSize.Four), Item("Tab", IndentSize.Tab)); ``` -------------------------------- ### Settings Management with SettingDefinition and ISettingsProvider Source: https://context7.com/devtoys-app/devtoys/llms.txt Demonstrates how to define, read, write, and reset type-safe, persistable settings using `SettingDefinition` and `ISettingsProvider`. It also shows how to subscribe to setting changes. ```APIDOC ## Settings Management ### Description Manages type-safe, persistable settings with optional custom serialization. Settings are automatically namespaced to the calling assembly to prevent collisions between extensions. ### Usage Define settings as static fields using `SettingDefinition`: ```csharp // Define settings as static fields (the name is auto-namespaced to the calling assembly) private static readonly SettingDefinition _indentJson = new("IndentJson", defaultValue: true); private static readonly SettingDefinition _indentSize = new("IndentSize", defaultValue: 4); private static readonly SettingDefinition _outputFormat = new( "OutputFormat", defaultValue: MyEnum.Compact, serialize: v => v.ToString(), deserialize: s => Enum.Parse(s)); ``` In a GUI tool constructor or View builder, import `ISettingsProvider`: ```csharp [Import] private ISettingsProvider _settingsProvider = null!; ``` **Reading Settings:** ```csharp bool indent = _settingsProvider.GetSetting(_indentJson); // Returns default value if not set int size = _settingsProvider.GetSetting(_indentSize); // Returns default value if not set ``` **Writing Settings:** ```csharp _settingsProvider.SetSetting(_indentJson, false); ``` **Resetting Settings to Default:** ```csharp _settingsProvider.ResetSetting(_indentJson); ``` **Reacting to External Changes:** ```csharp _settingsProvider.SettingChanged += (_, e) => { if (e.SettingName == _indentJson.Name) Console.WriteLine($"IndentJson changed to {e.NewValue}"); }; ``` ``` -------------------------------- ### GUI Layout with Stack, SplitGrid, and Grid Source: https://context7.com/devtoys-app/devtoys/llms.txt Utilize `GUI.Stack()`, `GUI.SplitGrid()`, and `GUI.Grid()` for declarative UI composition. Import `using static DevToys.Api.GUI;` to use these methods directly. ```csharp using static DevToys.Api.GUI; // ── Stack: linear horizontal or vertical arrangement ────────────────────────── IUIStack toolbar = Stack() .Horizontal() .SmallSpacing() .WithChildren( Button("encode-btn", "Encode").AccentAppearance().OnClick(OnEncodeClicked), Button("decode-btn", "Decode").NeutralAppearance().OnClick(OnDecodeClicked), Switch("utf8-switch").Title("UTF-8").On() .OnToggle(isOn => { /* handle toggle */ return ValueTask.CompletedTask; })); ``` ```csharp // ── SplitGrid: two-pane resizable split ─────────────────────────────────────── IUISplitGrid twoPane = SplitGrid() .Vertical() // vertical divider → left/right panes .LeftPaneLength(new UIGridLength(1, UIGridUnitType.Fraction)) .RightPaneLength(new UIGridLength(1, UIGridUnitType.Fraction)) .MinimumLength(100) .WithLeftPaneChild(MultiLineTextInput("left").Title("Original")) .WithRightPaneChild(MultiLineTextInput("right").Title("Result").ReadOnly()); ``` ```csharp // ── Grid: row/column grid with typed enum indices ───────────────────────────── enum Row { Options = 0, Content = 1 } enum Column { Input = 0, Output = 1 } IUIGrid layout = Grid() .Rows( (Row.Options, Auto), (Row.Content, Fraction(1))) .Columns( (Column.Input, Fraction(1)), (Column.Output, Fraction(1))) .Cells( Cell(Row.Options, Column.Input, Label("opt-label", "Options")), Cell(Row.Options, Column.Output, Button("copy-btn", "Copy")), Cell(Row.Content, Column.Input, MultiLineTextInput("editor-in")), Cell(Row.Content, Column.Output, MultiLineTextInput("editor-out").ReadOnly())); ``` -------------------------------- ### Create Labels with Styles - C# Source: https://context7.com/devtoys-app/devtoys/llms.txt Demonstrates creating different label styles (heading, body, caption) using the GUI.Label() method. Use UILabelStyle to match app typography. NeverWrap() prevents text wrapping for specific labels. ```csharp using static DevToys.Api.GUI; IUILabel heading = Label("h1", "JSON Formatter") .Style(UILabelStyle.Subtitle) .NeverWrap(); IUILabel body = Label("desc") .Text("Paste or type your JSON below.") .Style(UILabelStyle.Body) .WrapIfNeeded(); IUILabel caption = Label("caption", "v2.0.0") .Style(UILabelStyle.Caption); ``` -------------------------------- ### Interactive Controls: Buttons, Switches, Drop-downs Source: https://context7.com/devtoys-app/devtoys/llms.txt Demonstrates the creation and configuration of interactive UI elements including buttons with different appearances, toggle switches, and customizable drop-down lists. Includes event handling for clicks, toggles, and item selections. ```csharp using static DevToys.Api.GUI; // ── Button variants ─────────────────────────────────────────────────────────── IUIButton primaryBtn = Button("primary") .Text("Convert") .Icon("FluentSystemIcons", '\uF20A') .AccentAppearance() .OnClick(async () => { await DoConversionAsync(); }); IUIButton linkBtn = Button("link") .Text("Learn more") .HyperlinkAppearance() .OnClick(() => { /* navigate */ }); // ── Switch ──────────────────────────────────────────────────────────────────── IUISwitch modeSwitch = Switch("encode-mode") .Title("Mode") .OnText("Encode") .OffText("Decode") .On() .OnToggle((bool isOn) => { // isOn == true → encode mode selected return ValueTask.CompletedTask; }); // ── Drop-down list ──────────────────────────────────────────────────────────── IUISelectDropDownList encodingPicker = SelectDropDownList("encoding") .Title("Encoding") .WithItems( Item("UTF-8", "utf8"), Item("UTF-16", "utf16"), Item("ASCII", "ascii")) .Select(0) // pre-select first item .OnItemSelected((IUIDropDownListItem? item) => { string encoding = item?.Value as string ?? "utf8"; return ValueTask.CompletedTask; }); ``` -------------------------------- ### GUI Layout Containers Source: https://context7.com/devtoys-app/devtoys/llms.txt Provides core layout containers for composing tool UIs declaratively: `GUI.Stack()`, `GUI.SplitGrid()`, and `GUI.Grid()`. ```APIDOC ## GUI Layout ### Description Three core layout containers for composing tool UIs declaratively: `GUI.Stack()`, `GUI.SplitGrid()`, and `GUI.Grid()`. ### Stack Used for linear horizontal or vertical arrangement of UI elements. ```csharp using static DevToys.Api.GUI; IUIStack toolbar = Stack() .Horizontal() .SmallSpacing() .WithChildren( Button("encode-btn", "Encode").AccentAppearance().OnClick(OnEncodeClicked), Button("decode-btn", "Decode").NeutralAppearance().OnClick(OnDecodeClicked), Switch("utf8-switch").Title("UTF-8").On() .OnToggle(isOn => { /* handle toggle */ return ValueTask.CompletedTask; })); ``` ### SplitGrid Creates a two-pane resizable split view. ```csharp IUISplitGrid twoPane = SplitGrid() .Vertical() // vertical divider → left/right panes .LeftPaneLength(new UIGridLength(1, UIGridUnitType.Fraction)) .RightPaneLength(new UIGridLength(1, UIGridUnitType.Fraction)) .MinimumLength(100) .WithLeftPaneChild(MultiLineTextInput("left").Title("Original")) .WithRightPaneChild(MultiLineTextInput("right").Title("Result").ReadOnly()); ``` ### Grid Arranges UI elements in a grid with rows and columns, supporting typed enum indices. ```csharp enum Row { Options = 0, Content = 1 } enum Column { Input = 0, Output = 1 } IUIGrid layout = Grid() .Rows( (Row.Options, Auto), (Row.Content, Fraction(1))) .Columns( (Column.Input, Fraction(1)), (Column.Output, Fraction(1))) .Cells( Cell(Row.Options, Column.Input, Label("opt-label", "Options")), Cell(Row.Options, Column.Output, Button("copy-btn", "Copy")), Cell(Row.Content, Column.Input, MultiLineTextInput("editor-in")), Cell(Row.Content, Column.Output, MultiLineTextInput("editor-out").ReadOnly())); ``` ``` -------------------------------- ### Create a CLI Tool with ICommandLineTool Source: https://context7.com/devtoys-app/devtoys/llms.txt Implement ICommandLineTool to add a new sub-command to the DevToys CLI. Decorate properties with CommandLineOptionAttribute to define command-line arguments. Ensure the tool is exported and named correctly. ```csharp using System.ComponentModel.Composition; using DevToys.Api; using Microsoft.Extensions.Logging; [Export(typeof(ICommandLineTool))] [Name("Base64CommandLineTool")] [CommandName( Name = "base64", Alias = "b64", DescriptionResourceName = nameof(Strings.CliDescription), ResourceManagerBaseName = "MyExtension.Strings")] [TargetPlatform(Platform.Windows)] [TargetPlatform(Platform.MacOS)] [TargetPlatform(Platform.Linux)] internal sealed class Base64CommandLineTool : ICommandLineTool { [CommandLineOption( Name = "input", Alias = "i", IsRequired = true, DescriptionResourceName = nameof(Strings.InputOptionDescription))] internal string? Input { get; set; } [CommandLineOption( Name = "decode", Alias = "d", DescriptionResourceName = nameof(Strings.DecodeOptionDescription))] internal bool Decode { get; set; } = false; public ValueTask InvokeAsync(ILogger logger, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(Input)) { logger.LogError("Input is required."); return ValueTask.FromResult(1); } try { string result = Decode ? System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(Input)) : Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(Input)); Console.WriteLine(result); return ValueTask.FromResult(0); // success exit code } catch (Exception ex) { logger.LogError(ex, "Operation failed."); return ValueTask.FromResult(1); } } } ``` -------------------------------- ### Define and Use Type-Safe Settings Source: https://context7.com/devtoys-app/devtoys/llms.txt Define settings using `SettingDefinition` and manage them with `ISettingsProvider`. Settings are automatically namespaced. Ensure `ISettingsProvider` is imported. ```csharp private static readonly SettingDefinition _indentJson = new("IndentJson", defaultValue: true); private static readonly SettingDefinition _indentSize = new("IndentSize", defaultValue: 4); private static readonly SettingDefinition _outputFormat = new( "OutputFormat", defaultValue: MyEnum.Compact, serialize: v => v.ToString(), deserialize: s => Enum.Parse(s)); [Import] private ISettingsProvider _settingsProvider = null!; private void UseSettings() { // Read bool indent = _settingsProvider.GetSetting(_indentJson); // true int size = _settingsProvider.GetSetting(_indentSize); // 4 // Write _settingsProvider.SetSetting(_indentJson, false); // Reset to default _settingsProvider.ResetSetting(_indentJson); // React to external changes (e.g. user toggled from Settings page) _settingsProvider.SettingChanged += (_, e) => { if (e.SettingName == _indentJson.Name) Console.WriteLine($"IndentJson changed to {e.NewValue}"); }; } ``` -------------------------------- ### Implement Smart Detection with IDataTypeDetector Source: https://context7.com/devtoys-app/devtoys/llms.txt Integrate with DevToys' Smart Detection system by implementing IDataTypeDetector. This allows your tool to be suggested when specific data patterns are detected on the clipboard. Ensure the detector returns a successful DataDetectionResult. ```csharp using System.ComponentModel.Composition; using DevToys.Api; // jwt-token type extends json (base type); detection runs after the json detector succeeds [Export(typeof(IDataTypeDetector))] [DataTypeName("jwt-token", baseName: PredefinedCommonDataTypeNames.Json)] [TargetPlatform(Platform.Windows)] [TargetPlatform(Platform.WASM)] internal sealed class JwtDataTypeDetector : IDataTypeDetector { public ValueTask TryDetectDataAsync( object rawData, DataDetectionResult? resultFromBaseDetector, CancellationToken cancellationToken) { // rawData is the raw clipboard string; resultFromBaseDetector holds the parsed JSON (if any) if (rawData is not string text || string.IsNullOrWhiteSpace(text)) return ValueTask.FromResult(DataDetectionResult.Unsuccessful); string[] parts = text.Trim().Split('.'); if (parts.Length != 3) return ValueTask.FromResult(DataDetectionResult.Unsuccessful); try { // Attempt to decode each segment — a valid JWT has three Base64Url segments foreach (string part in parts) { string padded = part.PadRight(part.Length + (4 - part.Length % 4) % 4, '='); Convert.FromBase64String(padded.Replace('-', '+').Replace('_', '/')); } // Pass the raw token as the parsed data for the tool to consume return ValueTask.FromResult(new DataDetectionResult(true, text)); } catch { return ValueTask.FromResult(DataDetectionResult.Unsuccessful); } } } ``` -------------------------------- ### File Selector and Reader - C# Source: https://context7.com/devtoys-app/devtoys/llms.txt Implements a file selector UI for accepting multiple files with type limitations and provides methods for reading file content via SandboxedFileReader. Remember to dispose of file readers after use. ```csharp using static DevToys.Api.GUI; // ── File selector UI ────────────────────────────────────────────────────────── IUIFileSelector fileSelector = FileSelector("file-picker") .CanSelectManyFiles() .LimitFileTypesTo(".json", ".txt") // or .LimitFileTypesToImages() .OnFilesSelected(async (SandboxedFileReader[] files) => { foreach (SandboxedFileReader file in files) { await ProcessFileAsync(file, CancellationToken.None); file.Dispose(); // IMPORTANT: dispose when done } }); // ── Reading from a SandboxedFileReader ──────────────────────────────────────── private static async Task ProcessFileAsync( SandboxedFileReader file, CancellationToken cancellationToken) { // Option A: get a Stream using Stream stream = await file.GetNewAccessToFileContentAsync(cancellationToken); using var reader = new StreamReader(stream); string content = await reader.ReadToEndAsync(cancellationToken); Console.WriteLine($"[{file.FileName}] {content.Length} chars"); // Option B: copy to another stream (e.g., MemoryStream) using var ms = new MemoryStream(); await file.CopyFileContentToAsync(ms, cancellationToken); ms.Position = 0; // use ms … // Option C: create from a FileInfo on disk SandboxedFileReader fromDisk = SandboxedFileReader.FromFileInfo(new FileInfo("/tmp/data.json")); // … use fromDisk, then: fromDisk.Dispose(); } ``` -------------------------------- ### Notification Bar: InfoBar Source: https://context7.com/devtoys-app/devtoys/llms.txt Shows how to create and manage notification bars (InfoBars) for displaying status messages. Supports different severity levels (info, warning, error, success), custom actions, and programmatic control over visibility. Includes event handling for closing the bar. ```csharp using static DevToys.Api.GUI; IUIInfoBar statusBar = InfoBar("status") .Title("Conversion failed") .Description("The input contains invalid Base64 characters.") .Error() .NonClosable() .WithActionButton("Show Details", isAccent: false, () => { // called when user clicks — bar closes automatically return ValueTask.CompletedTask; }) .OnClose(() => { // called when user dismisses the bar return ValueTask.CompletedTask; }); // Show / hide programmatically statusBar.Open(); // makes bar visible statusBar.Close(); // hides bar // Severity variants InfoBar("info-bar").Informational(); InfoBar("warn-bar").Warning(); InfoBar("ok-bar").Success(); ``` -------------------------------- ### Push DevToys Package to Chocolatey Source: https://github.com/devtoys-app/devtoys/blob/main/chocolatey/README.md After generating the .nupkg file, use this command to push it to the Chocolatey repository. Ensure the file path is correct. ```powershell choco push .\DevToys.versiongenerated.nupkg --source https://push.chocolatey.org/ ``` -------------------------------- ### Interactive Controls Source: https://context7.com/devtoys-app/devtoys/llms.txt Provides documentation for interactive UI elements including buttons, switches, and drop-down lists with configurable appearances and event handlers. ```APIDOC ## Button Variants ### Description Defines button components with different appearance styles (primary, link) and event handlers for click actions. Buttons can also include icons. ### Method Signature `GUI.Button(string name)` ### Configuration Options - `.Text(string text)`: Sets the button's display text. - `.Icon(string iconFamily, char iconCode)`: Assigns an icon to the button. - `.AccentAppearance()`: Applies a primary accent style to the button. - `.HyperlinkAppearance()`: Styles the button as a hyperlink. - `.OnClick(Action handler)`: Registers a callback for when the button is clicked. ### Example Usage ```csharp using static DevToys.Api.GUI; // Primary button IUIButton primaryBtn = Button("primary") .Text("Convert") .Icon("FluentSystemIcons", '\uF20A') .AccentAppearance() .OnClick(async () => { await DoConversionAsync(); }); // Link button IUIButton linkBtn = Button("link") .Text("Learn more") .HyperlinkAppearance() .OnClick(() => { /* navigate */ }); ``` ## Switch Control ### Description Implements a toggle switch control with customizable on/off text labels and an event handler that is triggered when the switch's state changes. ### Method Signature `GUI.Switch(string name)` ### Configuration Options - `.Title(string title)`: Sets the title for the switch. - `.OnText(string text)`: Text to display when the switch is in the 'on' state. - `.OffText(string text)`: Text to display when the switch is in the 'off' state. - `.On()`: Sets the switch to the 'on' state by default. - `.Off()`: Sets the switch to the 'off' state by default. - `.OnToggle(Func handler)`: Registers a callback that receives the new state (true for on, false for off) when the switch is toggled. ### Example Usage ```csharp using static DevToys.Api.GUI; IUISwitch modeSwitch = Switch("encode-mode") .Title("Mode") .OnText("Encode") .OffText("Decode") .On() .OnToggle((bool isOn) => { // isOn == true → encode mode selected return ValueTask.CompletedTask; }); ``` ## Drop-down List ### Description Provides a configurable drop-down list control that allows users to select an item from a predefined list. It supports setting a default selected item and handling item selection events. ### Method Signature `GUI.SelectDropDownList(string name)` ### Configuration Options - `.Title(string title)`: Sets the title for the drop-down list. - `.WithItems(params IUISelectableItem[] items)`: Populates the drop-down list with specified items. - `.Select(int index)`: Pre-selects an item by its index. - `.OnItemSelected(Func handler)`: Registers a callback that is invoked when an item is selected. The selected item is passed to the handler. ### Example Usage ```csharp using static DevToys.Api.GUI; IUISelectDropDownList encodingPicker = SelectDropDownList("encoding") .Title("Encoding") .WithItems( Item("UTF-8", "utf8"), Item("UTF-16", "utf16"), Item("ASCII", "ascii")) .Select(0) // pre-select first item .OnItemSelected((IUIDropDownListItem? item) => { string encoding = item?.Value as string ?? "utf8"; return ValueTask.CompletedTask; }); ``` ``` -------------------------------- ### Implement CLI Progress Bar with ConsoleProgressBar Source: https://context7.com/devtoys-app/devtoys/llms.txt Use ConsoleProgressBar to display progress for long-running operations in ICommandLineTool implementations. Ensure cancellation tokens are checked and operations are awaited. ```csharp public async ValueTask InvokeAsync(ILogger logger, CancellationToken cancellationToken) { using var progressBar = new ConsoleProgressBar(); long total = GetTotalItems(); for (long i = 0; i < total; i++) { cancellationToken.ThrowIfCancellationRequested(); await ProcessItemAsync(i, cancellationToken); double pct = (double)(i + 1) / total; progressBar.Report(pct); // updates the terminal bar in place } Console.WriteLine("\nDone."); return 0; } ``` -------------------------------- ### Add Chocolatey API Key Source: https://github.com/devtoys-app/devtoys/blob/main/chocolatey/README.md Use this command to set your Chocolatey API key for pushing packages. Replace 'yourapikey' with your actual key obtained from Chocolatey Community. ```powershell choco apikey --key yourapikey --source https://push.chocolatey.org/ ``` -------------------------------- ### Define a Tool Group with GuiToolGroup Source: https://context7.com/devtoys-app/devtoys/llms.txt Register a new category in the DevToys application's navigation pane by implementing GuiToolGroup. Tools can then reference this group by its defined name. Configure the group's icon, display title, and accessible name. ```csharp using System.ComponentModel.Composition; using DevToys.Api; [Export(typeof(GuiToolGroup))] [Name("MyCustomGroup")] [Order(After = PredefinedCommonToolGroupNames.Generators)] internal sealed class MyCustomGroup : GuiToolGroup { [ImportingConstructor] internal MyCustomGroup() { IconFontName = "FluentSystemIcons"; IconGlyph = '\uF6FA'; // puzzle piece glyph DisplayTitle = "My Tools"; AccessibleName = "My Custom Tools Group"; } } ``` -------------------------------- ### Text Editors Source: https://context7.com/devtoys-app/devtoys/llms.txt Monaco Editor-backed text inputs supporting syntax highlighting, read-only mode, scroll synchronization, highlighting spans, hover tooltips, and inline/side-by-side diff. ```APIDOC ## Multi-line editor with JSON syntax highlighting ### Description Creates a multi-line text input component with support for syntax highlighting, extendable view, line numbers, text wrapping, highlighting specific text spans, and hover tooltips. It also includes an event handler for text changes. ### Method Signature `GUI.MultiLineTextInput(string name, string language)` ### Configuration Options - `.Title(string title)`: Sets the title of the text input. - `.Extendable()`: Allows the user to expand the input to full-screen. - `.AlwaysShowLineNumber()`: Ensures line numbers are always visible. - `.NeverWrap()`: Disables text wrapping. - `.Highlight(params UIHighlightedTextSpan[] spans)`: Applies highlighting to specified text spans. - `.HoverTooltip(UIHoverTooltip tooltip)`: Adds a hover tooltip to a specific text span. - `.OnTextChanged(Func handler)`: Registers a callback for when the text content changes. ### Example Usage ```csharp using static DevToys.Api.GUI; IUIMultiLineTextInput jsonEditor = MultiLineTextInput("json-input", "json") // "json" activates Monaco's JSON language .Title("JSON Input") .Extendable() .AlwaysShowLineNumber() .NeverWrap() .Highlight( new UIHighlightedTextSpan(0, 5, UIHighlightedTextSpanColor.Error), new UIHighlightedTextSpan(10, 8, UIHighlightedTextSpanColor.Warning)) .HoverTooltip(new UIHoverTooltip(0, 5, "Unexpected token here")) .OnTextChanged((string newText) => { // Validate and react — runs on every keystroke bool valid = TryParseJson(newText, out _); return ValueTask.CompletedTask; }); ``` ## Single-line text input with command-bar button ### Description Creates a single-line text input component that is editable, allows copying text when editable, and can include an extra button in its command bar. It also provides an event handler for text changes. ### Method Signature `GUI.SingleLineTextInput(string name)` ### Configuration Options - `.Title(string title)`: Sets the title of the text input. - `.Editable()`: Makes the text input editable. - `.CanCopyWhenEditable()`: Allows copying the text when the input is in editable mode. - `.CommandBarExtraContent(IUIButton button)`: Adds a custom button to the command bar. - `.OnTextChanged(Func handler)`: Registers a callback for when the text content changes. ### Example Usage ```csharp using static DevToys.Api.GUI; IUISingleLineTextInput urlInput = SingleLineTextInput("url-input") .Title("URL") .Editable() .CanCopyWhenEditable() .CommandBarExtraContent( Button("open-btn").Icon("FluentSystemIcons", '\uF6B7').OnClick(OpenInBrowser)) .OnTextChanged(OnUrlChanged); ValueTask OpenInBrowser() { /* ... */ return ValueTask.CompletedTask; } ValueTask OnUrlChanged(string v) { return ValueTask.CompletedTask; } ``` ## Diff Text Input ### Description Creates a text input component designed for comparing two versions of text, supporting extendable views and side-by-side or unified display. ### Method Signature `GUI.DiffTextInput(string name)` ### Configuration Options - `.Title(string title)`: Sets the title of the diff input. - `.Extendable()`: Allows the user to expand the input to full-screen. - `.SplitView()`: Displays the differences in a side-by-side view. - `.InlineView()`: Displays the differences in a unified view. - `.OriginalText(string text)`: Sets the original text content. - `.ModifiedText(string text)`: Sets the modified text content. ### Example Usage ```csharp using static DevToys.Api.GUI; IUIDiffTextInput differ = DiffTextInput("diff") .Title("Compare") .Extendable() .SplitView() .OriginalText("Hello, World!") .ModifiedText("Hello, DevToys!"); ``` ```