orderednodes

package module
v0.0.0-...-31af595 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 25, 2024 License: MIT Imports: 7 Imported by: 4

README

orderednodes

Nodes with ordered children, to use for XML mixed content and with golang os.DirFS

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

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

type FilePropsNord struct {
	Nord
	FU.FSItem
}

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 InspectorFunc func(pNode Norder) error

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

func NewNord(aRelPath string) *Nord

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) AbsFP

func (p *Nord) AbsFP() string

AbsFP is duh.

func (*Nord) AddKid

func (p *Nord) AddKid(aKid Norder) Norder

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) Echo

func (p *Nord) Echo() string

Echo implements Markupper.

func (*Nord) FirstKid

func (p *Nord) FirstKid() Norder

FirstKid provides read-only access for other packages. Can return nil.

func (*Nord) GetLineSummaryFunc

func (p *Nord) GetLineSummaryFunc() StringFunc

func (*Nord) GetRoot

func (p *Nord) GetRoot() Norder

GetRoot is duh.

func (*Nord) HasKids

func (p *Nord) HasKids() bool

HasKids is duh.

func (*Nord) IsDir

func (p *Nord) IsDir() bool

IsDir does NOT work, because we are not setting bool isDir yet. It is set (or not set) in embedding structs.

func (*Nord) IsRoot

func (p *Nord) IsRoot() bool

IsRoot is duh.

func (*Nord) KidsAsSlice

func (p *Nord) KidsAsSlice() []Norder

func (*Nord) LastKid

func (p *Nord) LastKid() Norder

LastKid provides read-only access for other packages. Can return nil.

func (*Nord) Level

func (p *Nord) Level() int

Level is duh.

func (Nord) LinePrefixString

func (p Nord) LinePrefixString() string

LinePrefixString provides indentation and should start a line of display/debug.

It does not end the string with (white)space. .

func (*Nord) LineSummaryString

func (p *Nord) LineSummaryString() string

func (*Nord) NextKid

func (p *Nord) NextKid() Norder

NextKid provides read-only access for other packages. Can return nil.

func (*Nord) Parent

func (p *Nord) Parent() Norder

Parent returns the parent, duh.

func (*Nord) PrevKid

func (p *Nord) PrevKid() Norder

PrevKid provides read-only access for other packages. Can return nil.

func (*Nord) PrintCssTree

func (p *Nord) PrintCssTree(w io.Writer) error

func (*Nord) PrintTree

func (p *Nord) PrintTree(w io.Writer) error

func (*Nord) RelFP

func (p *Nord) RelFP() string

RelFP is duh.

func (*Nord) ReplaceWith

func (pOld *Nord) ReplaceWith(pNew Norder) Norder

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) SeqID

func (p *Nord) SeqID() int

SeqId is duh.

func (*Nord) SetFirstKid

func (p *Nord) SetFirstKid(p2 Norder)

SetFirstKid has no side effects.

func (*Nord) SetLastKid

func (p *Nord) SetLastKid(p2 Norder)

SetLastKid has no side effects.

func (*Nord) SetLineSummaryFunc

func (p *Nord) SetLineSummaryFunc(sf StringFunc)

func (*Nord) SetNextKid

func (p *Nord) SetNextKid(p2 Norder)

SetNextKid has no side effects.

func (*Nord) SetParent

func (p *Nord) SetParent(p2 Norder)

SetParent has no side effects.

func (*Nord) SetPrevKid

func (p *Nord) SetPrevKid(p2 Norder)

SetPrevKid has no side effects.

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 ReplacerFunc func(Norder) Norder

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

type StringFunc func(Norder) string

StringFunc is used by interface Norder, so its method signature actually (MAYBE!) looks like: func (*Norder) FuncName() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL