Skip to content

Commit 9cdba16

Browse files
authored
Merge pull request #101 from shinokada/fix/i-feel-lucky
fix: #99 * **Documentation** * Updated shuffle shortcut from `t` to `Ctrl+T` across guides and help text. * **User Interface** * In-app hints and messages now reference `Ctrl+T` for toggling shuffle. * **Bug Fixes** * Number-key entry now only accumulates when not typing into the text input, improving input behavior. * **Tests** * Updated and added tests to validate `Ctrl+T` behavior and non-toggle-while-typing cases. * **Chores** * Build task now runs tests before compiling.
2 parents f9b63be + 9b3504b commit 9cdba16

File tree

7 files changed

+79
-29
lines changed

7 files changed

+79
-29
lines changed

docs/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ Set a timer to automatically stop playback — useful for falling asleep to radi
361361
Enter a keyword (genre, mood, style) and TERA finds a random matching station. Perfect for music discovery!
362362

363363
**Shuffle Mode**: Enable shuffle mode to automatically cycle through multiple stations matching your keyword:
364-
- Press `t` to toggle shuffle on/off
364+
- Press `Ctrl+T` to toggle shuffle on/off
365365
- Stations play in random order without repeats
366366
- Optional auto-advance timer (configurable)
367367
- Navigate backward through recently played stations
@@ -534,7 +534,7 @@ Shuffle mode is an enhanced version of "I Feel Lucky" that lets you explore mult
534534
### How It Works
535535

536536
1. Navigate to **I Feel Lucky** from the main menu (option 9)
537-
2. Press `t` to toggle shuffle mode on
537+
2. Press `Ctrl+T` to toggle shuffle mode on
538538
3. Enter your keyword (e.g., "jazz", "rock", "meditation")
539539
4. Press Enter to start shuffle mode
540540

@@ -566,7 +566,7 @@ Shuffle mode is an enhanced version of "I Feel Lucky" that lets you explore mult
566566

567567
| Key | Action |
568568
| ----- | ------------------------------------- |
569-
| `t` | Toggle shuffle mode (in input screen) |
569+
| `Ctrl+T` | Toggle shuffle mode (in input screen) |
570570
| `n` | Next shuffle station (manual skip) |
571571
| `[` | Previous station (from history) |
572572
| `b` | Block current station |

internal/ui/lucky.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -447,8 +447,8 @@ func (m LuckyModel) updateInput(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
447447
return m, tea.Quit
448448
}
449449

