Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added language service support for auto-completion and semantic token #1175

Merged
merged 1 commit into from
Jun 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace DevToys.Api;

/// <summary>
/// Provides a set of helper method to play around with cancellation tokens.
/// </summary>
public static class CancellationTokenExtension
{
/// <summary>
/// Converts the <see cref="CancellationToken"/> to a <see cref="Task"/>
/// that cancels when the <see cref="CancellationToken"/> is being canceled.
/// </summary>
public static Task AsTask(this CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<object>();
cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken), useSynchronizationContext: false);
return tcs.Task;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ public interface IUIMultiLineTextInput : IUISingleLineTextInput
/// </summary>
IReadOnlyList<UIHoverTooltip> HoverTooltips { get; }

/// <summary>
/// Gets the text input to synchronize the scroll bar with.
/// </summary>
IUIMultiLineTextInput? TextInputToSynchronizeScrollBarWith { get; }

/// <summary>
/// Gets the programming language name to use when colorizing the text in the control.
/// </summary>
Expand All @@ -33,6 +38,11 @@ public interface IUIMultiLineTextInput : IUISingleLineTextInput
/// </summary>
UITextWrapMode WrapMode { get; }

/// <summary>
/// Gets how the line number should be displayed in the text editor. Default is <see cref="UITextLineNumber.Auto"/>.
/// </summary>
UITextLineNumber LineNumberMode { get; }

/// <summary>
/// Gets the primary selection of the text control. When the selection length is 0, the span indicates the caret position.
/// </summary>
Expand All @@ -48,6 +58,11 @@ public interface IUIMultiLineTextInput : IUISingleLineTextInput
/// </summary>
event EventHandler? HighlightedSpansChanged;

/// <summary>
/// Raised when <see cref="TextInputToSynchronizeScrollBarWith"/> is changed.
/// </summary>
event EventHandler? TextInputToSynchronizeScrollBarWithChanged;

/// <summary>
/// Raised when <see cref="SyntaxColorizationLanguageName"/> is changed.
/// </summary>
Expand All @@ -63,6 +78,11 @@ public interface IUIMultiLineTextInput : IUISingleLineTextInput
/// </summary>
event EventHandler? WrapModeChanged;

/// <summary>
/// Raised when <see cref="LineNumberMode"/> is changed.
/// </summary>
event EventHandler? LineNumberModeChanged;

/// <summary>
/// Raised when <see cref="Selection"/> is changed.
/// </summary>
Expand All @@ -74,9 +94,11 @@ internal class UIMultilineTextInput : UISingleLineTextInput, IUIMultiLineTextInp
{
private IReadOnlyList<UIHoverTooltip>? _hoverTooltip;
private IReadOnlyList<UIHighlightedTextSpan>? _highlightedSpans;
private IUIMultiLineTextInput? _textInputToSynchronizeScrollBarWith;
private string? _syntaxColorizationLanguageName;
private bool _isExtendableToFullScreen;
private UITextWrapMode _wrapMode = UITextWrapMode.Auto;
private UITextLineNumber _lineNumberMode = UITextLineNumber.Auto;
private TextSpan? _selection;

internal UIMultilineTextInput(string? id)
Expand All @@ -96,6 +118,24 @@ public IReadOnlyList<UIHoverTooltip> HoverTooltips
internal set => SetPropertyValue(ref _hoverTooltip, value, HoverTooltipChanged);
}

public IUIMultiLineTextInput? TextInputToSynchronizeScrollBarWith
{
get => _textInputToSynchronizeScrollBarWith;
internal set
{
if (value is null && _textInputToSynchronizeScrollBarWith is not null)
{
((UIMultilineTextInput)_textInputToSynchronizeScrollBarWith).TextInputToSynchronizeScrollBarWith = null;
}

if (SetPropertyValue(ref _textInputToSynchronizeScrollBarWith, value, TextInputToSynchronizeScrollBarWithChanged)
&& value is not null)
{
((UIMultilineTextInput)value).TextInputToSynchronizeScrollBarWith = this;
}
}
}

public string SyntaxColorizationLanguageName
{
get => _syntaxColorizationLanguageName ?? string.Empty;
Expand All @@ -114,6 +154,12 @@ public UITextWrapMode WrapMode
internal set => SetPropertyValue(ref _wrapMode, value, WrapModeChanged);
}

public UITextLineNumber LineNumberMode
{
get => _lineNumberMode;
internal set => SetPropertyValue(ref _lineNumberMode, value, LineNumberModeChanged);
}

public TextSpan Selection
{
get => _selection ?? new TextSpan(0, 0);
Expand Down Expand Up @@ -141,9 +187,11 @@ internal set

public event EventHandler? HoverTooltipChanged;
public event EventHandler? HighlightedSpansChanged;
public event EventHandler? TextInputToSynchronizeScrollBarWithChanged;
public event EventHandler? SyntaxColorizationLanguageNameChanged;
public event EventHandler? IsExtendableToFullScreenChanged;
public event EventHandler? WrapModeChanged;
public event EventHandler? LineNumberModeChanged;
public event EventHandler? SelectionChanged;
}

