M tab.go => tab.go +49 -4
@@ 35,6 35,11 @@ const (
type tabID uint64
+const (
+ homeURL = "home://"
+ helpURL = "help://"
+)
+
type Tab struct {
id tabID
mode mode
@@ 46,6 51,7 @@ type Tab struct {
history *history.History
bookmarks *bookmark.Store
lastResponse ServerResponse
+ specialPages map[string]func(Tab) string
}
func NewTab(client *gemini.Client, startURL string, bs *bookmark.Store, h *history.History, id tabID) Tab {
@@ 65,6 71,10 @@ func NewTab(client *gemini.Client, startURL string, bs *bookmark.Store, h *histo
viewport: NewViewport(startURL, h),
message: Message{},
bookmarks: bs,
+ specialPages: map[string]func(Tab) string{
+ homeURL: homeContent,
+ helpURL: helpContent,
+ },
}
}
@@ 190,7 200,7 @@ func (tab Tab) showInput(msg, val, payload string, typ int) (Tab, tea.Cmd) {
return tab, textinput.Blink
}
-func (tab Tab) homeContent() string {
+func homeContent(tab Tab) string {
var buf strings.Builder
fmt.Fprint(&buf, "# Home\n\n")
for _, bookmark := range builtinBookmarks {
@@ 204,6 214,40 @@ func (tab Tab) homeContent() string {
return buf.String()
}
+func helpContent(tab Tab) string {
+ s := `
+# Keys
+
+Go back h
+Go forward l
+Open link type number + enter
+Open link in tab type number + t
+Quit ctrl+c
+Next tab tab
+Previous tab shift+tab
+Goto tab alt+#
+Close tab q
+Goto URL g
+Download page d
+Home H
+Bookmark b
+Scroll up k
+Scroll download j
+Scroll up (page) Page up
+Scroll down (page) Page down
+
+
+# Mouse
+
+Open link Left click
+Open link in tab Middle click
+Close tab Middle click (on tab)
+Go back Right click
+Scroll Mouse wheel
+`
+ return s
+}
+
type LoadError struct {
err error
message string
@@ 305,7 349,8 @@ func (tab Tab) loadURL(url string, addHist bool, level int, skipVerify bool) (Ta
if !strings.Contains(url, "://") {
url = fmt.Sprintf("gemini://%s", url)
}
- if url != "home://" && !strings.HasPrefix(url, "gemini://") && !strings.HasPrefix(url, "gopher://") {
+ specialF, isSpecial := tab.specialPages[url]
+ if !isSpecial && !strings.HasPrefix(url, "gemini://") && !strings.HasPrefix(url, "gopher://") {
tab.viewport.loading = false
return tab.showMessage(fmt.Sprintf("Open %q externally?", url), url, messageLoadExternal, true)
}
@@ 319,11 364,11 @@ func (tab Tab) loadURL(url string, addHist bool, level int, skipVerify bool) (Ta
cmd := func() tea.Msg {
defer cancel()
- if url == "home://" {
+ if isSpecial {
if addHist {
tab.history.Add(url)
}
- return GeminiResponse{Response: &gemini.Response{Body: []byte(tab.homeContent()),
+ return GeminiResponse{Response: &gemini.Response{Body: []byte(specialF(tab)),
URL: url, Header: gemini.Header{Status: 2, Meta: "text/gemini"}}, level: level, tab: tab.id}
}
M viewport.go => viewport.go +12 -5
@@ 25,6 25,7 @@ const (
buttonGoto = "Goto"
buttonCloseTab = "Close Tab"
buttonQuit = "Quit"
+ buttonHelp = "Help"
)
type Viewport struct {
@@ 50,7 51,7 @@ func NewViewport(startURL string, h *history.History) Viewport {
URL: startURL,
spinner: s,
history: h,
- footer: NewFooter(buttonBack, buttonFwd, buttonHome, buttonBookmark, buttonDownload, buttonQuit),
+ footer: NewFooter(buttonBack, buttonFwd, buttonHome, buttonBookmark, buttonDownload, buttonHelp, buttonQuit),
}
}
@@ 104,7 105,6 @@ func (v Viewport) Update(msg tea.Msg) (Viewport, tea.Cmd) {
switch msg := msg.(type) {
case tea.WindowSizeMsg:
verticalMargins := headerHeight + footerHeight
-
if !v.ready {
v.viewport = viewport.Model{Width: msg.Width, Height: msg.Height - verticalMargins}
v.viewport.YPosition = headerHeight
@@ 113,7 113,7 @@ func (v Viewport) Update(msg tea.Msg) (Viewport, tea.Cmd) {
v.ready = true
startURL := v.URL
if startURL == "" {
- startURL = "home://"
+ startURL = homeURL
}
return v, fireEvent(LoadURLEvent{URL: startURL, AddHistory: v.history.Current() != startURL})
} else {
@@ 135,6 135,8 @@ func (v Viewport) Update(msg tea.Msg) (Viewport, tea.Cmd) {
return v, v.handleButtonClick(buttonHome)
case "b":
return v, v.handleButtonClick(buttonBookmark)
+ case "?":
+ return v, v.handleButtonClick(buttonHelp)
case "left", "h":
return v, v.handleButtonClick(buttonBack)
case "right", "l":
@@ 186,7 188,12 @@ func (v Viewport) handleButtonClick(btn string) tea.Cmd {
case buttonFwd:
return fireEvent(GoForwardEvent{})
case buttonHome:
- return fireEvent(LoadURLEvent{URL: "home://", AddHistory: true})
+ return fireEvent(LoadURLEvent{URL: homeURL, AddHistory: true})
+ case buttonHelp:
+ if v.URL == helpURL {
+ return fireEvent(GoBackEvent{})
+ }
+ return fireEvent(LoadURLEvent{URL: helpURL, AddHistory: true})
case buttonBookmark:
return fireEvent(ToggleBookmarkEvent{URL: v.URL, Title: v.title})
case buttonDownload:
@@ 195,7 202,7 @@ func (v Viewport) handleButtonClick(btn string) tea.Cmd {
Type: inputDownloadSrc})
case buttonGoto:
var val string
- if cur := v.history.Current(); cur != "home://" {
+ if cur := v.history.Current(); cur != homeURL && cur != helpURL {
val = cur
}
return fireEvent(ShowInputEvent{Message: "Go to", Type: inputNav, Payload: "", Value: val})