Documentation ¶
Overview ¶
Package orderednodes is a way to create a hierarchical tree of nodes, where the nodes are ordered and keep their order, and without needing or using Go generics.
Node order is of course important for markup in general and XML mixed content in particular, while unimportant when XML is used purely for data records.
interface Norder is implemented not for type Nord but rather for `*Nord´. NThis is so that nodes are writable.
Index ¶
- func InspectTree(p Norder, f InspectorFunc) error
- func InspectTreeWithPreAndPost(p Norder, f0 InspectorFunc, f1 InspectorFunc) error
- type FilePropsNord
- type InspectorFunc
- type Nord
- func (p *Nord) AbsFP() string
- func (p *Nord) AddKid(aKid Norder) Norder
- func (p *Nord) Echo() string
- func (p *Nord) FirstKid() Norder
- func (p *Nord) GetLineSummaryFunc() StringFunc
- func (p *Nord) GetRoot() Norder
- func (p *Nord) HasKids() bool
- func (p *Nord) IsDir() bool
- func (p *Nord) IsRoot() bool
- func (p *Nord) KidsAsSlice() []Norder
- func (p *Nord) LastKid() Norder
- func (p *Nord) Level() int
- func (p Nord) LinePrefixString() string
- func (p *Nord) LineSummaryString() string
- func (p *Nord) NextKid() Norder
- func (p *Nord) Parent() Norder
- func (p *Nord) PrevKid() Norder
- func (p *Nord) PrintCssTree(w io.Writer) error
- func (p *Nord) PrintTree(w io.Writer) error
- func (p *Nord) RelFP() string
- func (pOld *Nord) ReplaceWith(pNew Norder) Norder
- func (p *Nord) SeqID() int
- func (p *Nord) SetFirstKid(p2 Norder)
- func (p *Nord) SetLastKid(p2 Norder)
- func (p *Nord) SetLineSummaryFunc(sf StringFunc)
- func (p *Nord) SetNextKid(p2 Norder)
- func (p *Nord) SetParent(p2 Norder)
- func (p *Nord) SetPrevKid(p2 Norder)
- type NordEngine
- type Norder
- type ReplacerFunc
- type RootFilePropsNord
- type RootNord
- type StringFunc
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func InspectTree ¶
func InspectTree(p Norder, f InspectorFunc) error
func InspectTree used to be func WalkNorders .
func InspectTreeWithPreAndPost ¶
func InspectTreeWithPreAndPost(p Norder, f0 InspectorFunc, f1 InspectorFunc) error
Types ¶
type FilePropsNord ¶
FilePropsNord is an Ordered Propertied Path node: NOT ONLY the child nodes have a specific specified order BUT ALSO each node has a filepath plus the file item itself including its contents (in TypedRaw). This means Pthat every Parent node is a directory.
It also means we can use the redundancy to do a lot of error checking. Also we can use fields of seqId's to store parent and kid seqId's, adding yet another layer of error checking and simplified access.
type InspectorFunc ¶
type Nord ¶
type Nord struct {
// contains filtered or unexported fields
}
Nord is shorthand for "ordered node" - a Node with ordered children nodes: the child nodes have a specific specified order. It lets us define such funcs as FirstKid(), NextKid(), PrevKid(), LastKid(). They are defined in interface Norder. A Nord also contains its own relative path (relative to its inbatch) and absolute paths.
There are three use cases identified for Nords: files & directories, DOM markup, and [Lw]DITA map files. Note the possibility of name duplication: we never have two identically-named files in the same directory, but that we might (for example) have multiple sibling <p> tags. So when representing markup, a map from paths to Nords will fail unless the tags are made unique with subscript indices, such as "[1]", "[2]", like those used in (for example) JQuery.
NOTE: Compared to using Nord for XML, using Nord for files & dirs is much more strictly typed. Dirs are dirs and files are files and never the twain shall meet. This means that dirs cannot contain own-content and that files can never be non-leaf nodes. However this kind of typing is too complex to handle here in a Nord, so it is handled instead by a struct type that embeds Nord, such as [fileutils.FSItem].
If we build up a tree of Nords when processing an os.DirFS, the strict ordering provided by DirFS is not strictly needed, BUT it can anyways be used (and relied upon) because [io.fs.WalkDir] is deterministic (using lexical order). It means that a given Nord will always appear AFTER the Nord for its directory has appeared, which makes it much easier to build a tree.
Fields are lower-cased so that other packages cannot damage links.
NOTE that this Implementation uses a doubly-linked list, not a slice. Therefore a Nord does not store a complete set of pointers to all of its kids. Therefore (a) it is not simple to get a kid count, and (b) it is not feasible to use this same code to define a simpler variant of Nord that has unordered kids. .
func NewNord ¶
NewNord expects a relative path (!!), and does not either (a) set/unset the bool [isDir] or (b) load file content, because these are expensive operations that can and should be done elsewhere, and also (c) they do not apply if this is being used for XML DOM.
func NewRootNord ¶
func NewRootNord(rootPath string, smryFunc StringFunc) *Nord
NewRootNord verifies it got a directory, and then sets the bools [isRoot] and [isDir]. Note that the passed-in field [rootPath] is set elsewhere, and must be set in the global NordEng before any child Nord is created using NewNord.
func (*Nord) AddKid ¶
AddKid adds the supplied node as the last kid, and returns it (i.e. the new last kid), now linked into the tree.
func (*Nord) GetLineSummaryFunc ¶
func (p *Nord) GetLineSummaryFunc() StringFunc
func (*Nord) IsDir ¶
IsDir does NOT work, because we are not setting bool isDir yet. It is set (or not set) in embedding structs.
func (*Nord) KidsAsSlice ¶
func (Nord) LinePrefixString ¶
LinePrefixString provides indentation and should start a line of display/debug.
It does not end the string with (white)space. .
func (*Nord) LineSummaryString ¶
func (*Nord) ReplaceWith ¶
AddKid adds the supplied node as the last kid, and returns it (i.e. the new last kid), now linked into the tree.
func (*Nord) SetLineSummaryFunc ¶
func (p *Nord) SetLineSummaryFunc(sf StringFunc)
type NordEngine ¶
type NordEngine struct {
// contains filtered or unexported fields
}
NordEngine tracks the state of a Nord tree being assembled, for example when a directory is specified for recursive analysis.
var NordEng *NordEngine = new(NordEngine)
NordEng is a package global, which is dodgy and not re-entrant. The solution probably involves currying.
type Norder ¶
type Norder interface { // PUBLIC METHODS SeqID() int // SetSeqID(int) Level() int RelFP() string AbsFP() string IsRoot() bool GetRoot() Norder IsDir() bool // IsDirlike() bool // FIXME: add this! // SetIsRoot(bool) Parent() Norder HasKids() bool FirstKid() Norder LastKid() Norder PrevKid() Norder NextKid() Norder KidsAsSlice() []Norder AddKid(Norder) Norder ReplaceWith(Norder) Norder SetParent(Norder) SetPrevKid(Norder) SetNextKid(Norder) SetFirstKid(Norder) SetLastKid(Norder) LinePrefixString() string LineSummaryString() string GetLineSummaryFunc() StringFunc // SetLineSummaryFunc(StringFunc) PrintTree(io.Writer) error // contains filtered or unexported methods }
Norder is satisfied by *Nord NOT by Nord
func ReplaceTree ¶
func ReplaceTree(oldRoot Norder, f ReplacerFunc) (newRoot Norder, err error)
type ReplacerFunc ¶
type RootFilePropsNord ¶
type RootFilePropsNord FilePropsNord
Available to ensure that assignments to/from root node are explicit.
type RootNord ¶
type RootNord Nord
RootNord is defined, so that assignments to/from a root node have to be explicit.
type StringFunc ¶
StringFunc is used by interface Norder, so its method signature actually (MAYBE!) looks like: func (*Norder) FuncName() string