feat(ui): navigate to top/botton of readme and files

Ayman Bagabas created

Change summary

ui/components/code/code.go | 11 ++++++++
ui/keymap/keymap.go        | 48 ++++++++++++++++++++++++++++++----------
ui/pages/repo/files.go     |  5 ++-
ui/pages/repo/readme.go    |  2 +
4 files changed, 51 insertions(+), 15 deletions(-)

Detailed changes

ui/components/code/code.go 🔗

@@ -6,6 +6,7 @@ import (
 	"sync"
 
 	"github.com/alecthomas/chroma/lexers"
+	"github.com/charmbracelet/bubbles/key"
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/charmbracelet/glamour"
 	gansi "github.com/charmbracelet/glamour/ansi"
@@ -98,10 +99,18 @@ func (r *Code) Init() tea.Cmd {
 // Update implements tea.Model.
 func (r *Code) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 	cmds := make([]tea.Cmd, 0)
-	switch msg.(type) {
+	switch msg := msg.(type) {
 	case tea.WindowSizeMsg:
 		// Recalculate content width and line wrap.
 		cmds = append(cmds, r.Init())
+	case tea.KeyMsg:
+		// Viewport doesn't handle these keys, so we do it here.
+		switch {
+		case key.Matches(msg, r.common.KeyMap.GotoTop):
+			r.GotoTop()
+		case key.Matches(msg, r.common.KeyMap.GotoBottom):
+			r.GotoBottom()
+		}
 	}
 	v, cmd := r.Viewport.Update(msg)
 	r.Viewport = v.(*vp.Viewport)

ui/keymap/keymap.go 🔗

@@ -4,18 +4,20 @@ import "github.com/charmbracelet/bubbles/key"
 
 // KeyMap is a map of key bindings for the UI.
 type KeyMap struct {
-	Quit      key.Binding
-	Up        key.Binding
-	Down      key.Binding
-	UpDown    key.Binding
-	LeftRight key.Binding
-	Arrows    key.Binding
-	Select    key.Binding
-	Section   key.Binding
-	Back      key.Binding
-	PrevPage  key.Binding
-	NextPage  key.Binding
-	Help      key.Binding
+	Quit       key.Binding
+	Up         key.Binding
+	Down       key.Binding
+	UpDown     key.Binding
+	LeftRight  key.Binding
+	Arrows     key.Binding
+	GotoTop    key.Binding
+	GotoBottom key.Binding
+	Select     key.Binding
+	Section    key.Binding
+	Back       key.Binding
+	PrevPage   key.Binding
+	NextPage   key.Binding
+	Help       key.Binding
 
 	SelectItem key.Binding
 	BackItem   key.Binding
@@ -103,6 +105,28 @@ func DefaultKeyMap() *KeyMap {
 		),
 	)
 
+	km.GotoTop = key.NewBinding(
+		key.WithKeys(
+			"home",
+			"g",
+		),
+		key.WithHelp(
+			"g/home",
+			"goto top",
+		),
+	)
+
+	km.GotoBottom = key.NewBinding(
+		key.WithKeys(
+			"end",
+			"G",
+		),
+		key.WithHelp(
+			"G/end",
+			"goto bottom",
+		),
+	)
+
 	km.Select = key.NewBinding(
 		key.WithKeys(
 			"enter",

ui/pages/repo/files.go 🔗

@@ -131,9 +131,9 @@ func (f *Files) ShortHelp() []key.Binding {
 // FullHelp implements help.KeyMap.
 func (f *Files) FullHelp() [][]key.Binding {
 	b := make([][]key.Binding, 0)
+	copyKey := f.common.KeyMap.Copy
 	switch f.activeView {
 	case filesViewFiles:
-		copyKey := f.common.KeyMap.Copy
 		copyKey.SetHelp("c", "copy name")
 		k := f.selector.KeyMap
 		b = append(b, []key.Binding{
@@ -154,7 +154,6 @@ func (f *Files) FullHelp() [][]key.Binding {
 			},
 		}...)
 	case filesViewContent:
-		copyKey := f.common.KeyMap.Copy
 		copyKey.SetHelp("c", "copy content")
 		k := f.code.KeyMap
 		b = append(b, []key.Binding{
@@ -171,6 +170,8 @@ func (f *Files) FullHelp() [][]key.Binding {
 		lc := []key.Binding{
 			k.Down,
 			k.Up,
+			f.common.KeyMap.GotoTop,
+			f.common.KeyMap.GotoBottom,
 			copyKey,
 		}
 		lexer := lexers.Match(f.currentContent.ext)

ui/pages/repo/readme.go 🔗

@@ -62,6 +62,8 @@ func (r *Readme) FullHelp() [][]key.Binding {
 		{
 			k.Down,
 			k.Up,
+			r.common.KeyMap.GotoTop,
+			r.common.KeyMap.GotoBottom,
 		},
 	}
 	return b