Documentation ¶
Index ¶
- Constants
- Variables
- func DexRemove(kegpath string, entry *DexEntry) error
- func DexUpdate(kegpath string, entry *DexEntry) error
- func Edit(kegpath string, id int) error
- func GrepTags(kegdir, tags string) (string, error)
- func HaveDex(kegpath string) bool
- func Import(kegpath string, targets ...string) error
- func ImportNode(kegpath, target string) error
- func MakeDex(kegdir string) error
- func Publish(kegpath string) error
- func Tag(kegdir, id, tags string) error
- func Tags(kegdir string) string
- func UpdateUpdated(kegpath string) error
- func Updated(kegpath string) (*time.Time, error)
- func UpdatedString(kegpath string) string
- func WriteDex(kegpath string, dex *Dex) error
- func WriteSample(kegpath string, entry *DexEntry) error
- type Dex
- func (d *Dex) Add(entry *DexEntry)
- func (e Dex) AsIncludes() string
- func (d Dex) ByChanges() Dex
- func (d Dex) ByID() Dex
- func (d *Dex) ChooseWithTitleText(key string) *DexEntry
- func (d *Dex) ChooseWithTitleTextExp(re *regexp.Regexp) *DexEntry
- func (d *Dex) Delete(entry *DexEntry)
- func (d Dex) Last() *DexEntry
- func (d Dex) LastChanged() *DexEntry
- func (d Dex) LastChangedIdString() string
- func (d Dex) LastChangedIdWidth() int
- func (d Dex) LastIdString() string
- func (d Dex) LastIdWidth() int
- func (d Dex) Lookup(id int) *DexEntry
- func (e Dex) MD() string
- func (d *Dex) MarshalJSON() ([]byte, error)
- func (d Dex) Pretty() string
- func (d Dex) PrettyLines() []string
- func (d Dex) Random() *DexEntry
- func (e Dex) String() string
- func (e Dex) TSV() string
- func (e *Dex) WithTitleText(keyword string) Dex
- func (e *Dex) WithTitleTextExp(re *regexp.Regexp) Dex
- type DexEntry
- type Local
- type TagsMap
Examples ¶
Constants ¶
const IsoDateExpStr = `\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\dZ`
const IsoDateFmt = `2006-01-02 15:04:05Z`
Variables ¶
var ChangesDefault = 5
var Cmd = &Z.Cmd{ Name: `keg`, Aliases: []string{`kn`}, Version: `v0.9.2`, UseVars: true, Copyright: `Copyright 2022 Robert S Muhlestein`, License: `Apache-2.0`, Site: `rwxrob.tv`, Source: `git@github.com:rwxrob/keg.git`, Issues: `https://github.com/rwxrob/keg/issues`, ConfVars: true, Summary: help.S(_keg), Description: help.D(_keg), Commands: []*Z.Cmd{ editCmd, help.Cmd, conf.Cmd, vars.Cmd, indexCmd, createCmd, currentCmd, directoryCmd, deleteCmd, lastCmd, changesCmd, titlesCmd, initCmd, randomCmd, importCmd, grepCmd, viewCmd, columnsCmd, linkCmd, tagCmd, }, Shortcuts: Z.ArgMap{ `set`: {`var`, `set`}, `unset`: {`var`, `unset`}, `get`: {`var`, `get`}, `sample`: {`create`, `sample`}, }, }
var DefColumns = 100
var LatestDexEntryExp = regexp.MustCompile(
`^\* (\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\dZ) \[(.*)\]\(\.\./(\d+)\)$`,
)
var NodePaths = _fs.IntDirs
NodePaths returns a list of node directory paths contained in the keg root directory path passed. Paths returns are fully qualified and cleaned. Only directories with valid integer node IDs will be recognized. Empty slice is returned if kegroot doesn't point to directory containing node directories with integer names.
The lowest and highest integer names are returned as well to help determine what to name a new directory.
File and directories that do not have an integer name will be ignored.
var SampleNodeReadme string
Functions ¶
func DexRemove ¶ added in v0.8.1
DexRemove removes an entry without changing the current sort order of dex/changes.md and calls WriteDex without a ScanDex.
func DexUpdate ¶ added in v0.4.0
DexUpdate first checks the keg at kegpath for an existing dex/changes.md file and if found loads it, if not, MakeDex is called to create it. Then DexUpdate examines the Dex for the DexEntry passed and if found updates it with the new information, otherwise, it will add the new entry without any further validation and call WriteDex create the dex files and update keg file.
func Edit ¶ added in v0.4.0
Edit calls file.Edit on the given node README.md file within the given kegpath.
func GrepTags ¶ added in v0.9.0
GrepTags returns all the lines from dex/tags with any of the tags listed (separated by comma).
Example ¶
package main import ( "fmt" "github.com/rwxrob/keg" ) func main() { str, err := keg.GrepTags(`testdata/samplekeg`, `foo`) if err != nil { fmt.Println(err) } fmt.Println(str) }
Output: foo 2 6 3
Example (Multiple) ¶
package main import ( "fmt" "github.com/rwxrob/keg" ) func main() { str, err := keg.GrepTags(`testdata/samplekeg`, `foo,bar`) if err != nil { fmt.Println(err) } fmt.Println(str) }
Output: foo 2 6 3 bar 8
func HaveDex ¶ added in v0.4.0
HaveDex returns true if keg at kegpath has a dex/changes.md file.
Example ¶
package main import ( "fmt" "github.com/rwxrob/keg" ) func main() { fmt.Println(keg.HaveDex(`testdata/samplekeg`)) fmt.Println(keg.HaveDex(`testdata/nothing`)) }
Output: true false
func Import ¶ added in v0.6.0
Import imports the targets into the kegpath creating new, unique identifiers for each. If the target ends with an integer it is assumed to be a node directory. If not, it is assumed to contain node directories with integer identifiers. Currently, there is no resolution of any links contained within any node README.md file.
func ImportNode ¶
ImportNode imports a single specific directory into the kegpath by getting the next integer identifier and moving the target into the kegpath with an os.Rename (which has limitations based on the host operating system's handling of cross-file system boundaries).
func MakeDex ¶
MakeDex calls ScanDex and writes (or overwrites) the output to the reserved dex node file within the kegdir passed. File-level locking is attempted using the go-internal/lockedfile (used by Go itself). Both a friendly markdown file reverse sorted by time of last update (changes.md) and a tab-delimited file sorted numerically by node ID (nodes.tsv) are created. Any empty content node directory is automatically removed. Empty is defined to be one that only contains 0-length files, recursively.
func Publish ¶ added in v0.2.0
Publish publishes the keg at kegpath location to its distribution targets listed in the keg file under "publish." Currently, this only involves looking for a .git directory and if found doing a git pull/add/commit/push. Git commit messages are always based on the latest node title without any verb.
func Tag ¶ added in v0.9.0
Tag will add the id specified to the dex/tags file, one entry for each line containing one of the comma-separated tags. The rwxrob/fs/file.Overwrite function is used preventing concurrent writes to the file, but it is possible that the file could change by another process before the Overwrite takes place. Therefore, other measures to preserve transactional integrity should be taken where needed. If the dex/tags file does not exist will create it.
func Tags ¶ added in v0.9.0
Tags returns a space separated string with all the tags currently in use (even if no nodes yet assigned).
func UpdateUpdated ¶
UpdateUpdated sets the updated YAML field in the keg info file.
func Updated ¶
Updated parses the most recent change time in the dex/node.md file (the first line) and returns the time stamp it contains as a time.Time. If a time stamp could not be determined returns time.
func UpdatedString ¶
UpdatedString returns Updated time as a string or an empty string if there is a error.
Example ¶
package main import ( "fmt" "github.com/rwxrob/keg" ) func main() { fmt.Println(keg.UpdatedString(`testdata/samplekeg`)) }
Output: 2022-11-26 19:33:24Z
func WriteDex ¶ added in v0.4.0
WriteDex writes the dex/changes.md and dex/nodes.tsv files to the keg at kegpath and calls UpdateUpdated to keep keg info file in sync.
func WriteSample ¶ added in v0.4.1
WriteSample writes the embedded SampleNodeReadme to the entry indicated in the keg specified by kegpath.
Types ¶
type Dex ¶
type Dex []*DexEntry
Dex is a collection of DexEntry structs. This allows mapping methods for its serialization to different output formats.
Example (Json) ¶
package main import ( "encoding/json" "fmt" "time" "github.com/rwxrob/keg" ) func main() { date := time.Date(2022, 12, 10, 6, 10, 4, 0, time.UTC) d := keg.DexEntry{U: date, N: 2, T: `Some title`} byt, err := json.Marshal(d) if err != nil { fmt.Println(err) } fmt.Println(string(byt)) }
Output: {"U":"2022-12-10T06:10:04Z","T":"Some title","N":2,"HBeg":0,"HEnd":0}
Example (String) ¶
package main import ( "fmt" "time" "github.com/rwxrob/keg" ) func main() { date := time.Date(2022, 12, 10, 6, 10, 4, 0, time.UTC) d := keg.DexEntry{U: date, N: 2, T: `Some title`} fmt.Println(d) fmt.Println(d.MD()) }
Output: * 2022-12-10 06:10:04Z [Some title](../2) * 2022-12-10 06:10:04Z [Some title](../2)
Example (Tsv) ¶
package main import ( "fmt" "time" "github.com/rwxrob/keg" ) func main() { date := time.Date(2022, 12, 10, 6, 10, 4, 0, time.UTC) d := keg.DexEntry{U: date, N: 2, T: `Some title`} fmt.Println(d.TSV()) }
Output: 2 2022-12-10 06:10:04Z Some title
func ParseDex ¶
ParseDex parses any input valid for to.String into a Dex pointer. FIXME: replace regular expression with pegn.Scanner instead
func (Dex) AsIncludes ¶
AsIncludes renders the entire Dex as a KEGML include list (markdown bulleted list) and cab be useful from within editing sessions to include from the current keg without leaving the terminal editor.
func (Dex) ByChanges ¶ added in v0.5.0
ByChanges sorts the Dex from most recently changed to oldest. A pointer to self is returned for convenience.
func (Dex) ByID ¶
ByID sorts the Dex from lowest to highest node ID integer. A pointer to self is returned for convenience.
func (*Dex) ChooseWithTitleText ¶ added in v0.3.1
ChooseWithTitleText returns a single *DexEntry for the keyword passed. If there are more than one then user is prompted to choose from list sent to the terminal.
func (*Dex) ChooseWithTitleTextExp ¶ added in v0.7.0
ChooseWithTitleTextExp returns a single *DexEntry for the regular expression matches passed. If there are more than one then user is prompted to choose from list sent to the terminal.
func (*Dex) Delete ¶ added in v0.8.1
Delete removes the specified entry shrinking the slice without changing the underlying size of the supporting array while maintaining references to each DexEntry. Note that the persisted content node directory may still exist. This method only affects the Dex itself. Stops at first match.
Example ¶
package main import ( "fmt" "github.com/rwxrob/keg" ) func main() { one := &keg.DexEntry{N: 1, T: `One`} two := &keg.DexEntry{N: 2, T: `Two`} three := &keg.DexEntry{N: 3, T: `Three`} dex := &keg.Dex{one, two, three} dex.Delete(two) fmt.Println(dex.MD()) }
Output: * 0001-01-01 00:00:00Z [One](../1) * 0001-01-01 00:00:00Z [Three](../3)
func (Dex) Last ¶ added in v0.5.0
Last returns the DexEntry with the highest integer value identifier.
func (Dex) LastChanged ¶ added in v0.5.0
LastChanged returns the highest integer value identifier.
func (Dex) LastChangedIdString ¶ added in v0.5.0
LastChangedIdString returns Last as string.
func (Dex) LastChangedIdWidth ¶ added in v0.5.0
LastChangedIdWidth returns width of Last integer identifier.
func (Dex) LastIdString ¶ added in v0.5.0
LastIdString returns Last as string.
func (Dex) LastIdWidth ¶ added in v0.5.0
LastIdWidth returns width of Last integer identifier.
func (Dex) Lookup ¶ added in v0.4.0
Lookup does a linear search through the Dex for one with the passed id and if found returns, otherwise returns nil.
func (Dex) MD ¶
MD renders the entire Dex as a Markdown list suitable for the standard dex/changes.md file.
func (*Dex) MarshalJSON ¶
MarshalJSON produces JSON text that contains one DexEntry per line that has not been HTML escaped (unlike the default).
func (Dex) Pretty ¶ added in v0.2.3
Pretty returns a string with pretty color string with no time stamps rendered in more readable way.
func (Dex) PrettyLines ¶ added in v0.2.3
PrettyLines returns Pretty but each line separate and without line return.
func (Dex) String ¶
String fulfills the fmt.Stringer interface as JSON. Any error returns a "null" string.
func (*Dex) WithTitleText ¶
WithTitleText returns a new Dex from self with all nodes that do not contain the text substring in the title filtered out.
type DexEntry ¶
type DexEntry struct { U time.Time // updated T string // title N int // node id (also see ID) HBeg int // start of highlighted HEnd int // end of highlighted }
DexEntry represents a single line in an index (usually the changes.md or nodes.tsv file). All three fields are always required.
func Last ¶
Last returns the last created content node. If cannot determine returns nil
Example ¶
package main import ( "fmt" "github.com/rwxrob/keg" ) func main() { fmt.Println(keg.Last(`testdata/samplekeg`).N) fmt.Println(keg.Last(`testdata/noexist`)) }
Output: 12 <nil>
func LastChanged ¶ added in v0.5.0
LastChanged parses and returns a DexEntry of the most recently updated node from first line of the dex/changes.md file. If cannot determine returns nil.
func MakeNode ¶ added in v0.4.0
MakeNode examines the keg at kegpath for highest integer identifier and provides a new one returning a *DexEntry for it.
func Next ¶ added in v0.6.0
Next returns a new DexEntry with its integer identify set to the next integer after Last and returns nil if cannot determine which is next. The updated time stamp is set to the current time even though the DexEntry may not have yet been written to disk and its time would be different from the actual time written. This is to save the overhead of grabbing it again once written.
Example ¶
package main import ( "fmt" "github.com/rwxrob/keg" ) func main() { fmt.Println(keg.Next(`testdata/samplekeg`).N) fmt.Println(keg.Next(`testdata/noexist`)) }
Output: 13 <nil>
func (*DexEntry) AsInclude ¶
Asinclude returns a KEGML include link list item without the time suitable for creating include blocks in node files.
func (*DexEntry) ID ¶ added in v0.2.0
ID returns the node identifier as a string instead of an integer. Returns an empty string if unable to parse the integer.
func (*DexEntry) MD ¶
MD returns the entry as a single Markdown list item for inclusion in the dex/nodex.md file:
- Second last changed in UTC in ISO8601 (RFC3339)
- Current title (always first line of README.md)
- Unique node integer identifier
Note that the second of last change is based on *any* file within the node directory changing, not just the README.md or meta files.
func (*DexEntry) MarshalJSON ¶
MarshalJSON produces JSON text that contains one DexEntry per line that has not been HTML escaped (unlike the default) and that uses a consistent DateTime format. Note that the (broken) encoding/json encoder is not used at all.
func (*DexEntry) Pretty ¶ added in v0.5.0
Pretty returns a string with pretty colors.
Example ¶
package main import ( "fmt" "github.com/rwxrob/keg" ) func main() { e := keg.DexEntry{T: "Some"} fmt.Printf("%q\n", e.Pretty()) e.HBeg = 2 e.HEnd = 3 fmt.Printf("%q\n", e.Pretty()) }
Output: "\x1b[30m0001-01-01 00:00Z \x1b[32m0 \x1b[37mSome\x1b[0m\n" "\x1b[30m0001-01-01 00:00Z \x1b[32m0 \x1b[37mSo\x1b[31mm\x1b[37me\x1b[0m\n"
type TagsMap ¶ added in v0.9.0
func ReadTags ¶ added in v0.9.0
ReadTags reads an existing dex/tags files within the target keg directory. The tags file must have one tag group per line with the tag being the first field. Fields are separated by a single space for the most performant parsing possible.
Example ¶
package main import ( "fmt" "github.com/rwxrob/keg" ) func main() { tags, err := keg.ReadTags(`testdata/samplekeg`) if err != nil { fmt.Println(err) } fmt.Println(tags[`foo`][1]) }
Output: 6
func (TagsMap) MarshalText ¶ added in v0.9.0
func (TagsMap) UnmarshalText ¶ added in v0.9.0
UnmarshalText parses the tag lines items from the bytes buffer and sets the key pair for that tag to the values overwriting any that were already set.