1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
package main
import (
tui "github.com/grindlemire/go-tui"
)
type viewer struct {
doc string
scrollY *tui.State[int]
content *tui.Ref
}
func Viewer() *viewer {
return &viewer{
doc: sampleDoc,
scrollY: tui.NewState(0),
content: tui.NewRef(),
}
}
func (v *viewer) scrollBy(delta int) {
el := v.content.El()
if el == nil {
return
}
_, maxY := el.MaxScroll()
newY := v.scrollY.Get() + delta
if newY < 0 {
newY = 0
}
if newY > maxY {
newY = maxY
}
v.scrollY.Set(newY)
}
func (v *viewer) KeyMap() tui.KeyMap {
return tui.KeyMap{
tui.On(tui.KeyEscape, func(ke tui.KeyEvent) { ke.App().Stop() }),
tui.On(tui.Rune('q'), func(ke tui.KeyEvent) { ke.App().Stop() }),
tui.On(tui.Rune('j'), func(ke tui.KeyEvent) { v.scrollBy(1) }),
tui.On(tui.Rune('k'), func(ke tui.KeyEvent) { v.scrollBy(-1) }),
tui.On(tui.KeyDown, func(ke tui.KeyEvent) { v.scrollBy(1) }),
tui.On(tui.KeyUp, func(ke tui.KeyEvent) { v.scrollBy(-1) }),
tui.On(tui.KeyPageDown, func(ke tui.KeyEvent) { v.scrollBy(10) }),
tui.On(tui.KeyPageUp, func(ke tui.KeyEvent) { v.scrollBy(-10) }),
}
}
func (v *viewer) HandleMouse(me tui.MouseEvent) bool {
switch me.Button {
case tui.MouseWheelUp:
v.scrollBy(-3)
return true
case tui.MouseWheelDown:
v.scrollBy(3)
return true
}
return false
}
// mdWidth makes the markdown responsive: the viewer has no border, padding, or
// visible scrollbar, so the text fills the full terminal width (wide terminals
// show unwrapped text, narrow ones wrap). Keeping lines flush to the edge means
// a copied selection carries no leading or trailing whitespace columns.
func (v *viewer) mdWidth(app *tui.App) int {
w, _ := app.Size()
if w < 10 {
w = 10
}
return w
}
templ (v *viewer) Render() {
<div class="flex-col">
<span class="text-gradient-cyan-magenta font-bold">Markdown Viewer</span>
<div
ref={v.content}
class="overflow-y-scroll scrollbar-hidden grow"
scrollOffset={0, v.scrollY.Get()}>
<markdown source={v.doc} width={v.mdWidth(app)} />
</div>
<span class="font-dim">scroll: wheel/j/k/arrows | select and click links natively | q/esc quit</span>
</div>
}
|