diff --git a/Terminal.Gui/Core/Autocomplete/Autocomplete.cd b/Terminal.Gui/Core/Autocomplete/Autocomplete.cd new file mode 100644 index 000000000..ca47d6435 --- /dev/null +++ b/Terminal.Gui/Core/Autocomplete/Autocomplete.cd @@ -0,0 +1,79 @@ + + + + + + AAAgAABAAQIAAAAAAAAAAAAABAAAIAQAgAEIAggAIAA= + Core\Autocomplete\AppendAutocomplete.cs + + + + + + AAQgAAAAAUAAIAAAAAIAAAAAAAEAIAQIgQAIQAAAMBA= + Core\Autocomplete\AutocompleteBase.cs + + + + + + + + + Core\Autocomplete\PopupAutocomplete.cs + + + + + IAEhAAQAASBEQAAAAAIBAAgYAAAAIAwAwKAAQACBAAA= + Core\Autocomplete\PopupAutocomplete.cs + + + + + + CEAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAIAA= + Core\Autocomplete\SingleWordSuggestionGenerator.cs + + + + + + + AAAAAAAAAAAAAEAAAAAABAAAAAAAAAAAAAAAAAAAAAE= + Core\Autocomplete\Suggestion.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAgAAAAAAAAAA= + Views\TextField.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAgAAAAAAAAAA= + Views\TextView.cs + + + + + + AAQgAAAAAUAAIAAAAAAAAAAAAAEAIAQIgQAIQAAAMBA= + Core\Autocomplete\IAutocomplete.cs + + + + + + + + + AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAA= + Core\Autocomplete\ISuggestionGenerator.cs + + + + \ No newline at end of file diff --git a/Terminal.Gui/Core/Autocomplete/AutocompleteBase.cs b/Terminal.Gui/Core/Autocomplete/AutocompleteBase.cs index f61fb1883..6eb16286a 100644 --- a/Terminal.Gui/Core/Autocomplete/AutocompleteBase.cs +++ b/Terminal.Gui/Core/Autocomplete/AutocompleteBase.cs @@ -7,109 +7,6 @@ using Rune = System.Rune; namespace Terminal.Gui { - public interface ISuggestionGenerator - { - - /// - /// Populates with all strings in that - /// match with the current cursor position/text in the . - /// - /// The column offset. Current (zero - default), left (negative), right (positive). - IEnumerable GenerateSuggestions (List currentLine, int idx); - - bool IsWordChar (Rune rune); - - } - - public class SingleWordSuggestionGenerator : ISuggestionGenerator - { - /// - /// The full set of all strings that can be suggested. - /// - /// - public virtual List AllSuggestions { get; set; } = new List (); - - public IEnumerable GenerateSuggestions (List currentLine, int idx) - { - // if there is nothing to pick from - if (AllSuggestions.Count == 0) { - return Enumerable.Empty(); - } - - var currentWord = IdxToWord (currentLine, idx); - - if (string.IsNullOrWhiteSpace (currentWord)) { - return Enumerable.Empty(); - } else { - return AllSuggestions.Where (o => - o.StartsWith (currentWord, StringComparison.CurrentCultureIgnoreCase) && - !o.Equals (currentWord, StringComparison.CurrentCultureIgnoreCase) - ).Select(o=>new Suggestion(currentWord.Length,o)) - .ToList ().AsReadOnly (); - - } - } - - /// - /// Return true if the given symbol should be considered part of a word - /// and can be contained in matches. Base behavior is to use - /// - /// - /// - public virtual bool IsWordChar (Rune rune) - { - return Char.IsLetterOrDigit ((char)rune); - } - - - /// - /// - /// Given a of characters, returns the word which ends at - /// or null. Also returns null if the is positioned in the middle of a word. - /// - /// - /// - /// 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 to indicate if search the word at left (negative), - /// at right (positive) or at the current column (zero) which is the default. - /// - /// - /// - /// - /// - /// - protected virtual string IdxToWord (List 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 { /// diff --git a/Terminal.Gui/Core/Autocomplete/IAutocomplete.cs b/Terminal.Gui/Core/Autocomplete/IAutocomplete.cs index 7cc54803d..9cdf73e46 100644 --- a/Terminal.Gui/Core/Autocomplete/IAutocomplete.cs +++ b/Terminal.Gui/Core/Autocomplete/IAutocomplete.cs @@ -5,44 +5,6 @@ using Rune = System.Rune; namespace Terminal.Gui { - /// - /// A replacement suggestion made by - /// - public class Suggestion { - /// - /// The number of characters to remove at the current cursor position - /// before adding the - /// - public int Remove { get; } - - /// - /// The user visible description for the . Typically - /// this would be the same as but may vary in advanced - /// use cases (e.g. Title= "ctor", Replacement = "MyClass()\n{\n}") - /// - public string Title {get;} - - /// - /// The replacement text that will be added - /// - public string Replacement { get; } - - - /// - /// Creates a new instance of the class. - /// - /// - /// - /// User visible title for the suggestion or null if the same - /// as . - public Suggestion (int remove, string replacement, string title = null) - { - Remove = remove; - Replacement = replacement; - Title = title ?? replacement; - } - } - /// /// Renders an overlay on another view at a given point that allows selecting /// from a range of 'autocomplete' options. diff --git a/Terminal.Gui/Core/Autocomplete/ISuggestionGenerator.cs b/Terminal.Gui/Core/Autocomplete/ISuggestionGenerator.cs new file mode 100644 index 000000000..f537c874c --- /dev/null +++ b/Terminal.Gui/Core/Autocomplete/ISuggestionGenerator.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using Rune = System.Rune; + +namespace Terminal.Gui { + public interface ISuggestionGenerator + { + + /// + /// Populates with all strings in that + /// match with the current cursor position/text in the . + /// + /// The column offset. Current (zero - default), left (negative), right (positive). + IEnumerable GenerateSuggestions (List currentLine, int idx); + + bool IsWordChar (Rune rune); + + } +} + diff --git a/Terminal.Gui/Core/Autocomplete/SingleWordSuggestionGenerator.cs b/Terminal.Gui/Core/Autocomplete/SingleWordSuggestionGenerator.cs new file mode 100644 index 000000000..656d2f1d0 --- /dev/null +++ b/Terminal.Gui/Core/Autocomplete/SingleWordSuggestionGenerator.cs @@ -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 + { + /// + /// The full set of all strings that can be suggested. + /// + /// + public virtual List AllSuggestions { get; set; } = new List (); + + public IEnumerable GenerateSuggestions (List currentLine, int idx) + { + // if there is nothing to pick from + if (AllSuggestions.Count == 0) { + return Enumerable.Empty(); + } + + var currentWord = IdxToWord (currentLine, idx); + + if (string.IsNullOrWhiteSpace (currentWord)) { + return Enumerable.Empty(); + } else { + return AllSuggestions.Where (o => + o.StartsWith (currentWord, StringComparison.CurrentCultureIgnoreCase) && + !o.Equals (currentWord, StringComparison.CurrentCultureIgnoreCase) + ).Select(o=>new Suggestion(currentWord.Length,o)) + .ToList ().AsReadOnly (); + + } + } + + /// + /// Return true if the given symbol should be considered part of a word + /// and can be contained in matches. Base behavior is to use + /// + /// + /// + public virtual bool IsWordChar (Rune rune) + { + return Char.IsLetterOrDigit ((char)rune); + } + + + /// + /// + /// Given a of characters, returns the word which ends at + /// or null. Also returns null if the is positioned in the middle of a word. + /// + /// + /// + /// 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 to indicate if search the word at left (negative), + /// at right (positive) or at the current column (zero) which is the default. + /// + /// + /// + /// + /// + /// + protected virtual string IdxToWord (List 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 (); + } + } +} + diff --git a/Terminal.Gui/Core/Autocomplete/Suggestion.cs b/Terminal.Gui/Core/Autocomplete/Suggestion.cs new file mode 100644 index 000000000..e27c1628e --- /dev/null +++ b/Terminal.Gui/Core/Autocomplete/Suggestion.cs @@ -0,0 +1,39 @@ +namespace Terminal.Gui { + /// + /// A replacement suggestion made by + /// + public class Suggestion { + /// + /// The number of characters to remove at the current cursor position + /// before adding the + /// + public int Remove { get; } + + /// + /// The user visible description for the . Typically + /// this would be the same as but may vary in advanced + /// use cases (e.g. Title= "ctor", Replacement = "MyClass()\n{\n}") + /// + public string Title {get;} + + /// + /// The replacement text that will be added + /// + public string Replacement { get; } + + + /// + /// Creates a new instance of the class. + /// + /// + /// + /// User visible title for the suggestion or null if the same + /// as . + public Suggestion (int remove, string replacement, string title = null) + { + Remove = remove; + Replacement = replacement; + Title = title ?? replacement; + } + } +}