Example #1
0
// 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())
		}
	}
}
Example #2
0
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())
}