mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-29 09:18:01 +01:00
Move classes to separate files
This commit is contained in:
79
Terminal.Gui/Core/Autocomplete/Autocomplete.cd
Normal file
79
Terminal.Gui/Core/Autocomplete/Autocomplete.cd
Normal file
@@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ClassDiagram MajorVersion="1" MinorVersion="1">
|
||||
<Class Name="Terminal.Gui.AppendAutocomplete" Collapsed="true">
|
||||
<Position X="0.5" Y="6.5" Width="2" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAgAABAAQIAAAAAAAAAAAAABAAAIAQAgAEIAggAIAA=</HashCode>
|
||||
<FileName>Core\Autocomplete\AppendAutocomplete.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="Terminal.Gui.AutocompleteBase" Collapsed="true">
|
||||
<Position X="1.75" Y="5.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAQgAAAAAUAAIAAAAAIAAAAAAAEAIAQIgQAIQAAAMBA=</HashCode>
|
||||
<FileName>Core\Autocomplete\AutocompleteBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="Terminal.Gui.PopupAutocomplete" Collapsed="true">
|
||||
<Position X="2.75" Y="6.5" Width="1.5" />
|
||||
<NestedTypes>
|
||||
<Class Name="Terminal.Gui.PopupAutocomplete.Popup" Collapsed="true">
|
||||
<TypeIdentifier>
|
||||
<NewMemberFileName>Core\Autocomplete\PopupAutocomplete.cs</NewMemberFileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
</NestedTypes>
|
||||
<TypeIdentifier>
|
||||
<HashCode>IAEhAAQAASBEQAAAAAIBAAgYAAAAIAwAwKAAQACBAAA=</HashCode>
|
||||
<FileName>Core\Autocomplete\PopupAutocomplete.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="Terminal.Gui.SingleWordSuggestionGenerator" BaseTypeListCollapsed="true">
|
||||
<Position X="6.25" Y="3.5" Width="3" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>CEAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAIAA=</HashCode>
|
||||
<FileName>Core\Autocomplete\SingleWordSuggestionGenerator.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="Terminal.Gui.Suggestion">
|
||||
<Position X="4.5" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAEAAAAAABAAAAAAAAAAAAAAAAAAAAAE=</HashCode>
|
||||
<FileName>Core\Autocomplete\Suggestion.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="Terminal.Gui.TextFieldAutocomplete" Collapsed="true">
|
||||
<Position X="1.5" Y="7.5" Width="2" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAgAAAAAAAAAA=</HashCode>
|
||||
<FileName>Views\TextField.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="Terminal.Gui.TextViewAutocomplete" Collapsed="true">
|
||||
<Position X="3.75" Y="7.5" Width="2.25" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAgAAAAAAAAAA=</HashCode>
|
||||
<FileName>Views\TextView.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Interface Name="Terminal.Gui.IAutocomplete">
|
||||
<Position X="1.75" Y="0.5" Width="2.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAQgAAAAAUAAIAAAAAAAAAAAAAEAIAQIgQAIQAAAMBA=</HashCode>
|
||||
<FileName>Core\Autocomplete\IAutocomplete.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<ShowAsAssociation>
|
||||
<Property Name="SuggestionGenerator" />
|
||||
</ShowAsAssociation>
|
||||
</Interface>
|
||||
<Interface Name="Terminal.Gui.ISuggestionGenerator">
|
||||
<Position X="6.25" Y="1.75" Width="2.25" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAA=</HashCode>
|
||||
<FileName>Core\Autocomplete\ISuggestionGenerator.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Font Name="Segoe UI" Size="9" />
|
||||
</ClassDiagram>
|
||||
@@ -7,109 +7,6 @@ using Rune = System.Rune;
|
||||
|
||||
namespace Terminal.Gui {
|
||||
|
||||
public interface ISuggestionGenerator
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Populates <see cref="Suggestions"/> with all strings in <see cref="AllSuggestions"/> that
|
||||
/// match with the current cursor position/text in the <see cref="HostControl"/>.
|
||||
/// </summary>
|
||||
/// <param name="columnOffset">The column offset. Current (zero - default), left (negative), right (positive).</param>
|
||||
IEnumerable<Suggestion> GenerateSuggestions (List<Rune> currentLine, int idx);
|
||||
|
||||
bool IsWordChar (Rune rune);
|
||||
|
||||
}
|
||||
|
||||
public class SingleWordSuggestionGenerator : ISuggestionGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// The full set of all strings that can be suggested.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual List<string> AllSuggestions { get; set; } = new List<string> ();
|
||||
|
||||
public IEnumerable<Suggestion> GenerateSuggestions (List<Rune> currentLine, int idx)
|
||||
{
|
||||
// if there is nothing to pick from
|
||||
if (AllSuggestions.Count == 0) {
|
||||
return Enumerable.Empty<Suggestion>();
|
||||
}
|
||||
|
||||
var currentWord = IdxToWord (currentLine, idx);
|
||||
|
||||
if (string.IsNullOrWhiteSpace (currentWord)) {
|
||||
return Enumerable.Empty<Suggestion>();
|
||||
} else {
|
||||
return AllSuggestions.Where (o =>
|
||||
o.StartsWith (currentWord, StringComparison.CurrentCultureIgnoreCase) &&
|
||||
!o.Equals (currentWord, StringComparison.CurrentCultureIgnoreCase)
|
||||
).Select(o=>new Suggestion(currentWord.Length,o))
|
||||
.ToList ().AsReadOnly ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return true if the given symbol should be considered part of a word
|
||||
/// and can be contained in matches. Base behavior is to use <see cref="char.IsLetterOrDigit(char)"/>
|
||||
/// </summary>
|
||||
/// <param name="rune"></param>
|
||||
/// <returns></returns>
|
||||
public virtual bool IsWordChar (Rune rune)
|
||||
{
|
||||
return Char.IsLetterOrDigit ((char)rune);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Given a <paramref name="line"/> of characters, returns the word which ends at <paramref name="idx"/>
|
||||
/// or null. Also returns null if the <paramref name="idx"/> is positioned in the middle of a word.
|
||||
/// </para>
|
||||
///
|
||||
/// <para>
|
||||
/// Use this method to determine whether autocomplete should be shown when the cursor is at
|
||||
/// a given point in a line and to get the word from which suggestions should be generated.
|
||||
/// Use the <paramref name="columnOffset"/> to indicate if search the word at left (negative),
|
||||
/// at right (positive) or at the current column (zero) which is the default.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="line"></param>
|
||||
/// <param name="idx"></param>
|
||||
/// <param name="columnOffset"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual string IdxToWord (List<Rune> line, int idx, int columnOffset = 0)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder ();
|
||||
var endIdx = idx;
|
||||
|
||||
// get the ending word index
|
||||
while (endIdx < line.Count) {
|
||||
if (IsWordChar (line [endIdx])) {
|
||||
endIdx++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// It isn't a word char then there is no way to autocomplete that word
|
||||
if (endIdx == idx && columnOffset != 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// we are at the end of a word. Work out what has been typed so far
|
||||
while (endIdx-- > 0) {
|
||||
if (IsWordChar (line [endIdx])) {
|
||||
sb.Insert (0, (char)line [endIdx]);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sb.ToString ();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class AutocompleteBase : IAutocomplete {
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -5,44 +5,6 @@ using Rune = System.Rune;
|
||||
|
||||
namespace Terminal.Gui {
|
||||
|
||||
/// <summary>
|
||||
/// A replacement suggestion made by <see cref="IAutocomplete"/>
|
||||
/// </summary>
|
||||
public class Suggestion {
|
||||
/// <summary>
|
||||
/// The number of characters to remove at the current cursor position
|
||||
/// before adding the <see cref="Replacement"/>
|
||||
/// </summary>
|
||||
public int Remove { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The user visible description for the <see cref="Replacement"/>. Typically
|
||||
/// this would be the same as <see cref="Replacement"/> but may vary in advanced
|
||||
/// use cases (e.g. Title= "ctor", Replacement = "MyClass()\n{\n}")
|
||||
/// </summary>
|
||||
public string Title {get;}
|
||||
|
||||
/// <summary>
|
||||
/// The replacement text that will be added
|
||||
/// </summary>
|
||||
public string Replacement { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="Suggestion"/> class.
|
||||
/// </summary>
|
||||
/// <param name="remove"></param>
|
||||
/// <param name="replacement"></param>
|
||||
/// <param name="title">User visible title for the suggestion or null if the same
|
||||
/// as <paramref name="replacement"/>.</param>
|
||||
public Suggestion (int remove, string replacement, string title = null)
|
||||
{
|
||||
Remove = remove;
|
||||
Replacement = replacement;
|
||||
Title = title ?? replacement;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders an overlay on another view at a given point that allows selecting
|
||||
/// from a range of 'autocomplete' options.
|
||||
|
||||
19
Terminal.Gui/Core/Autocomplete/ISuggestionGenerator.cs
Normal file
19
Terminal.Gui/Core/Autocomplete/ISuggestionGenerator.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Collections.Generic;
|
||||
using Rune = System.Rune;
|
||||
|
||||
namespace Terminal.Gui {
|
||||
public interface ISuggestionGenerator
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Populates <see cref="Suggestions"/> with all strings in <see cref="AllSuggestions"/> that
|
||||
/// match with the current cursor position/text in the <see cref="HostControl"/>.
|
||||
/// </summary>
|
||||
/// <param name="columnOffset">The column offset. Current (zero - default), left (negative), right (positive).</param>
|
||||
IEnumerable<Suggestion> GenerateSuggestions (List<Rune> currentLine, int idx);
|
||||
|
||||
bool IsWordChar (Rune rune);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Rune = System.Rune;
|
||||
|
||||
namespace Terminal.Gui {
|
||||
public class SingleWordSuggestionGenerator : ISuggestionGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// The full set of all strings that can be suggested.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual List<string> AllSuggestions { get; set; } = new List<string> ();
|
||||
|
||||
public IEnumerable<Suggestion> GenerateSuggestions (List<Rune> currentLine, int idx)
|
||||
{
|
||||
// if there is nothing to pick from
|
||||
if (AllSuggestions.Count == 0) {
|
||||
return Enumerable.Empty<Suggestion>();
|
||||
}
|
||||
|
||||
var currentWord = IdxToWord (currentLine, idx);
|
||||
|
||||
if (string.IsNullOrWhiteSpace (currentWord)) {
|
||||
return Enumerable.Empty<Suggestion>();
|
||||
} else {
|
||||
return AllSuggestions.Where (o =>
|
||||
o.StartsWith (currentWord, StringComparison.CurrentCultureIgnoreCase) &&
|
||||
!o.Equals (currentWord, StringComparison.CurrentCultureIgnoreCase)
|
||||
).Select(o=>new Suggestion(currentWord.Length,o))
|
||||
.ToList ().AsReadOnly ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return true if the given symbol should be considered part of a word
|
||||
/// and can be contained in matches. Base behavior is to use <see cref="char.IsLetterOrDigit(char)"/>
|
||||
/// </summary>
|
||||
/// <param name="rune"></param>
|
||||
/// <returns></returns>
|
||||
public virtual bool IsWordChar (Rune rune)
|
||||
{
|
||||
return Char.IsLetterOrDigit ((char)rune);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Given a <paramref name="line"/> of characters, returns the word which ends at <paramref name="idx"/>
|
||||
/// or null. Also returns null if the <paramref name="idx"/> is positioned in the middle of a word.
|
||||
/// </para>
|
||||
///
|
||||
/// <para>
|
||||
/// Use this method to determine whether autocomplete should be shown when the cursor is at
|
||||
/// a given point in a line and to get the word from which suggestions should be generated.
|
||||
/// Use the <paramref name="columnOffset"/> to indicate if search the word at left (negative),
|
||||
/// at right (positive) or at the current column (zero) which is the default.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="line"></param>
|
||||
/// <param name="idx"></param>
|
||||
/// <param name="columnOffset"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual string IdxToWord (List<Rune> line, int idx, int columnOffset = 0)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder ();
|
||||
var endIdx = idx;
|
||||
|
||||
// get the ending word index
|
||||
while (endIdx < line.Count) {
|
||||
if (IsWordChar (line [endIdx])) {
|
||||
endIdx++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// It isn't a word char then there is no way to autocomplete that word
|
||||
if (endIdx == idx && columnOffset != 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// we are at the end of a word. Work out what has been typed so far
|
||||
while (endIdx-- > 0) {
|
||||
if (IsWordChar (line [endIdx])) {
|
||||
sb.Insert (0, (char)line [endIdx]);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sb.ToString ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
39
Terminal.Gui/Core/Autocomplete/Suggestion.cs
Normal file
39
Terminal.Gui/Core/Autocomplete/Suggestion.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
namespace Terminal.Gui {
|
||||
/// <summary>
|
||||
/// A replacement suggestion made by <see cref="IAutocomplete"/>
|
||||
/// </summary>
|
||||
public class Suggestion {
|
||||
/// <summary>
|
||||
/// The number of characters to remove at the current cursor position
|
||||
/// before adding the <see cref="Replacement"/>
|
||||
/// </summary>
|
||||
public int Remove { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The user visible description for the <see cref="Replacement"/>. Typically
|
||||
/// this would be the same as <see cref="Replacement"/> but may vary in advanced
|
||||
/// use cases (e.g. Title= "ctor", Replacement = "MyClass()\n{\n}")
|
||||
/// </summary>
|
||||
public string Title {get;}
|
||||
|
||||
/// <summary>
|
||||
/// The replacement text that will be added
|
||||
/// </summary>
|
||||
public string Replacement { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="Suggestion"/> class.
|
||||
/// </summary>
|
||||
/// <param name="remove"></param>
|
||||
/// <param name="replacement"></param>
|
||||
/// <param name="title">User visible title for the suggestion or null if the same
|
||||
/// as <paramref name="replacement"/>.</param>
|
||||
public Suggestion (int remove, string replacement, string title = null)
|
||||
{
|
||||
Remove = remove;
|
||||
Replacement = replacement;
|
||||
Title = title ?? replacement;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user