diff --git a/CHANGELOG.md b/CHANGELOG.md index a2e95ac..b80824b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,18 @@ ### Changed - Documentation for Lunacolors has been improved, with more information added. - Values returned by bait hooks will be passed to the `throw` caller +- `display` property to completion groups entries to style completion entries when type is `list`. +example: +```lua +local cg = { + items = { + 'list item 1', + ['--command-flag-here'] = {'this does a thing', '--the-flag-alias'}, + ['--styled-command-flag-here'] = {'this does a thing', '--the-flag-alias', display = lunacolors.blue '--styled-command-flag-here'} + }, + type = 'list' +} +``` ## [2.3.4] - 2024-12-28 ### Fixed diff --git a/docs/completions.md b/docs/completions.md index 59ead1b..75a9a34 100644 --- a/docs/completions.md +++ b/docs/completions.md @@ -56,6 +56,50 @@ return {cg, cg2}, prefix Which looks like this: {{< video src="https://safe.saya.moe/t4CiLK6dgPbD.mp4" >}} +# Completion Group Types +### grid +Grid is the simplest completion group type. All items are strings and when +completion is done is displayed in a grid based on size. + +Example: +```lua +{ + items = {'just', 'a bunch', 'of items', 'here', 'hehe'}, + type = 'grid' +} +``` + +### list +The list completion group type displays in a list. A list item can either be a string, or a table for additional display options. +A completion alias can be specified either as the `2nd` entry in the options table +or te `alias` key. + +A description can optionally be displayed for a list item, which is either the `1st` +entry or the `description` key. + +Lastly, list entries can be styled. This is done with the `display` key. If this is present, this +overrides what the completion item *looks* like. + +Example: +```lua +{ + items = { + ['--flag'] = { + description = 'this flag nukes the bri ish', + alias = '--bye-bri-ish', + display = lunacolors.format('--{blue}fl{red}ag') + }, + ['--flag2'] = { + 'make pizza', -- description + '--pizzuh', -- alias + display = lunacolors.yellow '--pizzuh' + }, + '--flag3' + }, + type = 'list' +} +``` + # Completion Handler Like most parts of Hilbish, it's made to be extensible and customizable. The default handler for completions in general can diff --git a/readline/comp-group.go b/readline/comp-group.go index b2ee4b8..74b528a 100644 --- a/readline/comp-group.go +++ b/readline/comp-group.go @@ -14,6 +14,7 @@ type CompletionGroup struct { Suggestions []string Aliases map[string]string // A candidate has an alternative name (ex: --long, -l option flags) Descriptions map[string]string // Items descriptions + ItemDisplays map[string]string // What to display the item as (can be used for styling items) DisplayType TabDisplayType // Map, list or normal MaxLength int // Each group can be limited in the number of comps offered diff --git a/readline/comp-list.go b/readline/comp-list.go index cdcda8f..403cf5d 100644 --- a/readline/comp-list.go +++ b/readline/comp-list.go @@ -217,6 +217,11 @@ func (g *CompletionGroup) writeList(rl *Instance) (comp string) { alt = strings.Repeat(" ", maxLengthAlt+1) // + 2 to keep account of spaces } + styledSugg, ok := g.ItemDisplays[item] + if ok { + sugg = fmt.Sprintf("\r%s%-"+cellWidth+"s", highlight(y, 0), fmtEscape(styledSugg)) + } + // Description description := g.Descriptions[g.Suggestions[i]] if len(description) > maxDescWidth { diff --git a/rl.go b/rl.go index 231d04b..b431ad7 100644 --- a/rl.go +++ b/rl.go @@ -138,10 +138,15 @@ func newLineReader(prompt string, noHist bool) *lineReader { items := []string{} itemDescriptions := make(map[string]string) + itemDisplays := make(map[string]string) + itemAliases := make(map[string]string) util.ForEach(luaCompItems.AsTable(), func(lkey rt.Value, lval rt.Value) { if keytyp := lkey.Type(); keytyp == rt.StringType { + // TODO: remove in 3.0 // ['--flag'] = {'description', '--flag-alias'} + // OR + // ['--flag'] = {description = '', alias = '', display = ''} itemName, ok := lkey.TryString() vlTbl, okk := lval.TryTable() if !ok && !okk { @@ -152,10 +157,22 @@ func newLineReader(prompt string, noHist bool) *lineReader { items = append(items, itemName) itemDescription, ok := vlTbl.Get(rt.IntValue(1)).TryString() if !ok { - // TODO: error - return + // if we can't get it by number index, try by string key + itemDescription, _ = vlTbl.Get(rt.StringValue("description")).TryString() } itemDescriptions[itemName] = itemDescription + + // display + if itemDisplay, ok := vlTbl.Get(rt.StringValue("display")).TryString(); ok { + itemDisplays[itemName] = itemDisplay + } + + itemAlias, ok := vlTbl.Get(rt.IntValue(2)).TryString() + if !ok { + // if we can't get it by number index, try by string key + itemAlias, _ = vlTbl.Get(rt.StringValue("alias")).TryString() + } + itemAliases[itemName] = itemAlias } else if keytyp == rt.IntType { vlStr, ok := lval.TryString() if !ok { @@ -179,7 +196,9 @@ func newLineReader(prompt string, noHist bool) *lineReader { compGroups = append(compGroups, &readline.CompletionGroup{ DisplayType: dispType, + Aliases: itemAliases, Descriptions: itemDescriptions, + ItemDisplays: itemDisplays, Suggestions: items, TrimSlash: false, NoSpace: true,