diff --git a/gui/buffer.go b/gui/buffer.go index 377939d..5db5c06 100644 --- a/gui/buffer.go +++ b/gui/buffer.go @@ -131,6 +131,13 @@ func (b *Buffer) OnDispose() { func (b *Buffer) OnInit() {} +func (b *Buffer) setLine(idx int, val string) { + b.contents[idx] = rope.New(val) + if b.curs.y == idx { + b.moveToEndOfLine() + } +} + func (b *Buffer) appendLine(val string) { b.contents = append(b.contents, rope.New(val)) // because we've added a new line diff --git a/gui/palette.go b/gui/palette.go index 0e906d9..33a2ee1 100644 --- a/gui/palette.go +++ b/gui/palette.go @@ -20,18 +20,32 @@ func init() { type CommandPalette struct { BaseComponent - buff *Buffer - parentBuff *Buffer + buff *Buffer + parentBuff *Buffer + + suggestionIndex int recentSuggestions *[]suggestion } -const suggestionBoxHeight = 128 +var suggestionBoxHeight, suggestionBoxWidth = 48, 0 type suggestion struct { name string } +func (s *suggestion) renderHighlighted(x, y int, ctx *strife.Renderer) { + ctx.SetColor(strife.Blue) + ctx.Rect(x, y, suggestionBoxWidth, suggestionBoxHeight, strife.Fill) + + ctx.SetColor(strife.White) + ctx.String(s.name, x, y) +} + func (s *suggestion) render(x, y int, ctx *strife.Renderer) { + ctx.SetColor(strife.Red) + ctx.Rect(x, y, suggestionBoxWidth, suggestionBoxHeight, strife.Fill) + + ctx.SetColor(strife.White) ctx.String(s.name, x, y) } @@ -50,6 +64,8 @@ func NewCommandPalette(conf cfg.TomlConfig, view *View) *CommandPalette { palette.buff.Resize(palette.w, palette.h) palette.buff.Translate((view.w/2)-(palette.w/2), 10) + suggestionBoxWidth = palette.w + return palette } @@ -62,6 +78,8 @@ func (b *CommandPalette) processCommand() { tokenizedLine := strings.Split(b.buff.contents[0].String(), " ") command := tokenizedLine[0] + log.Println(tokenizedLine) + action, exists := actions[command] if !exists { return @@ -74,30 +92,89 @@ func (b *CommandPalette) calculateSuggestions() { tokenizedLine := strings.Split(b.buff.contents[0].String(), " ") command := tokenizedLine[0] + if command == "" { + b.recentSuggestions = nil + return + } + ranks := fuzzy.RankFind(command, commandSet) - suggestions := make([]suggestion, len(ranks)) + suggestions := []suggestion{} for _, r := range ranks { cmdName := commandSet[r.Index] + if cmdName == "" { + continue + } suggestions = append(suggestions, suggestion{cmdName}) } b.recentSuggestions = &suggestions } +func (b *CommandPalette) scrollSuggestion(dir int) { + if b.recentSuggestions != nil { + b.suggestionIndex += dir + + if b.suggestionIndex < 0 { + b.suggestionIndex = len(*b.recentSuggestions) - 1 + } else if b.suggestionIndex >= len(*b.recentSuggestions) { + b.suggestionIndex = 0 + } + } +} + func (b *CommandPalette) clearInput() { actions["delete_line"].proc(b.buff) } +func (b *CommandPalette) setToSuggested() { + if b.recentSuggestions == nil { + return + } + + // set the buffer + suggestions := *b.recentSuggestions + sugg := suggestions[b.suggestionIndex] + b.buff.setLine(0, sugg.name) + + // remove all suggestions + b.recentSuggestions = nil + b.suggestionIndex = -1 +} + func (b *CommandPalette) OnUpdate() bool { if !b.HasFocus() { return false } - override := func(k int) bool { - if k != sdl.K_RETURN && k != sdl.K_ESCAPE { + override := func(key int) bool { + switch key { + + case sdl.K_UP: + b.scrollSuggestion(-1) + return false + case sdl.K_DOWN: + b.scrollSuggestion(1) + return false + + // any other key we calculate + // the suggested commands + default: + b.suggestionIndex = -1 b.calculateSuggestions() return false + + case sdl.K_RETURN: + // we have a suggestion so let's + // fill the buffer with that instead! + if b.suggestionIndex != -1 { + b.setToSuggested() + return true + } + + fallthrough + case sdl.K_ESCAPE: + break } b.processCommand() @@ -121,7 +198,11 @@ func (b *CommandPalette) OnRender(ctx *strife.Renderer) { if b.recentSuggestions != nil { for i, sugg := range *b.recentSuggestions { - sugg.render(b.x, b.y+(i*suggestionBoxHeight), ctx) + if b.suggestionIndex != i { + sugg.render(b.x, b.y+((i+1)*suggestionBoxHeight), ctx) + } else { + sugg.renderHighlighted(b.x, b.y+((i+1)*suggestionBoxHeight), ctx) + } } } }