Skip to content

Commit 195c931

Browse files
committed
fix(sidebar separation): Make directory related functionality unexported
1 parent 5ac72de commit 195c931

File tree

8 files changed

+138
-131
lines changed

8 files changed

+138
-131
lines changed

src/internal/default_config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func defaultModelConfig(toggleDotFile bool, toggleFooter bool, firstFilePanelDir
1919
cursor: 0,
2020
render: 0,
2121
},
22-
sidebarModel: sidebar.New(sidebar.GetDirectories(), common.GenerateSearchBar()),
22+
sidebarModel: sidebar.New(),
2323
fileModel: fileModel{
2424
filePanels: filePanelSlice(firstFilePanelDirs),
2525
filePreview: filePreviewPanel{

src/internal/function.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ import (
1616
"strings"
1717
"time"
1818

19-
"github.com/yorukot/superfile/src/internal/ui/sidebar"
20-
2119
"github.com/yorukot/superfile/src/internal/utils"
2220

2321
tea "github.com/charmbracelet/bubbletea"
@@ -181,7 +179,7 @@ func returnDirElementBySearchString(location string, displayDotFile bool, search
181179
}
182180
// https://github.com/reinhrst/fzf-lib/blob/main/core.go#L43
183181
// No sorting needed. fzf.DefaultOptions() already return values ordered on Score
184-
fzfResults := sidebar.FzfSearch(searchString, fileAndDirectories)
182+
fzfResults := utils.FzfSearch(searchString, fileAndDirectories)
185183
dirElement := make([]element, 0, len(fzfResults))
186184
for _, item := range fzfResults {
187185
resultItem := folderElementMap[item.Key]

src/internal/ui/sidebar/directory_utils.go

Lines changed: 13 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,21 @@ import (
66
"log/slog"
77
"os"
88
"path/filepath"
9-
"runtime"
109
"slices"
11-
"strings"
1210

13-
"github.com/reinhrst/fzf-lib"
1411
"github.com/yorukot/superfile/src/internal/utils"
1512

1613
"github.com/adrg/xdg"
17-
"github.com/shirou/gopsutil/v4/disk"
1814
variable "github.com/yorukot/superfile/src/config"
1915
"github.com/yorukot/superfile/src/config/icon"
2016
)
2117

2218
// Return all sidebar directories
23-
func GetDirectories() []directory {
24-
return FormDirctorySlice(GetWellKnownDirectories(), GetPinnedDirectories(), GetExternalMediaFolders())
19+
func getDirectories() []directory {
20+
return formDirctorySlice(getWellKnownDirectories(), getPinnedDirectories(), getExternalMediaFolders())
2521
}
2622

27-
func FormDirctorySlice(homeDirectories []directory, pinnedDirectories []directory, diskDirectories []directory) []directory {
23+
func formDirctorySlice(homeDirectories []directory, pinnedDirectories []directory, diskDirectories []directory) []directory {
2824
// Preallocation for efficiency
2925
totalCapacity := len(homeDirectories) + len(pinnedDirectories) + len(diskDirectories) + 2
3026
directories := make([]directory, 0, totalCapacity)
@@ -38,7 +34,7 @@ func FormDirctorySlice(homeDirectories []directory, pinnedDirectories []director
3834
}
3935

4036
// Return system default directory e.g. Home, Downloads, etc
41-
func GetWellKnownDirectories() []directory {
37+
func getWellKnownDirectories() []directory {
4238
wellKnownDirectories := []directory{
4339
{Location: xdg.Home, Name: icon.Home + icon.Space + "Home"},
4440
{Location: xdg.UserDirs.Download, Name: icon.Download + icon.Space + "Downloads"},
@@ -57,7 +53,7 @@ func GetWellKnownDirectories() []directory {
5753
}
5854

5955
// Get user pinned directories
60-
func GetPinnedDirectories() []directory {
56+
func getPinnedDirectories() []directory {
6157
directories := []directory{}
6258
var paths []string
6359

@@ -84,88 +80,8 @@ func GetPinnedDirectories() []directory {
8480
return directories
8581
}
8682

87-
// Get external media directories
88-
func GetExternalMediaFolders() []directory {
89-
// only get physical drives
90-
parts, err := disk.Partitions(false)
91-
92-
if err != nil {
93-
slog.Error("Error while getting external media: ", "error", err)
94-
return nil
95-
}
96-
var disks []directory
97-
for _, disk := range parts {
98-
// ShouldListDisk, DiskName, and DiskLocation, each has runtime.GOOS checks
99-
// We can ideally reduce it to one check only.
100-
if ShouldListDisk(disk.Mountpoint) {
101-
disks = append(disks, directory{
102-
Name: DiskName(disk.Mountpoint),
103-
Location: DiskLocation(disk.Mountpoint),
104-
})
105-
}
106-
}
107-
return disks
108-
}
109-
110-
func ShouldListDisk(mountPoint string) bool {
111-
if runtime.GOOS == utils.OsWindows {
112-
// We need to get C:, D: drive etc in the list
113-
return true
114-
}
115-
116-
// Should always list the main disk
117-
if mountPoint == "/" {
118-
return true
119-
}
120-
121-
// Todo : make a configurable field in config.yaml
122-
// excluded_disk_mounts = ["/Volumes/.timemachine"]
123-
// Mountpoints that are in subdirectory of disk_mounts
124-
// but still are to be excluded in disk section of sidebar
125-
if strings.HasPrefix(mountPoint, "/Volumes/.timemachine") {
126-
return false
127-
}
128-
129-
// We avoid listing all mounted partitions (Otherwise listed disk could get huge)
130-
// but only a few partitions that usually corresponds to external physical devices
131-
// For example : mounts like /boot, /var/ will get skipped
132-
// This can be inaccurate based on your system setup if you mount any external devices
133-
// on other directories, or if you have some extra mounts on these directories
134-
// Todo : make a configurable field in config.yaml
135-
// disk_mounts = ["/mnt", "/media", "/run/media", "/Volumes"]
136-
// Only block devicies that are mounted on these or any subdirectory of these Mountpoints
137-
// Will be shown in disk sidebar
138-
return strings.HasPrefix(mountPoint, "/mnt") ||
139-
strings.HasPrefix(mountPoint, "/media") ||
140-
strings.HasPrefix(mountPoint, "/run/media") ||
141-
strings.HasPrefix(mountPoint, "/Volumes")
142-
}
143-
144-
func DiskName(mountPoint string) string {
145-
// In windows we dont want to use filepath.Base as it returns "\" for when
146-
// mountPoint is any drive root "C:", "D:", etc. Hence causing same name
147-
// for each drive
148-
if runtime.GOOS == utils.OsWindows {
149-
return mountPoint
150-
}
151-
152-
// This might cause duplicate names in case you mount two devices in
153-
// /mnt/usb and /mnt/dir2/usb . Full mountpoint is a more accurate way
154-
// but that results in messy UI, hence we do this.
155-
return filepath.Base(mountPoint)
156-
}
157-
158-
func DiskLocation(mountPoint string) string {
159-
// In windows if you are in "C:\some\path", "cd C:" will not cd to root of C: drive
160-
// but "cd C:\" will
161-
if runtime.GOOS == utils.OsWindows {
162-
return filepath.Join(mountPoint, "\\")
163-
}
164-
return mountPoint
165-
}
166-
16783
// Fuzzy search function for a list of directories.
168-
func FuzzySearch(query string, dirs []directory) []directory {
84+
func fuzzySearch(query string, dirs []directory) []directory {
16985
if len(dirs) == 0 {
17086
return []directory{}
17187
}
@@ -181,7 +97,7 @@ func FuzzySearch(query string, dirs []directory) []directory {
18197
dirMap[dir.Name] = dir
18298
}
18399

184-
for _, match := range FzfSearch(query, haystack) {
100+
for _, match := range utils.FzfSearch(query, haystack) {
185101
if d, ok := dirMap[match.Key]; ok {
186102
filteredDirs = append(filteredDirs, d)
187103
}
@@ -191,26 +107,17 @@ func FuzzySearch(query string, dirs []directory) []directory {
191107
}
192108

193109
// Get filtered directories using fuzzy search logic with three haystacks.
194-
func GetFilteredDirectories(query string) []directory {
195-
return FormDirctorySlice(
196-
FuzzySearch(query, GetWellKnownDirectories()),
197-
FuzzySearch(query, GetPinnedDirectories()),
198-
FuzzySearch(query, GetExternalMediaFolders()),
110+
func getFilteredDirectories(query string) []directory {
111+
return formDirctorySlice(
112+
fuzzySearch(query, getWellKnownDirectories()),
113+
fuzzySearch(query, getPinnedDirectories()),
114+
fuzzySearch(query, getExternalMediaFolders()),
199115
)
200116
}
201117

202-
// Returning a string slice causes inefficiency in current usage
203-
func FzfSearch(query string, source []string) []fzf.MatchResult {
204-
fzfSearcher := fzf.New(source, fzf.DefaultOptions())
205-
fzfSearcher.Search(query)
206-
fzfResults := <-fzfSearcher.GetResultChannel()
207-
fzfSearcher.End()
208-
return fzfResults.Matches
209-
}
210-
211118
// TogglePinnedDirectory adds or removes a directory from the pinned directories list
212119
func TogglePinnedDirectory(dir string) error {
213-
dirs := GetPinnedDirectories()
120+
dirs := getPinnedDirectories()
214121
unPinned := false
215122

216123
for i, other := range dirs {
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package sidebar
2+
3+
import (
4+
"log/slog"
5+
"path/filepath"
6+
"runtime"
7+
"strings"
8+
9+
"github.com/shirou/gopsutil/v4/disk"
10+
"github.com/yorukot/superfile/src/internal/utils"
11+
)
12+
13+
// Get external media directories
14+
func getExternalMediaFolders() []directory {
15+
// only get physical drives
16+
parts, err := disk.Partitions(false)
17+
18+
if err != nil {
19+
slog.Error("Error while getting external media: ", "error", err)
20+
return nil
21+
}
22+
var disks []directory
23+
for _, disk := range parts {
24+
// ShouldListDisk, DiskName, and DiskLocation, each has runtime.GOOS checks
25+
// We can ideally reduce it to one check only.
26+
if shouldListDisk(disk.Mountpoint) {
27+
disks = append(disks, directory{
28+
Name: diskName(disk.Mountpoint),
29+
Location: diskLocation(disk.Mountpoint),
30+
})
31+
}
32+
}
33+
return disks
34+
}
35+
36+
func shouldListDisk(mountPoint string) bool {
37+
if runtime.GOOS == utils.OsWindows {
38+
// We need to get C:, D: drive etc in the list
39+
return true
40+
}
41+
42+
// Should always list the main disk
43+
if mountPoint == "/" {
44+
return true
45+
}
46+
47+
// Todo : make a configurable field in config.yaml
48+
// excluded_disk_mounts = ["/Volumes/.timemachine"]
49+
// Mountpoints that are in subdirectory of disk_mounts
50+
// but still are to be excluded in disk section of sidebar
51+
if strings.HasPrefix(mountPoint, "/Volumes/.timemachine") {
52+
return false
53+
}
54+
55+
// We avoid listing all mounted partitions (Otherwise listed disk could get huge)
56+
// but only a few partitions that usually corresponds to external physical devices
57+
// For example : mounts like /boot, /var/ will get skipped
58+
// This can be inaccurate based on your system setup if you mount any external devices
59+
// on other directories, or if you have some extra mounts on these directories
60+
// Todo : make a configurable field in config.yaml
61+
// disk_mounts = ["/mnt", "/media", "/run/media", "/Volumes"]
62+
// Only block devicies that are mounted on these or any subdirectory of these Mountpoints
63+
// Will be shown in disk sidebar
64+
return strings.HasPrefix(mountPoint, "/mnt") ||
65+
strings.HasPrefix(mountPoint, "/media") ||
66+
strings.HasPrefix(mountPoint, "/run/media") ||
67+
strings.HasPrefix(mountPoint, "/Volumes")
68+
}
69+
70+
func diskName(mountPoint string) string {
71+
// In windows we dont want to use filepath.Base as it returns "\" for when
72+
// mountPoint is any drive root "C:", "D:", etc. Hence causing same name
73+
// for each drive
74+
if runtime.GOOS == utils.OsWindows {
75+
return mountPoint
76+
}
77+
78+
// This might cause duplicate names in case you mount two devices in
79+
// /mnt/usb and /mnt/dir2/usb . Full mountpoint is a more accurate way
80+
// but that results in messy UI, hence we do this.
81+
return filepath.Base(mountPoint)
82+
}
83+
84+
func diskLocation(mountPoint string) string {
85+
// In windows if you are in "C:\some\path", "cd C:" will not cd to root of C: drive
86+
// but "cd C:\" will
87+
if runtime.GOOS == utils.OsWindows {
88+
return filepath.Join(mountPoint, "\\")
89+
}
90+
return mountPoint
91+
}

src/internal/ui/sidebar/navigation_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ import (
99
func Test_lastRenderIndex(t *testing.T) {
1010
// Setup test data
1111
sidebarA := Model{
12-
directories: FormDirctorySlice(
12+
directories: formDirctorySlice(
1313
dirSlice(10), dirSlice(10), dirSlice(10),
1414
),
1515
}
1616
sidebarB := Model{
17-
directories: FormDirctorySlice(
17+
directories: formDirctorySlice(
1818
dirSlice(1), nil, dirSlice(5),
1919
),
2020
}
@@ -91,17 +91,17 @@ func Test_firstRenderIndex(t *testing.T) {
9191
directories: fullDirSlice(10),
9292
}
9393
sidebarB := Model{
94-
directories: FormDirctorySlice(
94+
directories: formDirctorySlice(
9595
dirSlice(1), nil, dirSlice(5),
9696
),
9797
}
9898
sidebarC := Model{
99-
directories: FormDirctorySlice(
99+
directories: formDirctorySlice(
100100
nil, dirSlice(5), dirSlice(5),
101101
),
102102
}
103103
sidebarD := Model{
104-
directories: FormDirctorySlice(
104+
directories: formDirctorySlice(
105105
nil, nil, dirSlice(3),
106106
),
107107
}
@@ -300,7 +300,7 @@ func Test_updateRenderIndex(t *testing.T) {
300300
{
301301
name: "Edge case: Large panel showing everything",
302302
sidebar: Model{
303-
directories: FormDirctorySlice(dirSlice(1), nil, dirSlice(5)),
303+
directories: formDirctorySlice(dirSlice(1), nil, dirSlice(5)),
304304
renderIndex: 2,
305305
cursor: 4,
306306
},
@@ -419,7 +419,7 @@ func Test_listUp(t *testing.T) {
419419
name: "Skip multiple consecutive dividers",
420420
sidebar: Model{
421421
// Create a sidebar with consecutive dividers for testing
422-
directories: FormDirctorySlice(dirSlice(5), nil, dirSlice(5)),
422+
directories: formDirctorySlice(dirSlice(5), nil, dirSlice(5)),
423423
renderIndex: 5,
424424
cursor: 7, // Position after consecutive dividers
425425
},
@@ -443,7 +443,7 @@ func Test_listUp(t *testing.T) {
443443
{
444444
name: "Large panel showing all directories",
445445
sidebar: Model{
446-
directories: FormDirctorySlice(dirSlice(2), dirSlice(2), dirSlice(2)),
446+
directories: formDirctorySlice(dirSlice(2), dirSlice(2), dirSlice(2)),
447447
renderIndex: 0,
448448
cursor: 3, // Some directory in the middle
449449
},
@@ -520,7 +520,7 @@ func Test_listDown(t *testing.T) {
520520
name: "Skip multiple consecutive dividers",
521521
sidebar: Model{
522522
// Create a sidebar with consecutive dividers for testing
523-
directories: FormDirctorySlice(dirSlice(5), nil, dirSlice(5)),
523+
directories: formDirctorySlice(dirSlice(5), nil, dirSlice(5)),
524524
renderIndex: 0,
525525
cursor: 4, // Position before consecutive dividers
526526
},
@@ -557,7 +557,7 @@ func Test_listDown(t *testing.T) {
557557
{
558558
name: "Large panel showing all directories",
559559
sidebar: Model{
560-
directories: FormDirctorySlice(dirSlice(2), dirSlice(2), dirSlice(2)),
560+
directories: formDirctorySlice(dirSlice(2), dirSlice(2), dirSlice(2)),
561561
renderIndex: 0,
562562
cursor: 3, // Some directory in the middle
563563
},

0 commit comments

Comments
 (0)