450-
// Handle 't' key to toggle shuffle mode (when not typing in input)
451-
if key == "t" && m.textInput.Value() == "" {
450+
// Handle 'ctrl+t' key to toggle shuffle mode
451+
if key == "ctrl+t" {
452452
m.shuffleEnabled = !m.shuffleEnabled
453453
return m, nil
454454
}
@@ -478,8 +478,8 @@ func (m LuckyModel) updateInput(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
478478
return m, cmd
479479
}
480480

481-
// Handle number input for multi-digit selection (only when not typing in input)
482-
if key >= "0" && key <= "9" {
481+
// Handle number input for multi-digit selection when user is not actively typing a keyword
482+
if !inputFocused && key >= "0" && key <= "9" {
483483
m.numberBuffer += key
484484

485485
// Check if we should auto-select
@@ -1022,15 +1022,15 @@ func (m LuckyModel) viewInput() string {
10221022
if m.shuffleEnabled {
10231023
content.WriteString("Shuffle mode: ")
10241024
content.WriteString(highlightStyle().Render("[✓] On"))
1025-
content.WriteString(" (press 't' to disable)")
1025+
content.WriteString(" (press ctrl+t to disable)")
10261026
if m.shuffleConfig.AutoAdvance {
10271027
fmt.Fprintf(&content, "\n Auto-advance in %d min • History: %d stations",
10281028
m.shuffleConfig.IntervalMinutes, m.shuffleConfig.MaxHistory)
10291029
}
10301030
} else {
10311031
content.WriteString("Shuffle mode: ")
10321032
content.WriteString(infoStyle().Render("[ ] Off"))
1033-
content.WriteString(" (press 't' to enable)")
1033+
content.WriteString(" (press ctrl+t to enable)")
10341034
}
10351035

10361036
// Show history menu if available
@@ -1057,7 +1057,7 @@ func (m LuckyModel) viewInput() string {
10571057
}
10581058
}
10591059

1060-
helpText := "↑↓/jk: Navigate • Enter: Search • t: Toggle shuffle"
1060+
helpText := "↑↓/jk: Navigate • Enter: Search • ctrl+t: Toggle shuffle"
10611061
if m.searchHistory != nil && len(m.searchHistory.LuckyQueries) > 0 {
10621062
maxItems := len(m.searchHistory.LuckyQueries)
10631063
if maxItems > m.searchHistory.MaxSize {

internal/ui/lucky_test.go

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -573,22 +573,47 @@ func TestLuckyShuffleToggle(t *testing.T) {
573573
t.Error("Expected shuffle to be disabled initially")
574574
}
575575

576+
// Plain 't' while typing should NOT toggle shuffle
577+
// Regression: first typed 't' from empty input must not toggle shuffle.
578+
model.textInput.SetValue("")
579+
firstT := tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("t")}
580+
firstTypedModel, _ := model.Update(firstT)
581+
firstLucky := firstTypedModel.(LuckyModel)
582+
if firstLucky.shuffleEnabled {
583+
t.Error("Expected shuffle to remain disabled after first typed 't'")
584+
}
585+
if firstLucky.textInput.Value() != "t" {
586+
t.Errorf("Expected text input to contain 't', got %q", firstLucky.textInput.Value())
587+
}
588+
589+
// Plain 't' while typing existing text should also not toggle shuffle.
590+
model.textInput.SetValue("rock")
591+
plainT := tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("t")}
592+
noToggleModel, _ := model.Update(plainT)
593+
if noToggleModel.(LuckyModel).shuffleEnabled {
594+
t.Error("Expected shuffle to remain disabled after pressing 't' while typing")
595+
}
596+
if noToggleModel.(LuckyModel).textInput.Value() != "rockt" {
597+
t.Errorf("Expected text input to contain 'rockt', got %q", noToggleModel.(LuckyModel).textInput.Value())
598+
}
599+
model.textInput.SetValue("") // Reset for subsequent toggle tests
600+
576601
// Toggle shuffle on
577-
msg := tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("t")}
602+
msg := tea.KeyMsg{Type: tea.KeyCtrlT}
578603
updatedModel, _ := model.Update(msg)
579604
luckyModel := updatedModel.(LuckyModel)
580605

581606
if !luckyModel.shuffleEnabled {
582-
t.Error("Expected shuffle to be enabled after pressing 't'")
607+
t.Error("Expected shuffle to be enabled after pressing 'ctrl+t'")
583608
}
584609

585610
// Toggle shuffle off
586-
msg = tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("t")}
611+
msg = tea.KeyMsg{Type: tea.KeyCtrlT}
587612
updatedModel, _ = luckyModel.Update(msg)
588613
luckyModel = updatedModel.(LuckyModel)
589614

590615
if luckyModel.shuffleEnabled {
591-
t.Error("Expected shuffle to be disabled after pressing 't' again")
616+
t.Error("Expected shuffle to be disabled after pressing 'ctrl+t' again")
592617
}
593618
}
594619

v3/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.PHONY: build test clean clean-cache clean-all run lint lint-fix coverage install
22

3-
build:
3+
build: test
44
go build -o tera cmd/tera/main.go
55

66
test:

v3/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ Set a timer to automatically stop playback — useful for falling asleep to radi
273273
Enter a keyword (genre, mood, style) and TERA finds a random matching station. Perfect for music discovery!
274274

275275
**Shuffle Mode**: Enable shuffle mode to automatically cycle through multiple stations matching your keyword:
276-
- Press `t` to toggle shuffle on/off
276+
- Press `Ctrl+T` to toggle shuffle on/off
277277
- Stations play in random order without repeats
278278
- Optional auto-advance timer (configurable)
279279
- Navigate backward through recently played stations
@@ -444,7 +444,7 @@ Shuffle mode is an enhanced version of "I Feel Lucky" that lets you explore mult
444444
### How It Works
445445

446446
1. Navigate to **I Feel Lucky** from the main menu (option 9)
447-
2. Press `t` to toggle shuffle mode on
447+
2. Press `Ctrl+T` to toggle shuffle mode on
448448
3. Enter your keyword (e.g., "jazz", "rock", "meditation")
449449
4. Press Enter to start shuffle mode
450450

@@ -476,7 +476,7 @@ Shuffle mode is an enhanced version of "I Feel Lucky" that lets you explore mult
476476

477477
| Key | Action |
478478
| ----- | ------------------------------------- |
479-
| `t` | Toggle shuffle mode (in input screen) |
479+
| `Ctrl+T` | Toggle shuffle mode (in input screen) |
480480
| `n` | Next shuffle station (manual skip) |
481481
| `[` | Previous station (from history) |
482482
| `b` | Block current station |

v3/internal/ui/lucky.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -539,8 +539,8 @@ func (m LuckyModel) updateInput(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
539539
return m, tea.Quit
540540
}
541541

