mirror of
https://github.com/Maks1mS/bubbles.git
synced 2025-01-11 14:38:10 +03:00
Viewport now has customizable keybindings
This commit is contained in:
parent
9c70b6a216
commit
4aed4e0a88
42
viewport/keymap.go
Normal file
42
viewport/keymap.go
Normal file
@ -0,0 +1,42 @@
|
||||
package viewport
|
||||
|
||||
import "github.com/charmbracelet/bubbles/key"
|
||||
|
||||
const spacebar = " "
|
||||
|
||||
// KeyMap defines the keybindings for the viewport. Note that you don't
|
||||
// necessary need to use keybindings at all; the viewport can be controlled
|
||||
// programmatically with methods like Model.LineDown(1). See the GoDocs for
|
||||
// details.
|
||||
type KeyMap struct {
|
||||
PageDown key.Binding
|
||||
PageUp key.Binding
|
||||
HalfPageUp key.Binding
|
||||
HalfPageDown key.Binding
|
||||
Down key.Binding
|
||||
Up key.Binding
|
||||
}
|
||||
|
||||
// DefaultKeyMap returns a set of pager-like default keybindings.
|
||||
func DefaultKeyMap() KeyMap {
|
||||
return KeyMap{
|
||||
PageDown: key.NewBinding(
|
||||
key.WithKeys("pgdown", spacebar, "f"),
|
||||
),
|
||||
PageUp: key.NewBinding(
|
||||
key.WithKeys("pgup", "b"),
|
||||
),
|
||||
HalfPageUp: key.NewBinding(
|
||||
key.WithKeys("u", "ctrl+u"),
|
||||
),
|
||||
HalfPageDown: key.NewBinding(
|
||||
key.WithKeys("d", "ctrl+d"),
|
||||
),
|
||||
Up: key.NewBinding(
|
||||
key.WithKeys("up", "k"),
|
||||
),
|
||||
Down: key.NewBinding(
|
||||
key.WithKeys("down", "j"),
|
||||
),
|
||||
}
|
||||
}
|
@ -4,18 +4,34 @@ import (
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/bubbles/key"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
)
|
||||
|
||||
const (
|
||||
spacebar = " "
|
||||
mouseWheelDelta = 3
|
||||
)
|
||||
// NewModel returns a new model with the given width and height as well as
|
||||
// default keymappings.
|
||||
func NewModel(width, height int) Model {
|
||||
return Model{
|
||||
Width: width,
|
||||
Height: height,
|
||||
KeyMap: DefaultKeyMap(),
|
||||
MouseWheelEnabled: true,
|
||||
MouseWheelDelta: 3,
|
||||
}
|
||||
}
|
||||
|
||||
// Model is the Bubble Tea model for this viewport element.
|
||||
type Model struct {
|
||||
Width int
|
||||
Height int
|
||||
KeyMap KeyMap
|
||||
|
||||
// Whether or not to respond to the mouse. The mouse must be enabled in
|
||||
// Bubble Tea for this to work. For details, see the Bubble Tea docs.
|
||||
MouseWheelEnabled bool
|
||||
|
||||
// The number of lines the mouse wheel will scroll. By default, this is 3.
|
||||
MouseWheelDelta int
|
||||
|
||||
// YOffset is the vertical scroll position.
|
||||
YOffset int
|
||||
@ -37,6 +53,11 @@ type Model struct {
|
||||
lines []string
|
||||
}
|
||||
|
||||
// Init exists to satisfy the tea.Model interface for composability purposes.
|
||||
func (m Model) Init() tea.Cmd {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AtTop returns whether or not the viewport is in the very top position.
|
||||
func (m Model) AtTop() bool {
|
||||
return m.YOffset <= 0
|
||||
@ -227,54 +248,52 @@ func ViewUp(m Model, lines []string) tea.Cmd {
|
||||
return tea.ScrollUp(lines, top, bottom)
|
||||
}
|
||||
|
||||
// UPDATE
|
||||
|
||||
// Update runs the update loop with default keybindings similar to popular
|
||||
// pagers. To define your own keybindings use the methods on Model (i.e.
|
||||
// Model.LineDown()) and define your own update function.
|
||||
// Update handles standard message-based viewport updates.
|
||||
func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
|
||||
var cmd tea.Cmd
|
||||
m, cmd = m.updateAsModel(msg)
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
// Author's note: this method has been broken out to make it easier to
|
||||
// potentially transition Update to satisfy tea.Model.
|
||||
func (m Model) updateAsModel(msg tea.Msg) (Model, tea.Cmd) {
|
||||
var cmd tea.Cmd
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case tea.KeyMsg:
|
||||
switch msg.String() {
|
||||
// Down one page
|
||||
case "pgdown", spacebar, "f":
|
||||
switch {
|
||||
case key.Matches(msg, m.KeyMap.PageDown):
|
||||
lines := m.ViewDown()
|
||||
if m.HighPerformanceRendering {
|
||||
cmd = ViewDown(m, lines)
|
||||
}
|
||||
|
||||
// Up one page
|
||||
case "pgup", "b":
|
||||
case key.Matches(msg, m.KeyMap.PageUp):
|
||||
lines := m.ViewUp()
|
||||
if m.HighPerformanceRendering {
|
||||
cmd = ViewUp(m, lines)
|
||||
}
|
||||
|
||||
// Down half page
|
||||
case "d", "ctrl+d":
|
||||
case key.Matches(msg, m.KeyMap.HalfPageDown):
|
||||
lines := m.HalfViewDown()
|
||||
if m.HighPerformanceRendering {
|
||||
cmd = ViewDown(m, lines)
|
||||
}
|
||||
|
||||
// Up half page
|
||||
case "u", "ctrl+u":
|
||||
case key.Matches(msg, m.KeyMap.HalfPageUp):
|
||||
lines := m.HalfViewUp()
|
||||
if m.HighPerformanceRendering {
|
||||
cmd = ViewUp(m, lines)
|
||||
}
|
||||
|
||||
// Down one line
|
||||
case "down", "j":
|
||||
case key.Matches(msg, m.KeyMap.Down):
|
||||
lines := m.LineDown(1)
|
||||
if m.HighPerformanceRendering {
|
||||
cmd = ViewDown(m, lines)
|
||||
}
|
||||
|
||||
// Up one line
|
||||
case "up", "k":
|
||||
case key.Matches(msg, m.KeyMap.Up):
|
||||
lines := m.LineUp(1)
|
||||
if m.HighPerformanceRendering {
|
||||
cmd = ViewUp(m, lines)
|
||||
@ -282,15 +301,18 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
|
||||
}
|
||||
|
||||
case tea.MouseMsg:
|
||||
if !m.MouseWheelEnabled {
|
||||
break
|
||||
}
|
||||
switch msg.Type {
|
||||
case tea.MouseWheelUp:
|
||||
lines := m.LineUp(mouseWheelDelta)
|
||||
lines := m.LineUp(m.MouseWheelDelta)
|
||||
if m.HighPerformanceRendering {
|
||||
cmd = ViewUp(m, lines)
|
||||
}
|
||||
|
||||
case tea.MouseWheelDown:
|
||||
lines := m.LineDown(mouseWheelDelta)
|
||||
lines := m.LineDown(m.MouseWheelDelta)
|
||||
if m.HighPerformanceRendering {
|
||||
cmd = ViewDown(m, lines)
|
||||
}
|
||||
@ -300,8 +322,6 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
// VIEW
|
||||
|
||||
// View renders the viewport into a string.
|
||||
func (m Model) View() string {
|
||||
if m.HighPerformanceRendering {
|
||||
|
Loading…
Reference in New Issue
Block a user