diff --git a/MonacoEditorComponent/CodeEditor/CodeEditor.Methods.cs b/MonacoEditorComponent/CodeEditor/CodeEditor.Methods.cs index 94c4be8..6674b35 100644 --- a/MonacoEditorComponent/CodeEditor/CodeEditor.Methods.cs +++ b/MonacoEditorComponent/CodeEditor/CodeEditor.Methods.cs @@ -11,7 +11,7 @@ namespace Monaco /// /// Action delegate for and . /// - public delegate void CommandHandler([ReadOnlyArray] string[] parameters); + public delegate void CommandHandler([ReadOnlyArray] object[] parameters); /// /// This file contains Monaco IEditor method implementations we can call on our control. @@ -122,7 +122,23 @@ namespace Monaco public IAsyncOperation AddCommandAsync(int keybinding, CommandHandler handler, string context) { var name = "Command" + keybinding; - _parentAccessor.RegisterActionWithParameters(name, (parameters) => { handler?.Invoke(parameters); }); + _parentAccessor.RegisterActionWithParameters(name, (parameters) => + { + if (parameters != null && parameters.Length > 0) + { + object[] args = new object[parameters.Length]; + for (int i = 0; i < parameters.Length; i++) + { + args[i] = JsonConvert.DeserializeObject(parameters[i]); + } + + handler?.Invoke(args); + } + else + { + handler?.Invoke(new object[] {}); + } + }); return InvokeScriptAsync("addCommand", new object[] { keybinding, name, context }).AsAsyncOperation(); } diff --git a/MonacoEditorComponent/CodeEditor/CodeEditor.html b/MonacoEditorComponent/CodeEditor/CodeEditor.html index 1c29a28..be10527 100644 --- a/MonacoEditorComponent/CodeEditor/CodeEditor.html +++ b/MonacoEditorComponent/CodeEditor/CodeEditor.html @@ -22,6 +22,7 @@
+ diff --git a/MonacoEditorComponent/Monaco/Languages/CodeLens.cs b/MonacoEditorComponent/Monaco/Languages/CodeLens.cs new file mode 100644 index 0000000..420284f --- /dev/null +++ b/MonacoEditorComponent/Monaco/Languages/CodeLens.cs @@ -0,0 +1,17 @@ +using Newtonsoft.Json; + +namespace Monaco.Languages +{ + public sealed class CodeLens + { + [JsonProperty("command", NullValueHandling = NullValueHandling.Ignore)] + public Command Command { get; set; } + + [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] + public string Id { get; set; } + + [JsonProperty("range", NullValueHandling = NullValueHandling.Ignore)] + public IRange Range { get; set; } + } +} + diff --git a/MonacoEditorComponent/Monaco/Languages/CodeLensList.cs b/MonacoEditorComponent/Monaco/Languages/CodeLensList.cs new file mode 100644 index 0000000..15e189b --- /dev/null +++ b/MonacoEditorComponent/Monaco/Languages/CodeLensList.cs @@ -0,0 +1,11 @@ +namespace Monaco.Languages +{ + using Newtonsoft.Json; + + public sealed class CodeLensList // IDisposible? + { + [JsonProperty("lenses", NullValueHandling = NullValueHandling.Ignore)] + public CodeLens[] Lenses { get; set; } + } +} + diff --git a/MonacoEditorComponent/Monaco/Languages/CodeLensProvider.cs b/MonacoEditorComponent/Monaco/Languages/CodeLensProvider.cs new file mode 100644 index 0000000..ffa5384 --- /dev/null +++ b/MonacoEditorComponent/Monaco/Languages/CodeLensProvider.cs @@ -0,0 +1,15 @@ +using Monaco.Editor; +using System; +using System.ComponentModel; +using Windows.Foundation; + +namespace Monaco.Languages +{ + public interface CodeLensProvider + { + IAsyncOperation ProvideCodeLensesAsync(IModel model); + + IAsyncOperation ResolveCodeLensAsync(IModel model, CodeLens codeLens); + } +} + diff --git a/MonacoEditorComponent/Monaco/LanguagesHelper.cs b/MonacoEditorComponent/Monaco/LanguagesHelper.cs index ccb4efe..8c2ad54 100644 --- a/MonacoEditorComponent/Monaco/LanguagesHelper.cs +++ b/MonacoEditorComponent/Monaco/LanguagesHelper.cs @@ -44,6 +44,43 @@ namespace Monaco return null; } + public IAsyncAction RegisterCodeLensProviderAsync(string languageId, CodeLensProvider provider) + { + if (_editor.TryGetTarget(out CodeEditor editor)) + { + editor._parentAccessor.RegisterEvent("ProvideCodeLenses" + languageId, async (args) => + { + var list = await provider.ProvideCodeLensesAsync(editor.GetModel()); + + if (list != null) + { + return JsonConvert.SerializeObject(list); + } + + return null; + }); + + editor._parentAccessor.RegisterEvent("ResolveCodeLens" + languageId, async (args) => + { + if (args != null && args.Length >= 1) + { + var lens = await provider.ResolveCodeLensAsync(editor.GetModel(), JsonConvert.DeserializeObject(args[0])); + + if (lens != null) + { + return JsonConvert.SerializeObject(lens); + } + } + + return null; + }); + + return editor.InvokeScriptAsync("registerCodeLensProvider", new object[] { languageId }).AsAsyncAction(); + } + + return null; + } + public IAsyncAction RegisterColorProviderAsync(string languageId, DocumentColorProvider provider) { if (_editor.TryGetTarget(out CodeEditor editor)) diff --git a/MonacoEditorComponent/MonacoEditorComponent.csproj b/MonacoEditorComponent/MonacoEditorComponent.csproj index 245a884..a59d303 100644 --- a/MonacoEditorComponent/MonacoEditorComponent.csproj +++ b/MonacoEditorComponent/MonacoEditorComponent.csproj @@ -210,6 +210,9 @@ + + + @@ -266,6 +269,10 @@ Designer + + MSBuild:Compile + Designer + MSBuild:Compile Designer diff --git a/MonacoEditorComponent/ts-helpermethods/otherScriptsToBeOrganized.ts b/MonacoEditorComponent/ts-helpermethods/otherScriptsToBeOrganized.ts index b435a18..bbee024 100644 --- a/MonacoEditorComponent/ts-helpermethods/otherScriptsToBeOrganized.ts +++ b/MonacoEditorComponent/ts-helpermethods/otherScriptsToBeOrganized.ts @@ -29,11 +29,11 @@ var addAction = function (action: monaco.editor.IActionDescriptor) { }; var addCommand = function (keybindingStr, handlerName, context) { - return editor.addCommand(parseInt(keybindingStr), (args) => { + return editor.addCommand(parseInt(keybindingStr), function () { let objs = []; - if (args) { - for (let i = 0; i < args.length; i++) { - objs.push(JSON.stringify(args[i])); + if (arguments) { // Use arguments as Monaco will pass each as it's own parameter, so we don't know how many that may be. + for (let i = 1; i < arguments.length; i++) { // Skip first one as that's the sender? + objs.push(JSON.stringify(arguments[i])); } } Parent.callActionWithParameters(handlerName, objs); @@ -124,4 +124,4 @@ var keyDown = function (event) { event.stopImmediatePropagation(); return false; } -}; \ No newline at end of file +}; diff --git a/MonacoEditorComponent/ts-helpermethods/registerCodeLensProvider.ts b/MonacoEditorComponent/ts-helpermethods/registerCodeLensProvider.ts new file mode 100644 index 0000000..8d63d01 --- /dev/null +++ b/MonacoEditorComponent/ts-helpermethods/registerCodeLensProvider.ts @@ -0,0 +1,22 @@ +/// +declare var Parent: ParentAccessor; + +var registerCodeLensProvider = function (languageId) { + return monaco.languages.registerCodeLensProvider(languageId, { + provideCodeLenses: function (model, token) { + return Parent.callEvent("ProvideCodeLenses" + languageId, []).then(result => { + if (result) { + return JSON.parse(result); + } + }); + }, + resolveCodeLens: function (model, codeLens, token) { + return Parent.callEvent("ResolveCodeLens" + languageId, [JSON.stringify(codeLens)]).then(result => { + if (result) { + return JSON.parse(result); + } + }); + } + // TODO: onDidChange, don't know what this does. + }); +} \ No newline at end of file diff --git a/MonacoEditorTestApp/Helpers/EditorCodeLensProvider.cs b/MonacoEditorTestApp/Helpers/EditorCodeLensProvider.cs new file mode 100644 index 0000000..181a439 --- /dev/null +++ b/MonacoEditorTestApp/Helpers/EditorCodeLensProvider.cs @@ -0,0 +1,55 @@ +using Monaco; +using Monaco.Editor; +using Monaco.Languages; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Windows.Foundation; + +namespace MonacoEditorTestApp.Helpers +{ + public class EditorCodeLensProvider : CodeLensProvider + { + private string _commandId; + + public EditorCodeLensProvider(string commandId) + { + _commandId = commandId; + } + + public IAsyncOperation ProvideCodeLensesAsync(IModel model) + { + return AsyncInfo.Run(async delegate (CancellationToken cancellationToken) + { + return new CodeLensList() + { + Lenses = new CodeLens[] { + new CodeLens() + { + Id = "Second Line", + Range = new Range(2, 1, 3, 1), + Command = new Command() + { + Id = _commandId, + Title = "Second Line Command", + Arguments = new object[] { "Arg 1" , 5, new float[] { 4.5f, 0.3f } }, // Note: This 3rd element array will come back as a JArray TODO? + Tooltip = "This is a CodeLens Command" + } + } + } + }; + }); + } + + public IAsyncOperation ResolveCodeLensAsync(IModel model, CodeLens codeLens) + { + return AsyncInfo.Run(delegate (CancellationToken cancelationToken) { + return Task.FromResult(codeLens); + }); + } + } +} diff --git a/MonacoEditorTestApp/MainPage.xaml.cs b/MonacoEditorTestApp/MainPage.xaml.cs index 6e08f4a..9064d15 100644 --- a/MonacoEditorTestApp/MainPage.xaml.cs +++ b/MonacoEditorTestApp/MainPage.xaml.cs @@ -8,6 +8,7 @@ using System.Diagnostics; using System.Linq; using Windows.Storage; using Windows.UI; +using Windows.UI.Core; using Windows.UI.Popups; using Windows.UI.Text; using Windows.UI.Xaml; @@ -101,6 +102,15 @@ namespace MonacoEditorTestApp var available_languages = Editor.Languages.GetLanguagesAsync(); //Debugger.Break(); + // Code Lens Action + string cmdId = await Editor.AddCommandAsync(0, async (args) => + { + var md = new MessageDialog("You hit the CodeLens command " + args[0].ToString()); + await md.ShowAsync(); + }); + + await Editor.Languages.RegisterCodeLensProviderAsync("csharp", new EditorCodeLensProvider(cmdId)); + await Editor.Languages.RegisterColorProviderAsync("csharp", new ColorProvider()); await Editor.Languages.RegisterCompletionItemProviderAsync("csharp", new LanguageProvider()); @@ -264,8 +274,7 @@ namespace MonacoEditorTestApp // You can now do this with a Command as well, see above. // Skip await, so we can read intercept value. - #pragma warning disable CS4014 - Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, async () => + _ = Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, async () => { var md = new MessageDialog("You Hit Ctrl+Enter!"); await md.ShowAsync(); @@ -273,7 +282,6 @@ namespace MonacoEditorTestApp // Refocus on CodeEditor Editor.Focus(FocusState.Programmatic); }); - #pragma warning restore CS4014 // Intercept input so we don't add a newline. e.Handled = true; diff --git a/MonacoEditorTestApp/MonacoEditorTestApp.csproj b/MonacoEditorTestApp/MonacoEditorTestApp.csproj index 9b635b8..e156759 100644 --- a/MonacoEditorTestApp/MonacoEditorTestApp.csproj +++ b/MonacoEditorTestApp/MonacoEditorTestApp.csproj @@ -96,6 +96,7 @@ App.xaml + diff --git a/README.md b/README.md index b23436e..c2a0f2d 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ The following Monaco Editor features are currently supported by this component b - [Markers](https://microsoft.github.io/monaco-editor/api/modules/monaco.editor.html#setmodelmarkers) and [Decorations](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.imodeldeltadecoration.html) (See #35) - [Actions](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonecodeeditor.html#addaction) and [Commands](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandalonecodeeditor.html#addcommand) - Basic [Language Features](https://code.visualstudio.com/api/language-extensions/programmatic-language-features) + - [CodeLens](https://microsoft.github.io/monaco-editor/api/modules/monaco.languages.html#registercodelensprovider) (onDidChange not supported) - [Color](https://microsoft.github.io/monaco-editor/api/modules/monaco.languages.html#registercolorprovider) - [CompletionItem](https://microsoft.github.io/monaco-editor/api/modules/monaco.languages.html#registercompletionitemprovider) (IntelliSense, Snippets) - [Hover](https://microsoft.github.io/monaco-editor/api/modules/monaco.languages.html#registerhoverprovider)