From 029c7dfd929d44c2f6dae53a5e54ffecc0c52674 Mon Sep 17 00:00:00 2001 From: plastikfan Date: Wed, 29 Nov 2023 07:38:38 +0000 Subject: [PATCH] feat(nav): fix! new dual sampling adapter, use for file/folders (#373) --- .vscode/settings.json | 1 + xfs/nav/navigation-agent.go | 31 ++-- xfs/nav/navigator-abstract.go | 4 + xfs/nav/navigator-files.go | 1 - xfs/nav/navigator-folders.go | 25 ++- xfs/nav/navigator-universal.go | 6 - xfs/nav/sampling-adapters.go | 34 +++- xfs/nav/sampling-while-iterator.go | 241 +++++++++++++++++------------ xfs/nav/traverse-defs.go | 1 + xfs/nav/traverse-sample_test.go | 7 +- 10 files changed, 224 insertions(+), 127 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 3e68f13..ec906d3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "cSpell.words": [ + "Aphex", "argh", "Assisable", "avfs", diff --git a/xfs/nav/navigation-agent.go b/xfs/nav/navigation-agent.go index a3a935c..f55a9d8 100644 --- a/xfs/nav/navigation-agent.go +++ b/xfs/nav/navigation-agent.go @@ -144,9 +144,10 @@ func (a *navigationAgent) traverse(params *agentTraverseParams) (*TraverseItem, var current *TraverseItem if a.samplingFilterActive { - inspection, found := a.cache[params.parent.key()] + inspection, found := a.cache[path] current = lo.TernaryF(found, func() *TraverseItem { + inspection.current.previewing = false return inspection.current }, func() *TraverseItem { @@ -166,17 +167,20 @@ func (a *navigationAgent) traverse(params *agentTraverseParams) (*TraverseItem, } } + // fmt.Printf("===> šŸ’”šŸ’”šŸ’” agent.traverse - item: '%v' (admit: '%v', previewing: '%v')\n", + // current.Path, current.admit, current.previewing, + // ) + + // AMBIENT-TECHNO + // if strings.HasSuffix(current.Path, "AMBIENT-TECHNO") { + // fmt.Printf("===> šŸ“šŸ“šŸ“ folder.inspect [admit: %v] '%v'...\n", + // current.admit, current.Path, + // ) + // } + if skipItem, err := params.impl.traverse(&traverseParams{ - current: &TraverseItem{ - Path: path, - Info: info, - Entry: entry, - Error: e, - Children: []fs.DirEntry{}, - Parent: params.parent, - }, - // šŸ’„šŸ’„šŸ’„ current: current, - frame: params.frame, + current: current, + frame: params.frame, }); skipItem == dontSkipTraverseItem { if err != nil { if errors.Is(err, fs.SkipDir) { @@ -210,3 +214,8 @@ func (a *navigationAgent) traverse(params *agentTraverseParams) (*TraverseItem, return dontSkipTraverseItem, nil } + +func (a *navigationAgent) keep(stash *inspection) { + a.cache[stash.current.key()] = stash + stash.current.filtered() +} diff --git a/xfs/nav/navigator-abstract.go b/xfs/nav/navigator-abstract.go index 28ed311..a8da808 100644 --- a/xfs/nav/navigator-abstract.go +++ b/xfs/nav/navigator-abstract.go @@ -115,3 +115,7 @@ func (n *navigator) ascend(navi *NavigationInfo) { func (n *navigator) finish() error { return n.log.Get().Sync() } + +func (n *navigator) keep(stash *inspection) { + n.agent.keep(stash) +} diff --git a/xfs/nav/navigator-files.go b/xfs/nav/navigator-files.go index 5694870..2cb7613 100644 --- a/xfs/nav/navigator-files.go +++ b/xfs/nav/navigator-files.go @@ -22,7 +22,6 @@ func (n *filesNavigator) top(frame *navigationFrame, root string) (*TraverseResu func (n *filesNavigator) preview(params *traverseParams) *inspection { stash := n.inspect(params) - n.agent.cache[params.current.key()] = stash return stash } diff --git a/xfs/nav/navigator-folders.go b/xfs/nav/navigator-folders.go index f37ae3d..4460662 100644 --- a/xfs/nav/navigator-folders.go +++ b/xfs/nav/navigator-folders.go @@ -1,7 +1,9 @@ package nav import ( + "fmt" "io/fs" + "strings" "github.com/samber/lo" ) @@ -27,8 +29,11 @@ func (n *foldersNavigator) top(frame *navigationFrame, root string) (*TraverseRe } func (n *foldersNavigator) preview(params *traverseParams) *inspection { + fmt.Printf("===> šŸ€šŸ€šŸ€ folders.preview - item: '%v'\n", + params.current.Path, + ) + stash := n.inspect(params) - n.agent.cache[params.current.key()] = stash return stash } @@ -47,6 +52,13 @@ func (n *foldersNavigator) inspect(params *traverseParams) *inspection { stash.entries = stash.contents.Folders stash.contents.sort(stash.entries) + // AMBIENT-TECHNO + if strings.HasSuffix(params.current.Path, "AMBIENT-TECHNO") { + fmt.Printf("===> šŸ‡šŸ‡šŸ‡ folder.inspect [admit: %v] '%v'...\n", + params.current.admit, params.current.Path, + ) + } + if n.o.Store.Subscription == SubscribeFoldersWithFiles { var files []fs.DirEntry @@ -94,6 +106,13 @@ func (n *foldersNavigator) traverse(params *traverseParams) (*TraverseItem, erro params.navi = navi n.descend(navi) + // AMBIENT-TECHNO + // if strings.HasSuffix(navi.Item.Path, "AMBIENT-TECHNO") { + // fmt.Printf("===> šŸ‘šŸ‘šŸ‘ folder.traverse [admit: %v] '%v'...\n", + // navi.Item.admit, navi.Item.Path, + // ) + // } + // >>> fmt.Printf("\nšŸ„šŸ„šŸ„ FOLDER-NAV: inspecting item: '%v'\n", params.current.Path) stash := n.inspect(params) entries := stash.entries @@ -116,10 +135,6 @@ func (n *foldersNavigator) traverse(params *traverseParams) (*TraverseItem, erro return nil, err } - if n.samplingFilterActive && navi.Item.admit { - return navi.Item, nil - } - return n.agent.traverse(&agentTraverseParams{ impl: n, entries: entries, diff --git a/xfs/nav/navigator-universal.go b/xfs/nav/navigator-universal.go index 4e51d4c..202c46b 100644 --- a/xfs/nav/navigator-universal.go +++ b/xfs/nav/navigator-universal.go @@ -21,9 +21,7 @@ func (n *universalNavigator) top(frame *navigationFrame, root string) (*Traverse } func (n *universalNavigator) preview(params *traverseParams) *inspection { - params.current.previewing = true stash := n.inspect(params) - n.agent.cache[params.current.key()] = stash return stash } @@ -85,10 +83,6 @@ func (n *universalNavigator) traverse(params *traverseParams) (*TraverseItem, er } } - if n.samplingFilterActive && navi.Item.admit { - return navi.Item, nil - } - if le := params.frame.proxy(params.current, nil); le != nil { return nil, le } diff --git a/xfs/nav/sampling-adapters.go b/xfs/nav/sampling-adapters.go index 5254fd5..7545fed 100644 --- a/xfs/nav/sampling-adapters.go +++ b/xfs/nav/sampling-adapters.go @@ -6,6 +6,8 @@ import ( "github.com/samber/lo" ) +const samplingFiles = true + func createSamplingAdapters() samplingAdaptersCollection { universal := samplingAdapters{ slice: func(contents *DirectoryContents, noOf *SampleNoOf, fn sliceEntriesFunc) { @@ -30,7 +32,20 @@ func createSamplingAdapters() samplingAdaptersCollection { filterWithIt: func(contents *DirectoryContents, iterator *directoryEntryWhileIt) { // šŸ’„ contents.Files = iterator.sample(contents.Files) // šŸ’„ contents.Folders = iterator.sample(contents.Folders) - iterator.samples(contents) + // iterator.samplesL(contents) + + // intended new universal functionality to match monomorphic form: + // for _, i := range contents.Folders { + // fmt.Printf("===> universal filterWithIt(before) šŸ°šŸ°šŸ° folder '%v'\n", + // i.Name(), + // ) + // } + contents.Files, contents.Folders = iterator.samples(contents) + // for _, i := range contents.Folders { + // fmt.Printf("===> universal filterWithIt(after) šŸ©šŸ©šŸ© folder '%v'\n", + // i.Name(), + // ) + // } }, isFull: func(fi *FilteredInfo, noOf *SampleNoOf) bool { if fi.Counts.Files == noOf.Files { @@ -49,7 +64,18 @@ func createSamplingAdapters() samplingAdaptersCollection { contents.Folders = fn(contents.Folders, int(noOf.Folders)) }, filterWithIt: func(contents *DirectoryContents, iterator *directoryEntryWhileIt) { - contents.Folders = iterator.sample(contents.Folders) + // iterator.samples(contents) + // for _, i := range contents.Folders { + // fmt.Printf("===> filterWithIt(before) šŸ°šŸ°šŸ° folder '%v'\n", + // i.Name(), + // ) + // } + contents.Folders = iterator.sample(contents.Folders, !samplingFiles) + // for _, i := range contents.Folders { + // fmt.Printf("===> filterWithIt(after) šŸ©šŸ©šŸ© folder '%v'\n", + // i.Name(), + // ) + // } }, isFull: func(fi *FilteredInfo, noOf *SampleNoOf) bool { return fi.Counts.Folders == noOf.Folders @@ -61,7 +87,9 @@ func createSamplingAdapters() samplingAdaptersCollection { contents.Files = fn(contents.Files, int(noOf.Files)) }, filterWithIt: func(contents *DirectoryContents, iterator *directoryEntryWhileIt) { - contents.Files = iterator.sample(contents.Files) + // iterator.samples(contents) + contents.Files = iterator.sample(contents.Files, samplingFiles) + // contents.Files = iterator.sample(contents.Files, true) }, isFull: func(fi *FilteredInfo, noOf *SampleNoOf) bool { return fi.Counts.Files == noOf.Files diff --git a/xfs/nav/sampling-while-iterator.go b/xfs/nav/sampling-while-iterator.go index 5be402a..cd9aa68 100644 --- a/xfs/nav/sampling-while-iterator.go +++ b/xfs/nav/sampling-while-iterator.go @@ -1,7 +1,6 @@ package nav import ( - "fmt" "io/fs" "path/filepath" @@ -108,8 +107,7 @@ func (i *directoryEntryWhileIt) withParams(tp *traverseParams) { i.tp = tp } -// sample creates a sample with a new collection of directories entries -func (i *directoryEntryWhileIt) sample(entries []fs.DirEntry) []fs.DirEntry { +func (i *directoryEntryWhileIt) start(entries []fs.DirEntry) { if utils.IsNil(i.iterator) { i.iterator = lo.TernaryF(i.forward, func() collections.Iterator[fs.DirEntry] { @@ -122,108 +120,75 @@ func (i *directoryEntryWhileIt) sample(entries []fs.DirEntry) []fs.DirEntry { } else { i.iterator.Reset(entries) } +} + +// sample creates a sample with a new collection of directories entries +func (i *directoryEntryWhileIt) sample(entries []fs.DirEntry, processingFiles bool) []fs.DirEntry { + i.start(entries) + + result := i.universalLoop(func(entry fs.DirEntry, _ *FilteredInfo, result *DirectoryContents) { + if processingFiles { + result.Files = append(result.Files, entry) + } else { + result.Folders = append(result.Folders, entry) + } + }) - return i.loop() + return lo.Ternary[[]fs.DirEntry](processingFiles, result.Files, result.Folders) } -func (i *directoryEntryWhileIt) samples( +type appendFunc func(entry fs.DirEntry, fi *FilteredInfo, result *DirectoryContents) + +func (i *directoryEntryWhileIt) samplesL( sourceEntries *DirectoryContents, ) { - all := sourceEntries.All() - - if utils.IsNil(i.iterator) { - i.iterator = lo.TernaryF(i.forward, - func() collections.Iterator[fs.DirEntry] { - return collections.BeginIt[fs.DirEntry](all, i.zero) - }, - func() collections.Iterator[fs.DirEntry] { - return collections.ReverseIt[fs.DirEntry](all, i.zero) - }, - ) - } else { - i.iterator.Reset(all) - } + i.start(sourceEntries.All()) + + result := i.universalLoop(func(entry fs.DirEntry, _ *FilteredInfo, result *DirectoryContents) { + if entry.IsDir() { + // fi.Counts.Folders++ + result.Folders = append(result.Folders, entry) + } else { + // fi.Counts.Files++ + result.Files = append(result.Files, entry) + } + }) - result := i.universalLoop() sourceEntries.Files = result.Files sourceEntries.Folders = result.Folders } -func (i *directoryEntryWhileIt) universalLoop() *DirectoryContents { - result := newEmptyDirectoryEntries(i.o) - parent := i.tp.current - - var fi FilteredInfo - - if parent.Extension.Name == "Selected Ambient Works 85-92" { - fmt.Printf("===> šŸ‡šŸ‡šŸ‡ [admit: %v] Selected Ambient Works 85-92, getting files ...\n", - parent.admit, - ) - } - - for entry := i.iterator.Start(); i.while(&fi); entry = i.iterator.Next() { - if entry == nil { - break - } - - info, err := entry.Info() - - if i.universal { - if fi.Enough.Files && !info.IsDir() { - break - } - - if fi.Enough.Folders && info.IsDir() { - break - } - } - - path := filepath.Join(parent.Path, entry.Name()) - child := &TraverseItem{ - Path: path, - Info: info, - Entry: entry, - Error: err, - Parent: parent, - } - - i.navigator.preview(&traverseParams{ - current: child, - frame: i.tp.frame, - navi: &NavigationInfo{ - Options: i.tp.navi.Options, - Item: child, - frame: i.tp.frame, - }, - }) - - if i.each(child) { - if info.IsDir() { - fi.Counts.Folders++ - result.Folders = append(result.Folders, entry) - } else { - fi.Counts.Files++ - result.Files = append(result.Files, entry) - } - - child.filtered() +func (i *directoryEntryWhileIt) samples( + sourceEntries *DirectoryContents, +) ([]fs.DirEntry, []fs.DirEntry) { + i.start(sourceEntries.All()) + + rez := i.universalLoop(func(entry fs.DirEntry, _ *FilteredInfo, result *DirectoryContents) { + if entry.IsDir() { + // fi.Counts.Folders++ + result.Folders = append(result.Folders, entry) + } else { + // fi.Counts.Files++ + result.Files = append(result.Files, entry) } - } + }) - return result + return rez.Files, rez.Folders } -func (i *directoryEntryWhileIt) loop() []fs.DirEntry { - result := []fs.DirEntry{} +func (i *directoryEntryWhileIt) universalLoop(appender appendFunc) *DirectoryContents { + result := newEmptyDirectoryEntries(i.o) // can we pass in pre-allocation counts? parent := i.tp.current var fi FilteredInfo - if parent.Extension.Name == "Selected Ambient Works 85-92" { - fmt.Printf("===> šŸ‡šŸ‡šŸ‡ [admit: %v] Selected Ambient Works 85-92, getting files ...\n", - parent.admit, - ) - } + // tag := "Tales Of Ephidrina" + + // if parent.Extension.Name == tag { + // fmt.Printf("===> šŸ‡šŸ‡šŸ‡ [admit: %v] Selected '%v', getting files ...\n", + // parent.admit, tag, + // ) + // } for entry := i.iterator.Start(); i.while(&fi); entry = i.iterator.Next() { if entry == nil { @@ -244,14 +209,15 @@ func (i *directoryEntryWhileIt) loop() []fs.DirEntry { path := filepath.Join(parent.Path, entry.Name()) child := &TraverseItem{ - Path: path, - Info: info, - Entry: entry, - Error: err, - Parent: parent, + Path: path, + Info: info, + Entry: entry, + Error: err, + Parent: parent, + previewing: true, } - i.navigator.preview(&traverseParams{ + stash := i.navigator.preview(&traverseParams{ current: child, frame: i.tp.frame, navi: &NavigationInfo{ @@ -262,17 +228,96 @@ func (i *directoryEntryWhileIt) loop() []fs.DirEntry { }) if i.each(child) { - result = append(result, entry) - - if info.IsDir() { + // fmt.Printf("===> šŸŸ¢šŸŸ¢šŸŸ¢ whit - ACCEPT item: '%v' (admit: '%v', previewing: '%v')\n", + // child.Path, child.admit, child.previewing, + // ) + i.navigator.keep(stash) + + // if entry.Name() == "01 - Xtal.flac" { + // fmt.Printf("===> ā­• whit - APPEND item: '%v'\n", + // child.Path, + // ) + // } + appender(entry, &fi, result) + + if entry.IsDir() { fi.Counts.Folders++ } else { fi.Counts.Files++ } - - child.filtered() } + // else { + // fmt.Printf("===> ā›”ā›”ā›” whit - REJECT item: '%v'\n", + // child.Path, + // ) + // } } return result } + +// ----------------------------------------------------------------------------------------- + +// func (i *directoryEntryWhileIt) loop() []fs.DirEntry { +// result := []fs.DirEntry{} +// parent := i.tp.current + +// var fi FilteredInfo + +// if parent.Extension.Name == "Selected Ambient Works 85-92" { +// fmt.Printf("===> šŸ‡šŸ‡šŸ‡ [admit: %v] Selected Ambient Works 85-92, getting files ...\n", +// parent.admit, +// ) +// } + +// for entry := i.iterator.Start(); i.while(&fi); entry = i.iterator.Next() { +// if entry == nil { +// break +// } + +// info, err := entry.Info() + +// if i.universal { +// if fi.Enough.Files && !info.IsDir() { +// break +// } + +// if fi.Enough.Folders && info.IsDir() { +// break +// } +// } + +// path := filepath.Join(parent.Path, entry.Name()) +// child := &TraverseItem{ +// Path: path, +// Info: info, +// Entry: entry, +// Error: err, +// Parent: parent, +// } + +// i.navigator.preview(&traverseParams{ +// current: child, +// frame: i.tp.frame, +// navi: &NavigationInfo{ +// Options: i.tp.navi.Options, +// Item: child, +// frame: i.tp.frame, +// }, +// }) + +// if i.each(child) { +// result = append(result, entry) + +// if info.IsDir() { +// fi.Counts.Folders++ +// } else { +// fi.Counts.Files++ +// } + +// child.filtered() +// } +// } + +// return result +// } diff --git a/xfs/nav/traverse-defs.go b/xfs/nav/traverse-defs.go index 1ab3cc3..2d839c3 100644 --- a/xfs/nav/traverse-defs.go +++ b/xfs/nav/traverse-defs.go @@ -165,6 +165,7 @@ type traverseParams struct { type inspector interface { preview(params *traverseParams) *inspection inspect(params *traverseParams) *inspection + keep(stash *inspection) } type navigatorImpl interface { diff --git a/xfs/nav/traverse-sample_test.go b/xfs/nav/traverse-sample_test.go index 71b4dfe..492ee4f 100644 --- a/xfs/nav/traverse-sample_test.go +++ b/xfs/nav/traverse-sample_test.go @@ -149,7 +149,7 @@ var _ = Describe("Traverse With Sample", Ordered, func() { }, }), - Entry(nil, &sampleTE{ // šŸ”„šŸ”„šŸ”„ infinity + Entry(nil, &sampleTE{ naviTE: naviTE{ message: "universal(filter): first, single file, first 2 folders", should: "invoke for at most single file per directory", @@ -173,7 +173,7 @@ var _ = Describe("Traverse With Sample", Ordered, func() { }, }), - Entry(nil, &sampleTE{ // šŸ”„šŸ”„šŸ”„ infinity + Entry(nil, &sampleTE{ naviTE: naviTE{ message: "universal(filter): last, last single files, last 2 folders", should: "invoke for at most single file per directory", @@ -240,13 +240,14 @@ var _ = Describe("Traverse With Sample", Ordered, func() { filter: &filterTE{ name: "items with that start with A", pattern: "A*", - scope: nav.ScopeAllEn, + scope: nav.ScopeFolderEn, }, sampleType: nav.SampleTypeFilterEn, noOf: nav.SampleNoOf{ Folders: 2, }, expectedNoOf: directoryQuantities{ + // AMBIENT-TECHNO, Amorphous Androgynous, Aphex Twin folders: 3, }, }),