542-
// Handle 't' key to toggle shuffle mode (when not typing in input)
543-
if key == "t" && m.textInput.Value() == "" {
542+
// Handle 'ctrl+t' key to toggle shuffle mode
543+
if key == "ctrl+t" {
544544
m.shuffleEnabled = !m.shuffleEnabled
545545
return m, nil
546546
}
@@ -570,8 +570,8 @@ func (m LuckyModel) updateInput(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
570570
return m, cmd
571571
}
572572

573-
// Handle number input for multi-digit selection (only when not typing in input)
574-
if key >= "0" && key <= "9" {
573+
// Handle number input for multi-digit selection when user is not actively typing a keyword
574+
if !inputFocused && key >= "0" && key <= "9" {
575575
m.numberBuffer += key
576576

577577
// Check if we should auto-select
@@ -1231,15 +1231,15 @@ func (m LuckyModel) viewInput() string {
12311231
if m.shuffleEnabled {
12321232
content.WriteString("Shuffle mode: ")
12331233
content.WriteString(highlightStyle().Render("[✓] On"))
1234-
content.WriteString(" (press 't' to disable)")
1234+
content.WriteString(" (press ctrl+t to disable)")
12351235
if m.shuffleConfig.AutoAdvance {
12361236
fmt.Fprintf(&content, "\n Auto-advance in %d min • History: %d stations",
12371237
m.shuffleConfig.IntervalMinutes, m.shuffleConfig.MaxHistory)
12381238
}
12391239
} else {
12401240
content.WriteString("Shuffle mode: ")
12411241
content.WriteString(infoStyle().Render("[ ] Off"))
1242-
content.WriteString(" (press 't' to enable)")
1242+
content.WriteString(" (press ctrl+t to enable)")
12431243
}
12441244

12451245
// Show history menu if available
@@ -1266,7 +1266,7 @@ func (m LuckyModel) viewInput() string {
12661266
}
12671267
}
12681268

1269-
helpText := "↑↓/jk: Navigate • Enter: Search • t: Toggle shuffle"
1269+
helpText := "↑↓/jk: Navigate • Enter: Search • ctrl+t: Toggle shuffle"
12701270
if m.searchHistory != nil && len(m.searchHistory.LuckyQueries) > 0 {
12711271
maxItems := len(m.searchHistory.LuckyQueries)
12721272
if maxItems > m.searchHistory.MaxSize {

v3/internal/ui/lucky_test.go

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -573,22 +573,47 @@ func TestLuckyShuffleToggle(t *testing.T) {
573573
t.Error("Expected shuffle to be disabled initially")
574574
}
575575

576+
// Plain 't' while typing should NOT toggle shuffle
577+
// Regression: first typed 't' from empty input must not toggle shuffle.
578+
model.textInput.SetValue("")
579+
firstT := tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("t")}
580+
firstTypedModel, _ := model.Update(firstT)
581+
firstLucky := firstTypedModel.(LuckyModel)
582+
if firstLucky.shuffleEnabled {
583+
t.Error("Expected shuffle to remain disabled after first typed 't'")
584+
}
585+
if firstLucky.textInput.Value() != "t" {
586+
t.Errorf("Expected text input to contain 't', got %q", firstLucky.textInput.Value())
587+
}
588+
589+
// Plain 't' while typing existing text should also not toggle shuffle.
590+
model.textInput.SetValue("rock")
591+
plainT := tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("t")}
592+
noToggleModel, _ := model.Update(plainT)
593+
if noToggleModel.(LuckyModel).shuffleEnabled {
594+
t.Error("Expected shuffle to remain disabled after pressing 't' while typing")
595+
}
596+
if noToggleModel.(LuckyModel).textInput.Value() != "rockt" {
597+
t.Errorf("Expected text input to contain 'rockt', got %q", noToggleModel.(LuckyModel).textInput.Value())
598+
}
599+
model.textInput.SetValue("") // Reset for subsequent toggle tests
600+
576601
// Toggle shuffle on
577-
msg := tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("t")}
602+
msg := tea.KeyMsg{Type: tea.KeyCtrlT}
578603
updatedModel, _ := model.Update(msg)
579604
luckyModel := updatedModel.(LuckyModel)
580605

581606
if !luckyModel.shuffleEnabled {
582-
t.Error("Expected shuffle to be enabled after pressing 't'")
607+
t.Error("Expected shuffle to be enabled after pressing 'ctrl+t'")
583608
}
584609

585610
// Toggle shuffle off
586-
msg = tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("t")}
611+
msg = tea.KeyMsg{Type: tea.KeyCtrlT}
587612
updatedModel, _ = luckyModel.Update(msg)
588613
luckyModel = updatedModel.(LuckyModel)
589614

590615
if luckyModel.shuffleEnabled {
591-
t.Error("Expected shuffle to be disabled after pressing 't' again")
616+
t.Error("Expected shuffle to be disabled after pressing 'ctrl+t' again")
592617
}
593618
}
594619

0 commit comments

Comments
 (0)