vim_navigation.go RawHistoryFolder
1package usecase
2
3import (
4 "context"
5 "errors"
6
7 "github.com/bnema/dumber/internal/application/dto"
8 "github.com/bnema/dumber/internal/application/port"
9)
10
11var (
12 errUnsupportedVimNavigationAction = errors.New("vim navigation: unsupported action")
13 errUnsupportedVimNavigationEngine = errors.New("vim navigation: unsupported webview capability")
14)
15
16// VimNavigationUseCase maps configured Vim Mode navigation actions to optional
17// WebView capabilities. The UI layer supplies the active WebView and remains
18// responsible only for event and theme context.
19type VimNavigationUseCase struct{}
20
21// NewVimNavigationUseCase creates a stateless Vim navigation use case.
22func NewVimNavigationUseCase() *VimNavigationUseCase {
23 return &VimNavigationUseCase{}
24}
25
26// Execute dispatches a configured semantic Vim action to the active WebView.
27func (*VimNavigationUseCase) Execute(ctx context.Context, wv port.WebView, action string, count int, highlightColor string) error {
28 if wv == nil {
29 return errors.New("vim navigation: nil webview")
30 }
31
32 if action == "focus-input" {
33 focuser, ok := wv.(port.PageInputFocuser)
34 if !ok {
35 return errUnsupportedVimNavigationEngine
36 }
37 focuser.FocusNextInput()
38 return nil
39 }
40
41 var request dto.SemanticNavigationRequest
42 switch action {
43 case "heading-next":
44 request = dto.SemanticNavigationRequest{
45 Target: dto.SemanticNavigationTargetHeading,
46 Direction: dto.SemanticNavigationForward,
47 Count: count,
48 HighlightColor: highlightColor,
49 }
50 case "heading-prev":
51 request = dto.SemanticNavigationRequest{
52 Target: dto.SemanticNavigationTargetHeading,
53 Direction: dto.SemanticNavigationBackward,
54 Count: count,
55 HighlightColor: highlightColor,
56 }
57 default:
58 return errUnsupportedVimNavigationAction
59 }
60
61 navigator, ok := wv.(port.SemanticNavigable)
62 if !ok {
63 return errUnsupportedVimNavigationEngine
64 }
65 return navigator.NavigateSemantic(ctx, request)
66}
67
68// ClearSemanticNavigationHighlight removes the visual target left by semantic
69// navigation when the active Vim Mode session ends.
70func (*VimNavigationUseCase) ClearSemanticNavigationHighlight(ctx context.Context, wv port.WebView) error {
71 if wv == nil {
72 return nil
73 }
74 clearer, ok := wv.(port.SemanticNavigationHighlightClearer)
75 if !ok {
76 return nil
77 }
78 return clearer.ClearSemanticNavigationHighlight(ctx)
79}
80
81// NavigatePageFocus keeps focus traversal inside a page when the active page
82// control would otherwise hand the host window a Tab event.
83func (*VimNavigationUseCase) NavigatePageFocus(wv port.WebView, backward bool) bool {
84 if wv == nil {
85 return false
86 }
87 navigator, ok := wv.(port.PageFocusNavigator)
88 if !ok {
89 return false
90 }
91 navigator.NavigatePageFocus(backward)
92 return true
93}