Expand Down Expand Up @@ -179,7 +227,14 @@ public static IUIMultiLineTextInput MultiLineTextInput(string? id)
/// This component is powered by Monaco Editor.
/// </remarks>
/// <param name="id">An optional unique identifier for this UI element.</param>
/// <param name="programmingLanguageName">the programming language name to use to colorize the text in the control.</param>
/// <param name="programmingLanguageName">
/// <para>
/// The programming language name to use to colorize the text in the control.
/// </para>
/// <para>
/// Many languages are supported by default, such as JSON or XML. You can create a custom language support using <see cref="ILanguageService"/>.
/// </para>
/// </param>
public static IUIMultiLineTextInput MultiLineTextInput(string? id, string programmingLanguageName)
{
return new UIMultilineTextInput(id).Language(programmingLanguageName);
Expand All @@ -203,6 +258,20 @@ public static IUIMultiLineTextInput HoverTooltip(this IUIMultiLineTextInput elem
return element;
}

/// <summary>
/// Synchronizes the scroll bars of the given element with the scroll bars of the other element.
/// </summary>
/// <remarks>
/// <para>
/// Many languages are supported by default, such as JSON or XML. You can create a custom language support using <see cref="ILanguageService"/>.
/// </para>
/// </remarks>
public static IUIMultiLineTextInput SynchronizeScrollBarWith(this IUIMultiLineTextInput element, IUIMultiLineTextInput? otherElement)
{
((UIMultilineTextInput)element).TextInputToSynchronizeScrollBarWith = otherElement;
return element;
}

/// <summary>
/// Sets the programming language name to use to colorize the text in the control.
/// </summary>
Expand Down Expand Up @@ -260,6 +329,33 @@ public static IUIMultiLineTextInput NeverWrap(this IUIMultiLineTextInput element
return element;
}

/// <summary>
/// Indicates that the line number should be automatically shown or hidden depending on the user's settings.
/// </summary>
public static IUIMultiLineTextInput AutoLineNumber(this IUIMultiLineTextInput element)
{
((UIMultilineTextInput)element).LineNumberMode = UITextLineNumber.Auto;
return element;
}

/// <summary>
/// Indicates that the line number should always be displayed in the editor.
/// </summary>
public static IUIMultiLineTextInput AlwaysShowLineNumber(this IUIMultiLineTextInput element)
{
((UIMultilineTextInput)element).LineNumberMode = UITextLineNumber.Show;
return element;
}

/// <summary>
/// Indicates that the line number should never be displayed in the editor.
/// </summary>
public static IUIMultiLineTextInput NeverShowLineNumber(this IUIMultiLineTextInput element)
{
((UIMultilineTextInput)element).LineNumberMode = UITextLineNumber.Hide;
return element;
}

/// <summary>
/// Selects the given span in the text document.
/// </summary>
Expand Down
22 changes: 22 additions & 0 deletions src/app/dev/DevToys.Api/Tool/GUI/Components/UITextLineNumber.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace DevToys.Api;

/// <summary>
/// Describes how the line number should be displayed in the text editor.
/// </summary>
public enum UITextLineNumber
{
/// <summary>
/// Automatically show or hide the line number depending on the user's settings.
/// </summary>
Auto,

/// <summary>
/// Show the line number.
/// </summary>
Show,

/// <summary>
/// Do not show the line number.
/// </summary>
Hide
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
namespace DevToys.Api;

/// <summary>
/// Represents an item in the auto-completion list of <see cref="IUIMultiLineTextInput"/>.
/// </summary>
[DebuggerDisplay($"Title = {{{nameof(Title)}}}, Kind = {{{nameof(Kind)}}}")]
public class AutoCompletionItem
{
/// <summary>
/// Initializes a new instance of the <see cref="AutoCompletionItem"/> class.
/// </summary>
/// <param name="title">The title of the completion item.</param>
/// <param name="kind">The kind of this completion item. Based on the kind an icon is chosen by the editor.</param>
/// <param name="textToInsert">A snippet that should be inserted in a document when selecting this completion item.</param>
public AutoCompletionItem(string title, AutoCompletionItemKind kind, string textToInsert)
{
Guard.IsNotNullOrEmpty(title);
Guard.IsNotNull(textToInsert);
Title = title;
Kind = kind;
TextToInsert = textToInsert;
}

/// <summary>
/// Gets or sets the title of the completion item.
/// </summary>
public string Title { get; set; }

/// <summary>
/// Gets or sets the description of the completion item, displayed to the right of the suggestion list.
/// </summary>
public string? Description { get; set; }

/// <summary>
/// Gets or sets the kind of this completion item. Based on the kind an icon is chosen by the editor.
/// </summary>
public AutoCompletionItemKind Kind { get; set; }

/// <summary>
/// Gets or sets a human-readable string that represents a doc-comment. This string can be in Markdown format.
/// </summary>
public string? Documentation { get; set; }

/// <summary>
/// Gets or sets whether the item should be selected when showing.
/// </summary>
/// <remarks>
/// <para>
/// Note that only one completion item can be selected and that the editor decides which item that is.
/// The rule is that the first item of those that match best is selected.
/// </para>
/// </remarks>
public bool? ShouldBePreselected { get; set; }

/// <summary>
/// Gets or sets a snippet that should be inserted in a document when selecting this completion item.
/// </summary>
/// <remarks>
/// <para>
/// You can use tab-stopped placeholders by using a syntax like <c>${1:foo}</c> and <c>${2:bar}</c>.
/// </para>
/// <para>
/// Example:
/// </para>
/// <example>
/// <code>
/// registerCustomer(${1:firstName}, ${2:lastName})
/// </code>
/// </example>
/// </remarks>
public string TextToInsert { get; set; }
}
Loading
Loading