mirror of
				https://github.com/nsnail/spectre.console.git
				synced 2025-11-04 10:35:27 +08:00 
			
		
		
		
	Adds optional function to get the display string for TextPrompt choices
This commit is contained in:
		
				
					committed by
					
						
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							041aea2ae5
						
					
				
				
					commit
					0bbf9b81a9
				
			@@ -1,5 +1,6 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
using System.Globalization;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
@@ -15,6 +16,7 @@ namespace Spectre.Console
 | 
			
		||||
    public sealed class TextPrompt<T> : IPrompt<T>
 | 
			
		||||
    {
 | 
			
		||||
        private readonly string _prompt;
 | 
			
		||||
        private readonly StringComparer? _comparer;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets or sets the prompt style.
 | 
			
		||||
@@ -24,7 +26,7 @@ namespace Spectre.Console
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets the list of choices.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public HashSet<T> Choices { get; }
 | 
			
		||||
        public List<T> Choices { get; } = new List<T>();
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets or sets the message for invalid choices.
 | 
			
		||||
@@ -59,6 +61,12 @@ namespace Spectre.Console
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool AllowEmpty { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets or sets the converter to get the display string for a choice. By default
 | 
			
		||||
        /// the corresponding <see cref="TypeConverter"/> is used.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Func<T, string>? Converter { get; set; } = TypeConverterHelper.ConvertToString;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets or sets the validator.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -74,11 +82,10 @@ namespace Spectre.Console
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="prompt">The prompt markup text.</param>
 | 
			
		||||
        /// <param name="comparer">The comparer used for choices.</param>
 | 
			
		||||
        public TextPrompt(string prompt, IEqualityComparer<T>? comparer = null)
 | 
			
		||||
        public TextPrompt(string prompt, StringComparer? comparer = null)
 | 
			
		||||
        {
 | 
			
		||||
            _prompt = prompt;
 | 
			
		||||
 | 
			
		||||
            Choices = new HashSet<T>(comparer ?? EqualityComparer<T>.Default);
 | 
			
		||||
            _comparer = comparer;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@@ -95,7 +102,9 @@ namespace Spectre.Console
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var promptStyle = PromptStyle ?? Style.Plain;
 | 
			
		||||
            var choices = Choices.Select(choice => TypeConverterHelper.ConvertToString(choice));
 | 
			
		||||
            var converter = Converter ?? TypeConverterHelper.ConvertToString;
 | 
			
		||||
            var choices = Choices.Select(choice => converter(choice)).ToList();
 | 
			
		||||
            var choiceMap = Choices.ToDictionary(choice => converter(choice), choice => choice, _comparer);
 | 
			
		||||
 | 
			
		||||
            WritePrompt(console);
 | 
			
		||||
 | 
			
		||||
@@ -108,7 +117,7 @@ namespace Spectre.Console
 | 
			
		||||
                {
 | 
			
		||||
                    if (DefaultValue != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        console.Write(TypeConverterHelper.ConvertToString(DefaultValue.Value), promptStyle);
 | 
			
		||||
                        console.Write(converter(DefaultValue.Value), promptStyle);
 | 
			
		||||
                        console.WriteLine();
 | 
			
		||||
                        return DefaultValue.Value;
 | 
			
		||||
                    }
 | 
			
		||||
@@ -121,17 +130,10 @@ namespace Spectre.Console
 | 
			
		||||
 | 
			
		||||
                console.WriteLine();
 | 
			
		||||
 | 
			
		||||
                // Try convert the value to the expected type.
 | 
			
		||||
                if (!TypeConverterHelper.TryConvertFromString<T>(input, out var result) || result == null)
 | 
			
		||||
                {
 | 
			
		||||
                    console.MarkupLine(ValidationErrorMessage);
 | 
			
		||||
                    WritePrompt(console);
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                T? result;
 | 
			
		||||
                if (Choices.Count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    if (Choices.Contains(result))
 | 
			
		||||
                    if (choiceMap.TryGetValue(input, out result) && result != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        return result;
 | 
			
		||||
                    }
 | 
			
		||||
@@ -142,6 +144,12 @@ namespace Spectre.Console
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else if (!TypeConverterHelper.TryConvertFromString<T>(input, out result) || result == null)
 | 
			
		||||
                {
 | 
			
		||||
                    console.MarkupLine(ValidationErrorMessage);
 | 
			
		||||
                    WritePrompt(console);
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Run all validators
 | 
			
		||||
                if (!ValidateResult(result, out var validationMessage))
 | 
			
		||||
@@ -171,7 +179,8 @@ namespace Spectre.Console
 | 
			
		||||
 | 
			
		||||
            if (ShowChoices && Choices.Count > 0)
 | 
			
		||||
            {
 | 
			
		||||
                var choices = string.Join("/", Choices.Select(choice => TypeConverterHelper.ConvertToString(choice)));
 | 
			
		||||
                var converter = Converter ?? TypeConverterHelper.ConvertToString;
 | 
			
		||||
                var choices = string.Join("/", Choices.Select(choice => converter(choice)));
 | 
			
		||||
                builder.AppendFormat(CultureInfo.InvariantCulture, " [blue][[{0}]][/]", choices);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace Spectre.Console
 | 
			
		||||
{
 | 
			
		||||
@@ -246,6 +247,33 @@ namespace Spectre.Console
 | 
			
		||||
            return obj;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Adds multiple choices to the prompt.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <typeparam name="T">The prompt result type.</typeparam>
 | 
			
		||||
        /// <param name="obj">The prompt.</param>
 | 
			
		||||
        /// <param name="choices">The choices to add.</param>
 | 
			
		||||
        /// <returns>The same instance so that multiple calls can be chained.</returns>
 | 
			
		||||
        public static TextPrompt<T> AddChoices<T>(this TextPrompt<T> obj, IEnumerable<T> choices)
 | 
			
		||||
        {
 | 
			
		||||
            if (obj is null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException(nameof(obj));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (choices is null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException(nameof(choices));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (var choice in choices)
 | 
			
		||||
            {
 | 
			
		||||
                obj.Choices.Add(choice);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return obj;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Replaces prompt user input with asterixes in the console.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
@@ -262,5 +290,23 @@ namespace Spectre.Console
 | 
			
		||||
            obj.IsSecret = true;
 | 
			
		||||
            return obj;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Sets the function to create a display string for a given choice.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <typeparam name="T">The prompt type.</typeparam>
 | 
			
		||||
        /// <param name="obj">The prompt.</param>
 | 
			
		||||
        /// <param name="displaySelector">The function to get a display string for a given choice.</param>
 | 
			
		||||
        /// <returns>The same instance so that multiple calls can be chained.</returns>
 | 
			
		||||
        public static TextPrompt<T> WithConverter<T>(this TextPrompt<T> obj, Func<T, string>? displaySelector)
 | 
			
		||||
        {
 | 
			
		||||
            if (obj is null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException(nameof(obj));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            obj.Converter = displaySelector;
 | 
			
		||||
            return obj;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user