From afae0c8f5aab6e1ee91cc61f6556109d6c544081 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Tue, 4 Feb 2025 15:50:27 +0530 Subject: [PATCH 1/3] Add extensive logs for help in debugging --- src/internal/function.go | 27 +++++++++++++++++++++------ src/internal/get_data.go | 6 +++++- src/internal/model.go | 12 ++++++++++++ 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/internal/function.go b/src/internal/function.go index 327c787c..42f291ec 100644 --- a/src/internal/function.go +++ b/src/internal/function.go @@ -42,14 +42,14 @@ func returnFocusType(focusPanel focusPanelType) filePanelFocusType { } func returnFolderElement(location string, displayDotFile bool, sortOptions sortOptionsModelData) (directoryElement []element) { - + slog.Debug("returnFolderElement() called.") files, err := os.ReadDir(location) - if len(files) == 0 { - return directoryElement - } - if err != nil { outPutLog("Return folder element function error", err) + return directoryElement + } + if len(files) == 0 { + return directoryElement } // Sort files @@ -59,6 +59,9 @@ func returnFolderElement(location string, displayDotFile bool, sortOptions sortO switch sortOptions.options[sortOptions.selected] { case "Name": order = func(i, j int) bool { + slog.Debug("sort func", "i", i, "j", j) + // This is inefficient, no need to read directories recurdsively here + // We just need their name to sort. _, errI := os.ReadDir(location + "/" + files[i].Name()) _, errJ := os.ReadDir(location + "/" + files[j].Name()) if (files[i].IsDir() || errI == nil) && (!files[j].IsDir() && errJ != nil) { @@ -79,6 +82,8 @@ func returnFolderElement(location string, displayDotFile bool, sortOptions sortO // Files sorted by size fileInfoI, _ := files[i].Info() fileInfoJ, _ := files[j].Info() + + // Hard coded "/" - Should only use filepath.join _, errI := os.ReadDir(location + "/" + files[i].Name()) _, errJ := os.ReadDir(location + "/" + files[j].Name()) @@ -88,6 +93,9 @@ func returnFolderElement(location string, displayDotFile bool, sortOptions sortO if (!files[i].IsDir() && errI != nil) && (files[j].IsDir() || errJ == nil) { return false } + + // This needs to be improved, and we should sort by actual size only + // Repeated recursive read would be slow, so we could cache if files[i].IsDir() && files[j].IsDir() { filesI, err := os.ReadDir(filepath.Join(location, files[i].Name())) if err != nil { @@ -103,6 +111,7 @@ func returnFolderElement(location string, displayDotFile bool, sortOptions sortO } case "Date Modified": order = func(i, j int) bool { + // You should make sure that files with info nil are filtered beforehand fileInfoI, _ := files[i].Info() fileInfoJ, _ := files[j].Info() return fileInfoI.ModTime().After(fileInfoJ.ModTime()) != reversed @@ -113,13 +122,16 @@ func returnFolderElement(location string, displayDotFile bool, sortOptions sortO for _, item := range files { fileInfo, err := item.Info() + // should have skipped these files way before if err != nil { continue } - + + // If the dot files were not even needed, why consider them for sorting ? if !displayDotFile && strings.HasPrefix(fileInfo.Name(), ".") { continue } + // should have skipped before . if fileInfo == nil { continue } @@ -127,6 +139,7 @@ func returnFolderElement(location string, displayDotFile bool, sortOptions sortO name: item.Name(), directory: item.IsDir(), } + // Redundant. if location == "/" { newElement.location = location + item.Name() } else { @@ -135,6 +148,8 @@ func returnFolderElement(location string, displayDotFile bool, sortOptions sortO directoryElement = append(directoryElement, newElement) } + slog.Debug("returnFolderElement() returning.", "directoryElement", directoryElement) + return directoryElement } diff --git a/src/internal/get_data.go b/src/internal/get_data.go index 247e02e8..5baff5d1 100644 --- a/src/internal/get_data.go +++ b/src/internal/get_data.go @@ -2,6 +2,7 @@ package internal import ( "encoding/json" + "log/slog" "os" "path/filepath" @@ -13,6 +14,7 @@ import ( // Return all sidebar directories func getDirectories() []directory { + slog.Debug("getDirectories() called") directories := []directory{} directories = append(directories, getWellKnownDirectories()...) @@ -26,7 +28,7 @@ func getDirectories() []directory { location: "Disks+-*/=?", }) directories = append(directories, getExternalMediaFolders()...) - + slog.Debug("getDirectories() returning", "directories", directories) return directories } @@ -66,6 +68,8 @@ func getPinnedDirectories() []directory { jsonData, err := os.ReadFile(variable.PinnedFile) if err != nil { outPutLog("Read superfile data error", err) + // Should exit here + return directories } // Check if the data is in the old format diff --git a/src/internal/model.go b/src/internal/model.go index ad944807..29695163 100644 --- a/src/internal/model.go +++ b/src/internal/model.go @@ -51,6 +51,8 @@ func (m model) Init() tea.Cmd { // Update function for bubble tea to provide internal communication to the // application func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + slog.Debug("model.Update() called.", "current width", m.fullWidth, + "current height", m.fullHeight) var cmd tea.Cmd switch msg := msg.(type) { @@ -68,13 +70,18 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.updateSidebarState(msg, &cmd) m.sidebarModel.directories = getDirectories() + // check if there already have listening message if !ListeningMessage { + slog.Debug("ListeningMessage is false in model Update()") cmd = tea.Batch(cmd, listenForChannelMessage(channel)) } m.getFilePanelItems() + slog.Debug("model.Update() returning.", "current width", m.fullWidth, + "current height", m.fullHeight) + return m, tea.Batch(cmd) } @@ -95,6 +102,7 @@ func (m *model) handleChannelMessage(msg channelMessage) { // Adjust window size based on msg information func (m *model) handleWindowResize(msg tea.WindowSizeMsg) { + slog.Debug("model.Update() called with handleWindowResize msg.", "msg.Width", msg.Width, "msg.Height", msg.Height) m.fullHeight = msg.Height m.fullWidth = msg.Width @@ -247,6 +255,7 @@ func (m *model) handleKeyInput(msg tea.KeyMsg, cmd tea.Cmd) tea.Cmd { // Update the file panel state. Change name of renamed files, filter out files // in search, update typingb bar, etc func (m *model) updateFilePanelsState(msg tea.Msg, cmd *tea.Cmd) { + slog.Debug("updateFilePanelsState() called") focusPanel := &m.fileModel.filePanels[m.filePanelFocusIndex] if m.firstTextInput { m.firstTextInput = false @@ -267,6 +276,7 @@ func (m *model) updateFilePanelsState(msg tea.Msg, cmd *tea.Cmd) { // Update the sidebar state. Change name of the renaming pinned directory. func (m *model) updateSidebarState(msg tea.Msg, cmd *tea.Cmd) { + slog.Debug("updateSidebarState() is called") sidebar := &m.sidebarModel if sidebar.renaming { sidebar.rename, *cmd = sidebar.rename.Update(msg) @@ -296,6 +306,7 @@ func (m *model) warnModalForQuit() { // Implement View function for bubble tea model to handle visualization. func (m model) View() string { + slog.Debug("model.View() called.", "h", m.fullHeight, "w", m.fullWidth) panel := m.fileModel.filePanels[m.filePanelFocusIndex] // check is the terminal size enough if m.fullHeight < minimumHeight || m.fullWidth < minimumWidth { @@ -404,6 +415,7 @@ func listenForChannelMessage(msg chan channelMessage) tea.Cmd { // Render and update file panel items. Check for changes and updates in files and // folders in the current directory. func (m *model) getFilePanelItems() { + slog.Debug("getFilePanelItems() called") focusPanel := m.fileModel.filePanels[m.filePanelFocusIndex] for i, filePanel := range m.fileModel.filePanels { var fileElement []element From adddf06920c713e69b6019c8ed289a80c612b6e9 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Tue, 4 Feb 2025 23:40:17 +0530 Subject: [PATCH 2/3] fix: Fix file listing. Better error handling and performance improvements --- src/internal/function.go | 107 +++++++++++++++++---------------------- src/internal/model.go | 8 ++- 2 files changed, 49 insertions(+), 66 deletions(-) diff --git a/src/internal/function.go b/src/internal/function.go index 42f291ec..da4762d4 100644 --- a/src/internal/function.go +++ b/src/internal/function.go @@ -9,6 +9,7 @@ import ( "os" "path/filepath" "regexp" + "slices" "sort" "strconv" "strings" @@ -41,14 +42,23 @@ func returnFocusType(focusPanel focusPanelType) filePanelFocusType { return secondFocus } -func returnFolderElement(location string, displayDotFile bool, sortOptions sortOptionsModelData) (directoryElement []element) { +// Need to rename folder to directory. +func returnDirectoryElement(location string, displayDotFile bool, sortOptions sortOptionsModelData) (directoryElement []element) { slog.Debug("returnFolderElement() called.") - files, err := os.ReadDir(location) + dirEntries, err := os.ReadDir(location) if err != nil { outPutLog("Return folder element function error", err) return directoryElement } - if len(files) == 0 { + + dirEntries = slices.DeleteFunc(dirEntries, func(e os.DirEntry) bool { + // Should be deleted + _, err := e.Info() + return err != nil || (strings.HasPrefix(e.Name(), ".") && !displayDotFile) + }) + + // No files/directoes to process + if len(dirEntries) == 0 { return directoryElement } @@ -60,92 +70,67 @@ func returnFolderElement(location string, displayDotFile bool, sortOptions sortO case "Name": order = func(i, j int) bool { slog.Debug("sort func", "i", i, "j", j) - // This is inefficient, no need to read directories recurdsively here - // We just need their name to sort. - _, errI := os.ReadDir(location + "/" + files[i].Name()) - _, errJ := os.ReadDir(location + "/" + files[j].Name()) - if (files[i].IsDir() || errI == nil) && (!files[j].IsDir() && errJ != nil) { - return true - } - if (!files[i].IsDir() && errI != nil) && (files[j].IsDir() || errJ == nil) { - return false + + // One of them is a directory, and other is not + if dirEntries[i].IsDir() != dirEntries[j].IsDir() { + return dirEntries[i].IsDir() } + if Config.CaseSensitiveSort { - return files[i].Name() < files[j].Name() != reversed + return dirEntries[i].Name() < dirEntries[j].Name() != reversed } else { - return strings.ToLower(files[i].Name()) < strings.ToLower(files[j].Name()) != reversed + return strings.ToLower(dirEntries[i].Name()) < strings.ToLower(dirEntries[j].Name()) != reversed } } case "Size": order = func(i, j int) bool { // Directories at the top sorted by direct child count (not recursive) // Files sorted by size - fileInfoI, _ := files[i].Info() - fileInfoJ, _ := files[j].Info() - - // Hard coded "/" - Should only use filepath.join - _, errI := os.ReadDir(location + "/" + files[i].Name()) - _, errJ := os.ReadDir(location + "/" + files[j].Name()) - - if (files[i].IsDir() || errI == nil) && (!files[j].IsDir() && errJ != nil) { - return true - } - if (!files[i].IsDir() && errI != nil) && (files[j].IsDir() || errJ == nil) { - return false + + // One of them is a directory, and other is not + if dirEntries[i].IsDir() != dirEntries[j].IsDir() { + return dirEntries[i].IsDir() } // This needs to be improved, and we should sort by actual size only - // Repeated recursive read would be slow, so we could cache - if files[i].IsDir() && files[j].IsDir() { - filesI, err := os.ReadDir(filepath.Join(location, files[i].Name())) + // Repeated recursive read would be slow, so we could cache + if dirEntries[i].IsDir() && dirEntries[j].IsDir() { + filesI, err := os.ReadDir(filepath.Join(location, dirEntries[i].Name())) + // No need of early return, we only call len() on filesI, so nil would + // just result in 0 if err != nil { - outPutLog("Error when reading directory", err) + outPutLog("Error when reading directory during sort", err) } - filesJ, err := os.ReadDir(filepath.Join(location, files[j].Name())) + filesJ, err := os.ReadDir(filepath.Join(location, dirEntries[j].Name())) if err != nil { - outPutLog("Error when reading directory", err) + outPutLog("Error when reading directory during sort", err) } return len(filesI) < len(filesJ) != reversed + } else { + // No need for err check, we already filtered out dirEntries with err != nil in Info() call + fileInfoI, _ := dirEntries[i].Info() + fileInfoJ, _ := dirEntries[j].Info() + return fileInfoI.Size() < fileInfoJ.Size() != reversed } - return fileInfoI.Size() < fileInfoJ.Size() != reversed + } case "Date Modified": order = func(i, j int) bool { - // You should make sure that files with info nil are filtered beforehand - fileInfoI, _ := files[i].Info() - fileInfoJ, _ := files[j].Info() + // No need for err check, we already filtered out dirEntries with err != nil in Info() call + fileInfoI, _ := dirEntries[i].Info() + fileInfoJ, _ := dirEntries[j].Info() return fileInfoI.ModTime().After(fileInfoJ.ModTime()) != reversed } } - sort.Slice(files, order) + sort.Slice(dirEntries, order) - for _, item := range files { - fileInfo, err := item.Info() - // should have skipped these files way before - if err != nil { - continue - } - - // If the dot files were not even needed, why consider them for sorting ? - if !displayDotFile && strings.HasPrefix(fileInfo.Name(), ".") { - continue - } - // should have skipped before . - if fileInfo == nil { - continue - } - newElement := element{ + for _, item := range dirEntries { + directoryElement = append(directoryElement, element{ name: item.Name(), directory: item.IsDir(), - } - // Redundant. - if location == "/" { - newElement.location = location + item.Name() - } else { - newElement.location = filepath.Join(location, item.Name()) - } - directoryElement = append(directoryElement, newElement) + location: filepath.Join(location, item.Name()), + }) } slog.Debug("returnFolderElement() returning.", "directoryElement", directoryElement) diff --git a/src/internal/model.go b/src/internal/model.go index 29695163..e0b4a9bd 100644 --- a/src/internal/model.go +++ b/src/internal/model.go @@ -51,7 +51,7 @@ func (m model) Init() tea.Cmd { // Update function for bubble tea to provide internal communication to the // application func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - slog.Debug("model.Update() called.", "current width", m.fullWidth, + slog.Debug("model.Update() called.", "current width", m.fullWidth, "current height", m.fullHeight) var cmd tea.Cmd @@ -70,7 +70,6 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.updateSidebarState(msg, &cmd) m.sidebarModel.directories = getDirectories() - // check if there already have listening message if !ListeningMessage { slog.Debug("ListeningMessage is false in model Update()") @@ -79,7 +78,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.getFilePanelItems() - slog.Debug("model.Update() returning.", "current width", m.fullWidth, + slog.Debug("model.Update() returning.", "current width", m.fullWidth, "current height", m.fullHeight) return m, tea.Batch(cmd) @@ -415,7 +414,6 @@ func listenForChannelMessage(msg chan channelMessage) tea.Cmd { // Render and update file panel items. Check for changes and updates in files and // folders in the current directory. func (m *model) getFilePanelItems() { - slog.Debug("getFilePanelItems() called") focusPanel := m.fileModel.filePanels[m.filePanelFocusIndex] for i, filePanel := range m.fileModel.filePanels { var fileElement []element @@ -447,7 +445,7 @@ func (m *model) getFilePanelItems() { if filePanel.searchBar.Value() != "" { fileElement = returnFolderElementBySearchString(filePanel.location, m.toggleDotFile, filePanel.searchBar.Value()) } else { - fileElement = returnFolderElement(filePanel.location, m.toggleDotFile, filePanel.sortOptions.data) + fileElement = returnDirectoryElement(filePanel.location, m.toggleDotFile, filePanel.sortOptions.data) } // Update file panel list filePanel.element = fileElement From c3d9fea1615ca88cc77d76a70945e0a331ef0d67 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Tue, 4 Feb 2025 23:42:44 +0530 Subject: [PATCH 3/3] PR fix: Remove additional log lines --- src/internal/function.go | 31 +++++++++++++------------------ src/internal/get_data.go | 4 ---- src/internal/model.go | 14 ++------------ 3 files changed, 15 insertions(+), 34 deletions(-) diff --git a/src/internal/function.go b/src/internal/function.go index da4762d4..f32659ef 100644 --- a/src/internal/function.go +++ b/src/internal/function.go @@ -42,9 +42,7 @@ func returnFocusType(focusPanel focusPanelType) filePanelFocusType { return secondFocus } -// Need to rename folder to directory. -func returnDirectoryElement(location string, displayDotFile bool, sortOptions sortOptionsModelData) (directoryElement []element) { - slog.Debug("returnFolderElement() called.") +func returnDirElement(location string, displayDotFile bool, sortOptions sortOptionsModelData) (directoryElement []element) { dirEntries, err := os.ReadDir(location) if err != nil { outPutLog("Return folder element function error", err) @@ -52,7 +50,7 @@ func returnDirectoryElement(location string, displayDotFile bool, sortOptions so } dirEntries = slices.DeleteFunc(dirEntries, func(e os.DirEntry) bool { - // Should be deleted + // Entries not needed to be considered _, err := e.Info() return err != nil || (strings.HasPrefix(e.Name(), ".") && !displayDotFile) }) @@ -66,16 +64,17 @@ func returnDirectoryElement(location string, displayDotFile bool, sortOptions so var order func(i, j int) bool reversed := sortOptions.reversed + // Todo : These strings should not be hardcoded here, but defined as constants switch sortOptions.options[sortOptions.selected] { case "Name": order = func(i, j int) bool { slog.Debug("sort func", "i", i, "j", j) - + // One of them is a directory, and other is not if dirEntries[i].IsDir() != dirEntries[j].IsDir() { return dirEntries[i].IsDir() } - + if Config.CaseSensitiveSort { return dirEntries[i].Name() < dirEntries[j].Name() != reversed } else { @@ -86,12 +85,12 @@ func returnDirectoryElement(location string, displayDotFile bool, sortOptions so order = func(i, j int) bool { // Directories at the top sorted by direct child count (not recursive) // Files sorted by size - + // One of them is a directory, and other is not if dirEntries[i].IsDir() != dirEntries[j].IsDir() { return dirEntries[i].IsDir() } - + // This needs to be improved, and we should sort by actual size only // Repeated recursive read would be slow, so we could cache if dirEntries[i].IsDir() && dirEntries[j].IsDir() { @@ -112,7 +111,7 @@ func returnDirectoryElement(location string, displayDotFile bool, sortOptions so fileInfoJ, _ := dirEntries[j].Info() return fileInfoI.Size() < fileInfoJ.Size() != reversed } - + } case "Date Modified": order = func(i, j int) bool { @@ -124,7 +123,6 @@ func returnDirectoryElement(location string, displayDotFile bool, sortOptions so } sort.Slice(dirEntries, order) - for _, item := range dirEntries { directoryElement = append(directoryElement, element{ name: item.Name(), @@ -132,13 +130,10 @@ func returnDirectoryElement(location string, displayDotFile bool, sortOptions so location: filepath.Join(location, item.Name()), }) } - - slog.Debug("returnFolderElement() returning.", "directoryElement", directoryElement) - return directoryElement } -func returnFolderElementBySearchString(location string, displayDotFile bool, searchString string) (folderElement []element) { +func returnDirElementBySearchString(location string, displayDotFile bool, searchString string) (dirElement []element) { items, err := os.ReadDir(location) if err != nil { @@ -182,15 +177,15 @@ func returnFolderElementBySearchString(location string, displayDotFile bool, sea for _, item := range result.Matches { resultItem := folderElementMap[item.Key] resultItem.matchRate = float64(item.Score) - folderElement = append(folderElement, resultItem) + dirElement = append(dirElement, resultItem) } // Sort folders and files by match rate - sort.Slice(folderElement, func(i, j int) bool { - return folderElement[i].matchRate > folderElement[j].matchRate + sort.Slice(dirElement, func(i, j int) bool { + return dirElement[i].matchRate > dirElement[j].matchRate }) - return folderElement + return dirElement } func panelElementHeight(mainPanelHeight int) int { diff --git a/src/internal/get_data.go b/src/internal/get_data.go index 5baff5d1..73c69c2b 100644 --- a/src/internal/get_data.go +++ b/src/internal/get_data.go @@ -2,7 +2,6 @@ package internal import ( "encoding/json" - "log/slog" "os" "path/filepath" @@ -14,7 +13,6 @@ import ( // Return all sidebar directories func getDirectories() []directory { - slog.Debug("getDirectories() called") directories := []directory{} directories = append(directories, getWellKnownDirectories()...) @@ -28,7 +26,6 @@ func getDirectories() []directory { location: "Disks+-*/=?", }) directories = append(directories, getExternalMediaFolders()...) - slog.Debug("getDirectories() returning", "directories", directories) return directories } @@ -68,7 +65,6 @@ func getPinnedDirectories() []directory { jsonData, err := os.ReadFile(variable.PinnedFile) if err != nil { outPutLog("Read superfile data error", err) - // Should exit here return directories } diff --git a/src/internal/model.go b/src/internal/model.go index e0b4a9bd..74136e1a 100644 --- a/src/internal/model.go +++ b/src/internal/model.go @@ -51,8 +51,6 @@ func (m model) Init() tea.Cmd { // Update function for bubble tea to provide internal communication to the // application func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - slog.Debug("model.Update() called.", "current width", m.fullWidth, - "current height", m.fullHeight) var cmd tea.Cmd switch msg := msg.(type) { @@ -72,15 +70,11 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { // check if there already have listening message if !ListeningMessage { - slog.Debug("ListeningMessage is false in model Update()") cmd = tea.Batch(cmd, listenForChannelMessage(channel)) } m.getFilePanelItems() - slog.Debug("model.Update() returning.", "current width", m.fullWidth, - "current height", m.fullHeight) - return m, tea.Batch(cmd) } @@ -101,7 +95,6 @@ func (m *model) handleChannelMessage(msg channelMessage) { // Adjust window size based on msg information func (m *model) handleWindowResize(msg tea.WindowSizeMsg) { - slog.Debug("model.Update() called with handleWindowResize msg.", "msg.Width", msg.Width, "msg.Height", msg.Height) m.fullHeight = msg.Height m.fullWidth = msg.Width @@ -254,7 +247,6 @@ func (m *model) handleKeyInput(msg tea.KeyMsg, cmd tea.Cmd) tea.Cmd { // Update the file panel state. Change name of renamed files, filter out files // in search, update typingb bar, etc func (m *model) updateFilePanelsState(msg tea.Msg, cmd *tea.Cmd) { - slog.Debug("updateFilePanelsState() called") focusPanel := &m.fileModel.filePanels[m.filePanelFocusIndex] if m.firstTextInput { m.firstTextInput = false @@ -275,7 +267,6 @@ func (m *model) updateFilePanelsState(msg tea.Msg, cmd *tea.Cmd) { // Update the sidebar state. Change name of the renaming pinned directory. func (m *model) updateSidebarState(msg tea.Msg, cmd *tea.Cmd) { - slog.Debug("updateSidebarState() is called") sidebar := &m.sidebarModel if sidebar.renaming { sidebar.rename, *cmd = sidebar.rename.Update(msg) @@ -305,7 +296,6 @@ func (m *model) warnModalForQuit() { // Implement View function for bubble tea model to handle visualization. func (m model) View() string { - slog.Debug("model.View() called.", "h", m.fullHeight, "w", m.fullWidth) panel := m.fileModel.filePanels[m.filePanelFocusIndex] // check is the terminal size enough if m.fullHeight < minimumHeight || m.fullWidth < minimumWidth { @@ -443,9 +433,9 @@ func (m *model) getFilePanelItems() { // Get file names based on search bar filter if filePanel.searchBar.Value() != "" { - fileElement = returnFolderElementBySearchString(filePanel.location, m.toggleDotFile, filePanel.searchBar.Value()) + fileElement = returnDirElementBySearchString(filePanel.location, m.toggleDotFile, filePanel.searchBar.Value()) } else { - fileElement = returnDirectoryElement(filePanel.location, m.toggleDotFile, filePanel.sortOptions.data) + fileElement = returnDirElement(filePanel.location, m.toggleDotFile, filePanel.sortOptions.data) } // Update file panel list filePanel.element = fileElement