Skip to content

Commit 38d9386

Browse files
authored
Add option to configure the style of the choices list and the default value in TextPrompt (#681)
* Allow setting the style of the default value in TextPrompt Add property "DefaultValueStyle" to TextPrompt which allows setting the style in which the default value is rendered. When no style is set, the value is displayed as green text, keeping the existing behavior. * Allow setting the style in which a TextPrompt's choices are displayed Add property "ChoicesStyle" to TextPrompt which allows setting the style in the prompt's choices are rendered. When no style is set, choices are displayed as blue text, keeping the existing behavior.
1 parent 7998ece commit 38d9386

File tree

7 files changed

+158
-2
lines changed

7 files changed

+158
-2
lines changed

src/Spectre.Console/Prompts/TextPrompt.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ public sealed class TextPrompt<T> : IPrompt<T>
6363
/// </summary>
6464
public Func<T, ValidationResult>? Validator { get; set; }
6565

66+
/// <summary>
67+
/// Gets or sets the style in which the default value is displayed.
68+
/// </summary>
69+
public Style? DefaultValueStyle { get; set; }
70+
71+
/// <summary>
72+
/// Gets or sets the style in which the list of choices is displayed.
73+
/// </summary>
74+
public Style? ChoicesStyle { get; set; }
75+
6676
/// <summary>
6777
/// Gets or sets the default value.
6878
/// </summary>
@@ -183,16 +193,20 @@ private void WritePrompt(IAnsiConsole console)
183193
appendSuffix = true;
184194
var converter = Converter ?? TypeConverterHelper.ConvertToString;
185195
var choices = string.Join("/", Choices.Select(choice => converter(choice)));
186-
builder.AppendFormat(CultureInfo.InvariantCulture, " [blue][[{0}]][/]", choices);
196+
var choicesStyle = ChoicesStyle?.ToMarkup() ?? "blue";
197+
builder.AppendFormat(CultureInfo.InvariantCulture, " [{0}][[{1}]][/]", choicesStyle, choices);
187198
}
188199

189200
if (ShowDefaultValue && DefaultValue != null)
190201
{
191202
appendSuffix = true;
192203
var converter = Converter ?? TypeConverterHelper.ConvertToString;
204+
var defaultValueStyle = DefaultValueStyle?.ToMarkup() ?? "green";
205+
193206
builder.AppendFormat(
194207
CultureInfo.InvariantCulture,
195-
" [green]({0})[/]",
208+
" [{0}]({1})[/]",
209+
defaultValueStyle,
196210
IsSecret ? "******" : converter(DefaultValue.Value));
197211
}
198212

src/Spectre.Console/Prompts/TextPromptExtensions.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,4 +305,50 @@ public static TextPrompt<T> WithConverter<T>(this TextPrompt<T> obj, Func<T, str
305305
obj.Converter = displaySelector;
306306
return obj;
307307
}
308+
309+
/// <summary>
310+
/// Sets the style in which the default value is displayed.
311+
/// </summary>
312+
/// <typeparam name="T">The prompt result type.</typeparam>
313+
/// <param name="obj">The prompt.</param>
314+
/// <param name="style">The default value style.</param>
315+
/// <returns>The same instance so that multiple calls can be chained.</returns>
316+
public static TextPrompt<T> DefaultValueStyle<T>(this TextPrompt<T> obj, Style style)
317+
{
318+
if (obj is null)
319+
{
320+
throw new ArgumentNullException(nameof(obj));
321+
}
322+
323+
if (style is null)
324+
{
325+
throw new ArgumentNullException(nameof(style));
326+
}
327+
328+
obj.DefaultValueStyle = style;
329+
return obj;
330+
}
331+
332+
/// <summary>
333+
/// Sets the style in which the list of choices is displayed.
334+
/// </summary>
335+
/// <typeparam name="T">The prompt result type.</typeparam>
336+
/// <param name="obj">The prompt.</param>
337+
/// <param name="style">The style to use for displaying the choices.</param>
338+
/// <returns>The same instance so that multiple calls can be chained.</returns>
339+
public static TextPrompt<T> ChoicesStyle<T>(this TextPrompt<T> obj, Style style)
340+
{
341+
if (obj is null)
342+
{
343+
throw new ArgumentNullException(nameof(obj));
344+
}
345+
346+
if (style is null)
347+
{
348+
throw new ArgumentNullException(nameof(style));
349+
}
350+
351+
obj.ChoicesStyle = style;
352+
return obj;
353+
}
308354
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Enter Value: [Choice 1/Choice 2]: Choice 2
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Enter Value: [Choice 1/Choice 2]: Choice 2
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Enter Value: (default): Input
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Enter Value: (default): Input

