// NewNavigator constructs a new navigator object and waits indefinitely // for commands sent to it. It sends an updated buffer whenever the // navigator changes state. // This function is meant to be run in a goroutine. func NewNavigator(path string, commands <-chan string, buffers chan<- *view.Buffer) { navigator := new(Navigator) // Link the navigator up to the view. navigator.view = buffers // Set the initial working directory using // the path passed in as an argument. navigator.SetWorkingDirectory(path) for { select { case command := <-commands: // A command has arrived. // Invoke the command on the navigator. switch command { case "SelectNextEntry": navigator.SelectNextEntry() case "SelectLastEntry": navigator.SelectLastEntry() case "SelectPreviousEntry": navigator.SelectPreviousEntry() case "SelectFirstEntry": navigator.SelectFirstEntry() case "SortEntries": navigator.SortEntries() case "IntoSelectedEntry": navigator.IntoSelectedEntry() case "ToParentDirectory": navigator.ToParentDirectory() case "RemoveSelectedEntry": navigator.RemoveSelectedEntry() } // Refresh the view. buffers <- navigator.View(view.Height()) case directorySize := <-navigator.DirectorySizes: // A directory size calculation has completed. // Update the stored entry size and flag it as calculated. navigator.entries[directorySize.Index].Size = directorySize.Size navigator.entries[directorySize.Index].SizeCalculated = true // Reduce this count so the view increases the completion percentage. navigator.pendingCalculations-- // Update the view, since we have another directory size. navigator.view <- navigator.View(view.Height()) } } }
func (navigator *Navigator) populateEntries() { var size int64 // Read the directory entries. dirEntries, _ := ioutil.ReadDir(navigator.currentPath + "/") navigator.entries = make([]*directory.Entry, len(dirEntries)) // Allocate a buffered channel on which we'll receive // directory sizes from size-calculating goroutines. navigator.DirectorySizes = make(chan *directory.EntrySize, len(dirEntries)) // Reset the number of pending calculations. navigator.pendingCalculations = 0 for index, entry := range dirEntries { entryInfo, _ := os.Stat(navigator.currentPath + "/" + entry.Name()) // Figure out the entry's size differently // depending on whether or not it's a directory. if entryInfo.IsDir() { navigator.pendingCalculations++ // Calculate the directory's size asynchronously, passing the current // index so that we know where to put the result when we receive it later on. go directory.Size(navigator.currentPath+"/"+entry.Name(), index, navigator.DirectorySizes) } else { size = entryInfo.Size() } // Store the entry details. navigator.entries[index] = &directory.Entry{Name: entry.Name(), Size: size, IsDirectory: entryInfo.IsDir(), SizeCalculated: !entryInfo.IsDir()} } // Update the view, since we have sizes for files. navigator.view <- navigator.View(view.Height()) }