package mode
import (
)
type NavigationCursor interface {
Current() (NavigationFile, error)
Parent() (NavigationFile, error)
Ascend() error
Descend(name string) error
}
type NavigationFile interface {
Name() string
ShowName() ui.Text
IsDirDeep() bool
Read() ([]NavigationFile, []byte, error)
}
func () NavigationCursor {
return osCursor{lscolors.GetColorist()}
}
type osCursor struct{ colorist lscolors.Colorist }
func ( osCursor) () (NavigationFile, error) {
, := filepath.Abs(".")
if != nil {
return nil,
}
return file{filepath.Base(), , os.ModeDir, .colorist}, nil
}
func ( osCursor) () (NavigationFile, error) {
if , := filepath.Abs("."); == "/" {
return emptyDir{}, nil
}
, := filepath.Abs("..")
if != nil {
return nil,
}
return file{filepath.Base(), , os.ModeDir, .colorist}, nil
}
func ( osCursor) () error { return os.Chdir("..") }
func ( osCursor) ( string) error { return os.Chdir() }
type emptyDir struct{}
func (emptyDir) () string { return "" }
func (emptyDir) () ui.Text { return nil }
func (emptyDir) () bool { return true }
func (emptyDir) () ([]NavigationFile, []byte, error) { return []NavigationFile{}, nil, nil }
type file struct {
name string
path string
mode os.FileMode
colorist lscolors.Colorist
}
func ( file) () string { return .name }
func ( file) () ui.Text {
:= .colorist.GetStyle(.path)
return ui.Text{&ui.Segment{
Style: ui.StyleFromSGR(), Text: .name}}
}
func ( file) () bool {
if .mode.IsDir() {
return true
}
, := os.Stat(.path)
return == nil && .IsDir()
}
const previewBytes = 64 * 1024
var (
errDevice = errors.New("no preview for device file")
errNamedPipe = errors.New("no preview for named pipe")
errSocket = errors.New("no preview for socket file")
errCharDevice = errors.New("no preview for char device")
errNonUTF8 = errors.New("no preview for non-utf8 file")
)
var specialFileModes = []struct {
mode os.FileMode
err error
}{
{os.ModeDevice, errDevice},
{os.ModeNamedPipe, errNamedPipe},
{os.ModeSocket, errSocket},
{os.ModeCharDevice, errCharDevice},
}
func ( file) () ([]NavigationFile, []byte, error) {
, := os.Open(.path)
if != nil {
return nil, nil,
}
defer .Close()
, := .Stat()
if != nil {
return nil, nil,
}
if .IsDir() {
, := .Readdir(0)
if != nil {
return nil, nil,
}
:= make([]NavigationFile, len())
for , := range {
[] = file{
.Name(),
filepath.Join(.path, .Name()),
.Mode(),
.colorist,
}
}
return , nil,
}
for , := range specialFileModes {
if .Mode()&.mode != 0 {
return nil, nil, .err
}
}
var [previewBytes]byte
, := .Read([:])
if != nil && != io.EOF {
return nil, nil,
}
:= [:]
if !utf8.Valid() {
return nil, nil, errNonUTF8
}
return nil, , nil
}