1
0
mirror of https://github.com/mum4k/termdash.git synced 2025-04-25 13:48:50 +08:00

Ability to focus the previous container using keyboard.

This commit is contained in:
Jakub Sobon 2020-11-24 14:24:08 -05:00
parent 1fd4b044cf
commit e4edc8f15a
No known key found for this signature in database
GPG Key ID: F2451A77FB05D3B7
3 changed files with 160 additions and 12 deletions

View File

@ -278,8 +278,11 @@ func (c *Container) updateFocusFromMouse(m *terminalapi.Mouse) {
// changes the focused container.
// Caller must hold c.mu.
func (c *Container) updateFocusFromKeyboard(k *terminalapi.Keyboard) {
if c.opts.global.keyFocusNext != nil && *c.opts.global.keyFocusNext == k.Key {
switch {
case c.opts.global.keyFocusNext != nil && *c.opts.global.keyFocusNext == k.Key:
c.focusTracker.next()
case c.opts.global.keyFocusPrevious != nil && *c.opts.global.keyFocusPrevious == k.Key:
c.focusTracker.previous()
}
}

View File

@ -82,20 +82,20 @@ func (ft *focusTracker) setActive(c *Container) {
func (ft *focusTracker) next() {
var (
errStr string
first *Container
cont *Container
firstCont *Container
nextCont *Container
focusNext bool
)
postOrder(rootCont(ft.container), &errStr, visitFunc(func(c *Container) error {
if cont != nil {
preOrder(rootCont(ft.container), &errStr, visitFunc(func(c *Container) error {
if nextCont != nil {
// Already found the next container, nothing to do.
return nil
}
if c.isLeaf() && first == nil {
if c.isLeaf() && firstCont == nil {
// Remember the first eligible container in case we "wrap" over,
// i.e. finish the iteration before finding the next container.
first = c
firstCont = c
}
if ft.container == c {
@ -106,18 +106,49 @@ func (ft *focusTracker) next() {
}
if c.isLeaf() && focusNext {
cont = c
nextCont = c
}
return nil
}))
if cont == nil && first != nil {
if nextCont == nil && firstCont != nil {
// If the traversal finishes without finding the next container, move
// focus back to the first container.
cont = first
nextCont = firstCont
}
if cont != nil {
ft.setActive(cont)
if nextCont != nil {
ft.setActive(nextCont)
}
}
// previous moves focus to the previous container.
func (ft *focusTracker) previous() {
var (
errStr string
prevCont *Container
lastCont *Container
visitedCurr bool
)
preOrder(rootCont(ft.container), &errStr, visitFunc(func(c *Container) error {
if ft.container == c {
visitedCurr = true
}
if c.isLeaf() {
if !visitedCurr {
// Remember the last eligible container closest to the one
// currently focused.
prevCont = c
}
lastCont = c
}
return nil
}))
if prevCont != nil {
ft.setActive(prevCont)
} else if lastCont != nil {
ft.setActive(lastCont)
}
}

View File

@ -624,6 +624,120 @@ func TestFocusTrackerNextAndPrevious(t *testing.T) {
wantFocused: contLocLeft,
wantProcessed: 5,
},
{
desc: "keyPrevious does nothing when only root exists",
container: func(ft *faketerm.Terminal) (*Container, error) {
return New(
ft,
KeyFocusPrevious(keyPrevious),
)
},
events: []*terminalapi.Keyboard{
{Key: keyPrevious},
},
wantFocused: contLocRoot,
wantProcessed: 1,
},
{
desc: "keyPrevious focuses the last container",
container: func(ft *faketerm.Terminal) (*Container, error) {
return New(
ft,
SplitVertical(
Left(),
Right(),
),
KeyFocusPrevious(keyPrevious),
)
},
events: []*terminalapi.Keyboard{
{Key: keyPrevious},
},
wantFocused: contLocRight,
wantProcessed: 1,
},
{
desc: "two keyPrevious presses focuses the first container",
container: func(ft *faketerm.Terminal) (*Container, error) {
return New(
ft,
SplitVertical(
Left(),
Right(),
),
KeyFocusPrevious(keyPrevious),
)
},
events: []*terminalapi.Keyboard{
{Key: keyPrevious},
{Key: keyPrevious},
},
wantFocused: contLocLeft,
wantProcessed: 2,
},
{
desc: "three keyPrevious presses focuses the second container again",
container: func(ft *faketerm.Terminal) (*Container, error) {
return New(
ft,
SplitVertical(
Left(),
Right(),
),
KeyFocusPrevious(keyPrevious),
)
},
events: []*terminalapi.Keyboard{
{Key: keyPrevious},
{Key: keyPrevious},
{Key: keyPrevious},
},
wantFocused: contLocRight,
wantProcessed: 3,
},
{
desc: "four keyPrevious presses focuses the first container again",
container: func(ft *faketerm.Terminal) (*Container, error) {
return New(
ft,
SplitVertical(
Left(),
Right(),
),
KeyFocusPrevious(keyPrevious),
)
},
events: []*terminalapi.Keyboard{
{Key: keyPrevious},
{Key: keyPrevious},
{Key: keyPrevious},
{Key: keyPrevious},
},
wantFocused: contLocLeft,
wantProcessed: 4,
},
{
desc: "five keyPrevious presses focuses the second container again",
container: func(ft *faketerm.Terminal) (*Container, error) {
return New(
ft,
SplitVertical(
Left(),
Right(),
),
KeyFocusPrevious(keyPrevious),
)
},
events: []*terminalapi.Keyboard{
{Key: keyPrevious},
{Key: keyPrevious},
{Key: keyPrevious},
{Key: keyPrevious},
{Key: keyPrevious},
},
wantFocused: contLocRight,
wantProcessed: 5,
},
}
for _, tc := range tests {