test/Spectre.Console.Tests/Unit/Prompts/TextPromptTests.cs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,4 +241,96 @@ public Task Should_Not_Append_Questionmark_Or_Colon_If_No_Choices_Are_Set()
241241
// Then
242242
return Verifier.Verify(console.Output);
243243
}
244+
245+
[Fact]
246+
[Expectation("DefaultValueStyleNotSet")]
247+
public Task Uses_default_style_for_default_value_if_no_style_is_set()
248+
{
249+
// Given
250+
var console = new TestConsole
251+
{
252+
EmitAnsiSequences = true,
253+
};
254+
console.Input.PushTextWithEnter("Input");
255+
256+
var prompt = new TextPrompt<string>("Enter Value:")
257+
.ShowDefaultValue()
258+
.DefaultValue("default");
259+
260+
// When
261+
console.Prompt(prompt);
262+
263+
// Then
264+
return Verifier.Verify(console.Output);
265+
}
266+
267+
[Fact]
268+
[Expectation("DefaultValueStyleSet")]
269+
public Task Uses_specified_default_value_style()
270+
{
271+
// Given
272+
var console = new TestConsole
273+
{
274+
EmitAnsiSequences = true,
275+
};
276+
console.Input.PushTextWithEnter("Input");
277+
278+
var prompt = new TextPrompt<string>("Enter Value:")
279+
.ShowDefaultValue()
280+
.DefaultValue("default")
281+
.DefaultValueStyle(new Style(foreground: Color.Red));
282+
283+
// When
284+
console.Prompt(prompt);
285+
286+
// Then
287+
return Verifier.Verify(console.Output);
288+
}
289+
290+
[Fact]
291+
[Expectation("ChoicesStyleNotSet")]
292+
public Task Uses_default_style_for_choices_if_no_style_is_set()
293+
{
294+
// Given
295+
var console = new TestConsole
296+
{
297+
EmitAnsiSequences = true,
298+
};
299+
console.Input.PushTextWithEnter("Choice 2");
300+
301+
var prompt = new TextPrompt<string>("Enter Value:")
302+
.ShowChoices()
303+
.AddChoice("Choice 1")
304+
.AddChoice("Choice 2");
305+
306+
// When
307+
console.Prompt(prompt);
308+
309+
// Then
310+
return Verifier.Verify(console.Output);
311+
}
312+
313+
[Fact]
314+
[Expectation("ChoicesStyleSet")]
315+
public Task Uses_the_specified_choices_style()
316+
{
317+
// Given
318+
var console = new TestConsole
319+
{
320+
EmitAnsiSequences = true,
321+
};
322+
console.Input.PushTextWithEnter("Choice 2");
323+
324+
var prompt = new TextPrompt<string>("Enter Value:")
325+
.ShowChoices()
326+
.AddChoice("Choice 1")
327+
.AddChoice("Choice 2")
328+
.ChoicesStyle(new Style(foreground: Color.Red));
329+
330+
// When
331+
console.Prompt(prompt);
332+
333+
// Then
334+
return Verifier.Verify(console.Output);
335+
}
244336
}

0 commit comments

Comments
 (0)