Skip to content

Commit 23a303a

Browse files
Support J and K for navigating list prompts
1 parent 0889c2f commit 23a303a

File tree

3 files changed

+78
-18
lines changed

3 files changed

+78
-18
lines changed

src/Spectre.Console/Prompts/List/ListPromptState.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public bool Update(ConsoleKeyInfo keyInfo)
6363
switch (keyInfo.Key)
6464
{
6565
case ConsoleKey.UpArrow:
66+
case ConsoleKey.K:
6667
if (currentLeafIndex > 0)
6768
{
6869
index = _leafIndexes[currentLeafIndex - 1];
@@ -75,6 +76,7 @@ public bool Update(ConsoleKeyInfo keyInfo)
7576
break;
7677

7778
case ConsoleKey.DownArrow:
79+
case ConsoleKey.J:
7880
if (currentLeafIndex < _leafIndexes.Count - 1)
7981
{
8082
index = _leafIndexes[currentLeafIndex + 1];
@@ -117,8 +119,8 @@ public bool Update(ConsoleKeyInfo keyInfo)
117119
{
118120
index = keyInfo.Key switch
119121
{
120-
ConsoleKey.UpArrow => Index - 1,
121-
ConsoleKey.DownArrow => Index + 1,
122+
ConsoleKey.UpArrow or ConsoleKey.K => Index - 1,
123+
ConsoleKey.DownArrow or ConsoleKey.J => Index + 1,
122124
ConsoleKey.Home => 0,
123125
ConsoleKey.End => ItemCount - 1,
124126
ConsoleKey.PageUp => Index - PageSize,

src/Tests/Spectre.Console.Cli.Tests/Unit/Testing/InteractiveCommandTests.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,35 @@ public void InteractiveCommand_WithMockedUserInputs_ProducesExpectedOutput()
7777
result.ExitCode.ShouldBe(0);
7878
result.Output.EndsWith("[Apple;Apricot;Spectre Console]");
7979
}
80+
81+
[Fact]
82+
public void InteractiveCommand_WithMockedUserInputs_VimMotions_ProducesExpectedOutput()
83+
{
84+
// Given
85+
TestConsole console = new();
86+
console.Interactive();
87+
88+
// Your mocked inputs must always end with "Enter" for each prompt!
89+
90+
// Multi selection prompt: Choose first option
91+
console.Input.PushKey(ConsoleKey.Spacebar);
92+
console.Input.PushKey(ConsoleKey.Enter);
93+
94+
// Selection prompt: Choose second option
95+
console.Input.PushKey(ConsoleKey.J);
96+
console.Input.PushKey(ConsoleKey.Enter);
97+
98+
// Ask text prompt: Enter name
99+
console.Input.PushTextWithEnter("Spectre Console");
100+
101+
var app = new CommandAppTester(null, new CommandAppTesterSettings(), console);
102+
app.SetDefaultCommand<InteractiveCommand>();
103+
104+
// When
105+
var result = app.Run();
106+
107+
// Then
108+
result.ExitCode.ShouldBe(0);
109+
result.Output.EndsWith("[Apple;Apricot;Spectre Console]");
110+
}
80111
}

src/Tests/Spectre.Console.Tests/Unit/Prompts/ListPromptStateTests.cs

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,35 @@ public void Should_Have_Start_Index_Zero()
2222
}
2323

2424
[Theory]
25-
[InlineData(true)]
26-
[InlineData(false)]
27-
public void Should_Increase_Index(bool wrap)
25+
[InlineData(ConsoleKey.UpArrow)]
26+
[InlineData(ConsoleKey.K)]
27+
public void Should_Decrease_Index(ConsoleKey key)
28+
{
29+
// Given
30+
var state = CreateListPromptState(100, 10, false, false);
31+
state.Update(ConsoleKey.End.ToConsoleKeyInfo());
32+
var index = state.Index;
33+
34+
// When
35+
state.Update(key.ToConsoleKeyInfo());
36+
37+
// Then
38+
state.Index.ShouldBe(index - 1);
39+
}
40+
41+
[Theory]
42+
[InlineData(ConsoleKey.DownArrow, true)]
43+
[InlineData(ConsoleKey.DownArrow, false)]
44+
[InlineData(ConsoleKey.J, true)]
45+
[InlineData(ConsoleKey.J, false)]
46+
public void Should_Increase_Index(ConsoleKey key, bool wrap)
2847
{
2948
// Given
3049
var state = CreateListPromptState(100, 10, wrap, false);
3150
var index = state.Index;
3251

3352
// When
34-
state.Update(ConsoleKey.DownArrow.ToConsoleKeyInfo());
53+
state.Update(key.ToConsoleKeyInfo());
3554

3655
// Then
3756
state.Index.ShouldBe(index + 1);
@@ -52,42 +71,48 @@ public void Should_Go_To_End(bool wrap)
5271
state.Index.ShouldBe(99);
5372
}
5473

55-
[Fact]
56-
public void Should_Clamp_Index_If_No_Wrap()
74+
[Theory]
75+
[InlineData(ConsoleKey.DownArrow)]
76+
[InlineData(ConsoleKey.J)]
77+
public void Should_Clamp_Index_If_No_Wrap(ConsoleKey key)
5778
{
5879
// Given
5980
var state = CreateListPromptState(100, 10, false, false);
6081
state.Update(ConsoleKey.End.ToConsoleKeyInfo());
6182

6283
// When
63-
state.Update(ConsoleKey.DownArrow.ToConsoleKeyInfo());
84+
state.Update(key.ToConsoleKeyInfo());
6485

6586
// Then
6687
state.Index.ShouldBe(99);
6788
}
6889

69-
[Fact]
70-
public void Should_Wrap_Index_If_Wrap()
90+
[Theory]
91+
[InlineData(ConsoleKey.DownArrow)]
92+
[InlineData(ConsoleKey.J)]
93+
public void Should_Wrap_Index_If_Wrap(ConsoleKey key)
7194
{
7295
// Given
7396
var state = CreateListPromptState(100, 10, true, false);
7497
state.Update(ConsoleKey.End.ToConsoleKeyInfo());
7598

7699
// When
77-
state.Update(ConsoleKey.DownArrow.ToConsoleKeyInfo());
100+
state.Update(key.ToConsoleKeyInfo());
78101

79102
// Then
80103
state.Index.ShouldBe(0);
81104
}
82105

83-
[Fact]
84-
public void Should_Wrap_Index_If_Wrap_And_Down()
106+
[Theory]
107+
[InlineData(ConsoleKey.UpArrow)]
108+
[InlineData(ConsoleKey.K)]
109+
public void Should_Wrap_Index_If_Wrap_And_Down(ConsoleKey key)
85110
{
86111
// Given
87112
var state = CreateListPromptState(100, 10, true, false);
88113

89114
// When
90-
state.Update(ConsoleKey.UpArrow.ToConsoleKeyInfo());
115+
state.Update(key.ToConsoleKeyInfo());
91116

92117
// Then
93118
state.Index.ShouldBe(99);
@@ -106,13 +131,15 @@ public void Should_Wrap_Index_If_Wrap_And_Page_Up()
106131
state.Index.ShouldBe(0);
107132
}
108133

109-
[Fact]
110-
public void Should_Wrap_Index_If_Wrap_And_Offset_And_Page_Down()
134+
[Theory]
135+
[InlineData(ConsoleKey.UpArrow)]
136+
[InlineData(ConsoleKey.K)]
137+
public void Should_Wrap_Index_If_Wrap_And_Offset_And_Page_Down(ConsoleKey key)
111138
{
112139
// Given
113140
var state = CreateListPromptState(10, 100, true, false);
114141
state.Update(ConsoleKey.End.ToConsoleKeyInfo());
115-
state.Update(ConsoleKey.UpArrow.ToConsoleKeyInfo());
142+
state.Update(key.ToConsoleKeyInfo());
116143

117144
// When
118145
state.Update(ConsoleKey.PageDown.ToConsoleKeyInfo());

0 commit comments

Comments
 (0)