Skip to content

Commit f15e7a3

Browse files
feat: Add a new hotkey to handle cd-on-quit whenever needed (#924)
Resolves #923 This PR introduces a new hotkey defaulted to "shift+q" (cd_quit = ['Q']) to change directory upon quitting superfile. I tried to add the new hotkey without affecting the cd-on-quit configuration, so it stays relevant for anyone that wants to always change directory when quitting. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a global hotkey “Cd Quit” (Q) to quit and change directory to the current folder. Available in default and Vim keymaps and configurable in hotkeys settings. * **Documentation** * Updated hotkey list with “Cd Quit,” including a note about required scripts. * Added “Cd Quit” entry to the in-app help menu. * **Tests** * Added test ensuring “Cd Quit” writes the expected change-directory command on exit. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 1376fd7 commit f15e7a3

File tree

7 files changed

+57
-16
lines changed

7 files changed

+57
-16
lines changed

src/internal/common/config_type.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ func (c *ConfigType) GetIgnoreMissingFields() bool {
112112
type HotkeysType struct {
113113
Confirm []string `toml:"confirm" comment:"=================================================================================================\nGlobal hotkeys (cannot conflict with other hotkeys)"`
114114
Quit []string `toml:"quit"`
115+
CdQuit []string `toml:"cd_quit"`
116+
115117
// movement
116118
ListUp []string `toml:"list_up" comment:"movement"`
117119
ListDown []string `toml:"list_down"`

src/internal/default_config.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ func getHelpMenuData() []helpMenuModalData { //nolint: funlen // This should be
6464
description: "Quit typing, modal or superfile",
6565
hotkeyWorkType: globalType,
6666
},
67+
{
68+
hotkey: common.Hotkeys.CdQuit,
69+
description: "Quit superfile and change directory to current folder",
70+
hotkeyWorkType: globalType,
71+
},
6772
{
6873
hotkey: common.Hotkeys.ConfirmTyping,
6974
description: "Confirm typing",

src/internal/model.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@ import (
2727
)
2828

2929
// These represent model's state information, its not a global preperty
30-
var LastTimeCursorMove = [2]int{int(time.Now().UnixMicro()), 0} //nolint: gochecknoglobals // TODO: Move to model struct
31-
var hasTrash = true //nolint: gochecknoglobals // TODO: Move to model struct
32-
var batCmd = "" //nolint: gochecknoglobals // TODO: Move to model struct
33-
var et *exiftool.Exiftool //nolint: gochecknoglobals // TODO: Move to model struct
30+
var (
31+
LastTimeCursorMove = [2]int{int(time.Now().UnixMicro()), 0} //nolint: gochecknoglobals // TODO: Move to model struct
32+
hasTrash = true //nolint: gochecknoglobals // TODO: Move to model struct
33+
batCmd = "" //nolint: gochecknoglobals // TODO: Move to model struct
34+
et *exiftool.Exiftool //nolint: gochecknoglobals // TODO: Move to model struct
35+
)
3436

3537
// Initialize and return model with default configs
3638
// It returns only tea.Model because when it used in main, the return value
@@ -287,6 +289,7 @@ func (m *model) handleKeyInput(msg tea.KeyMsg) tea.Cmd {
287289
return nil
288290
}
289291
var cmd tea.Cmd
292+
cdOnQuit := common.Config.CdOnQuit
290293
switch {
291294
case m.typingModal.open:
292295
m.typingModalOpenKey(msg.String())
@@ -319,6 +322,10 @@ func (m *model) handleKeyInput(msg tea.KeyMsg) tea.Cmd {
319322
case slices.Contains(common.Hotkeys.Quit, msg.String()):
320323
m.modelQuitState = quitInitiated
321324

325+
case slices.Contains(common.Hotkeys.CdQuit, msg.String()):
326+
m.modelQuitState = quitInitiated
327+
cdOnQuit = true
328+
322329
default:
323330
// Handles general kinds of inputs in the regular state of the application
324331
cmd = m.mainKey(msg.String())
@@ -336,7 +343,7 @@ func (m *model) handleKeyInput(msg tea.KeyMsg) tea.Cmd {
336343
m.modelQuitState = quitConfirmationReceived
337344
}
338345
if m.modelQuitState == quitConfirmationReceived {
339-
m.quitSuperfile()
346+
m.quitSuperfile(cdOnQuit)
340347
return tea.Quit
341348
}
342349
return cmd
@@ -635,7 +642,7 @@ func (m *model) getFilePanelItems() {
635642

636643
// Close superfile application. Cd into the current dir if CdOnQuit on and save
637644
// the path in state direcotory
638-
func (m *model) quitSuperfile() {
645+
func (m *model) quitSuperfile(cdOnQuit bool) {
639646
// close exiftool session
640647
if common.Config.Metadata && et != nil {
641648
et.Close()
@@ -644,7 +651,7 @@ func (m *model) quitSuperfile() {
644651
currentDir := m.fileModel.filePanels[m.filePanelFocusIndex].location
645652
variable.SetLastDir(currentDir)
646653

647-
if common.Config.CdOnQuit {
654+
if cdOnQuit {
648655
// escape single quote
649656
currentDir = strings.ReplaceAll(currentDir, "'", "'\\''")
650657
err := os.WriteFile(variable.LastDirFile, []byte("cd '"+currentDir+"'"), 0755)

src/internal/model_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ func TestQuit(t *testing.T) {
100100
// 2 - Normal quit with running process causing a warn modal
101101
// 2a - Cancelling quit
102102
// 2b - Proceeding with the quit
103+
// 3 - Cd on quit test that LastDir is written on
103104

104105
t.Run("Normal Quit", func(t *testing.T) {
105106
m := defaultTestModel(testDir)
@@ -138,6 +139,26 @@ func TestQuit(t *testing.T) {
138139
assert.Equal(t, quitDone, m.modelQuitState)
139140
assert.True(t, IsTeaQuit(cmd))
140141
})
142+
143+
t.Run("Cd on quit test that LastDir is written on", func(t *testing.T) {
144+
lastDirFile := filepath.Join(variable.SuperFileStateDir, "lastdir")
145+
require.NoError(t, os.MkdirAll(filepath.Dir(lastDirFile), 0o755))
146+
m := defaultTestModel(testDir)
147+
148+
assert.Equal(t, notQuitting, m.modelQuitState)
149+
150+
cmd := TeaUpdateWithErrCheck(m, utils.TeaRuneKeyMsg(common.Hotkeys.CdQuit[0]))
151+
152+
assert.Equal(t, quitDone, m.modelQuitState)
153+
assert.True(t, IsTeaQuit(cmd))
154+
155+
data, err := os.ReadFile(lastDirFile)
156+
require.NoError(t, err)
157+
assert.Equal(t, "cd '"+testDir+"'", string(data), "LastDir file should contain the tempDir path")
158+
159+
err = os.Remove(lastDirFile)
160+
require.NoError(t, err)
161+
})
141162
}
142163

143164
func TestChooserFile(t *testing.T) {

src/superfile_config/hotkeys.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Global hotkeys (cannot conflict with other hotkeys)
33
confirm = ['enter', 'right', 'l']
44
quit = ['q', 'esc']
5-
5+
cd_quit = ['Q', '']
66
# movement
77
list_up = ['up', 'k']
88
list_down = ['down', 'j']

src/superfile_config/vimHotkeys.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# Global hotkeys (cannot conflict with other hotkeys)
55
confirm = ['enter', '']
66
quit = ['ctrl+c', ''] # also know as, theprimeagen troller
7+
cd_quit = ['Q', '']
78
# movement
89
list_up = ['k', '']
910
list_down = ['j', '']

website/src/content/docs/list/hotkey-list.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,19 @@ These are the default hotkeys and you can [change](/configure/custom-hotkeys) th
1212

1313
## General
1414

15-
| Function | Key | Variable name |
16-
| ------------------------------- | ---------------- | ---------------- |
17-
| Open superfile | `spf` | |
18-
| Confirm your select or typing | `enter`, `right` | `confirm_typing` |
19-
| Quit typing, modal or superfile | `esc`, `q` | `quit` |
20-
| Cancel typing | `ctrl+c`, `esc` | `cancel_typing` |
21-
| Open help menu(hotkeylist) | `?` | `open_help_menu` |
22-
| Toggle footer | `F` | `toggle_footer` |
15+
| Function | Key | Variable name |
16+
| --------------------------------------- | ---------------- | ---------------- |
17+
| Open superfile | `spf` | |
18+
| Confirm your select or typing | `enter`, `right` | `confirm_typing` |
19+
| Quit typing, modal or superfile | `esc`, `q` | `quit` |
20+
| Quit superfile and cd to current folder | `Q` | `cd_quit` |
21+
| Cancel typing | `ctrl+c`, `esc` | `cancel_typing` |
22+
| Open help menu(hotkeylist) | `?` | `open_help_menu` |
23+
| Toggle footer | `F` | `toggle_footer` |
24+
25+
:::note
26+
Quit superfile and cd to current folder "cd_quit" require the same scripts as ["cd_on_quit"](/configure/superfile-config/#cd_on_quit) setting
27+
:::
2328

2429
## Panel navigation
2530

0 commit comments

Comments
 (0)