forked from varia/go-sh-manymanuals
wip: showing pdf viewport
This commit is contained in:
parent
e347b4924c
commit
fd88becf55
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
/datasheets/
|
||||
debug.log
|
||||
gshmm
|
||||
|
@ -19,5 +19,6 @@ manuals and datasheets for everything in [Varia](https://varia.zone).
|
||||
|
||||
```
|
||||
mkdir -p datasheets # fill with https://vvvvvvaria.org/~crunk/datasheets.zip
|
||||
tail -f debug.log # in another terminal
|
||||
go run goshmm.go
|
||||
```
|
||||
|
3
go.mod
3
go.mod
@ -5,13 +5,14 @@ go 1.18
|
||||
require (
|
||||
github.com/charmbracelet/bubbles v0.15.0
|
||||
github.com/charmbracelet/bubbletea v0.23.1
|
||||
github.com/charmbracelet/lipgloss v0.6.0
|
||||
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80
|
||||
github.com/sahilm/fuzzy v0.1.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/atotto/clipboard v0.1.4 // indirect
|
||||
github.com/aymanbagabas/go-osc52 v1.0.3 // indirect
|
||||
github.com/charmbracelet/lipgloss v0.6.0 // indirect
|
||||
github.com/containerd/console v1.0.3 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
|
2
go.sum
2
go.sum
@ -13,6 +13,8 @@ github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARu
|
||||
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo=
|
||||
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
|
128
gshmm.go
128
gshmm.go
@ -1,14 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/bubbles/textinput"
|
||||
"github.com/charmbracelet/bubbles/viewport"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/ledongthuc/pdf"
|
||||
"github.com/sahilm/fuzzy"
|
||||
)
|
||||
|
||||
@ -35,18 +41,60 @@ func handleCliFlags() {
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
func readPDF(name string) (string, error) {
|
||||
file, reader, err := pdf.Open(name)
|
||||
if err != nil {
|
||||
return "", errors.Unwrap(err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if e := file.Close(); e != nil {
|
||||
err = e
|
||||
}
|
||||
}()
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
buffer, err := reader.GetPlainText()
|
||||
|
||||
if err != nil {
|
||||
return "", errors.Unwrap(err)
|
||||
}
|
||||
|
||||
_, err = buf.ReadFrom(buffer)
|
||||
if err != nil {
|
||||
return "", errors.Unwrap(err)
|
||||
}
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
type model struct {
|
||||
filterInput textinput.Model // fuzzy search interface
|
||||
datasheets []string // all datasheets under cwd
|
||||
dataSheetsView []string // filtered view on all datasheets
|
||||
filterInput textinput.Model // fuzzy search interface
|
||||
datasheets []datasheet // all datasheets under cwd
|
||||
dataSheetsView []string // filtered view on all datasheets
|
||||
dataSheetViewport viewport.Model
|
||||
}
|
||||
|
||||
func (m model) dataSheetNames() []string {
|
||||
var names []string
|
||||
for _, datasheet := range m.datasheets {
|
||||
names = append(names, datasheet.filename)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
type datasheet struct {
|
||||
filename string
|
||||
absPath string
|
||||
contents string
|
||||
}
|
||||
|
||||
func initialModel() model {
|
||||
input := textinput.New()
|
||||
input.Focus()
|
||||
|
||||
var ds []string
|
||||
// TODO(d1): handle error in interface?
|
||||
var ds []datasheet
|
||||
// TODO: handle error in interface?
|
||||
_ = filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
@ -54,35 +102,50 @@ func initialModel() model {
|
||||
|
||||
name := info.Name()
|
||||
if strings.HasSuffix(name, "pdf") {
|
||||
ds = append(ds, name)
|
||||
// TODO: handle error in interface?
|
||||
contents, _ := readPDF(path)
|
||||
d := datasheet{
|
||||
filename: name,
|
||||
absPath: path,
|
||||
contents: contents,
|
||||
}
|
||||
ds = append(ds, d)
|
||||
log.Print(d)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return model{
|
||||
filterInput: input,
|
||||
datasheets: ds,
|
||||
dataSheetsView: ds,
|
||||
viewp := viewport.New(60, 30)
|
||||
viewp.SetContent(ds[len(ds)-1].contents)
|
||||
|
||||
m := model{
|
||||
filterInput: input,
|
||||
datasheets: ds,
|
||||
dataSheetViewport: viewp,
|
||||
}
|
||||
// TODO: which index is the datasheet closest to the filter input?
|
||||
m.dataSheetsView = m.dataSheetNames()
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (m model) Init() tea.Cmd {
|
||||
// TODO(d1): implement reading all PDFs in cwd
|
||||
// https://stackoverflow.com/a/67214584
|
||||
// requires error reporting also
|
||||
return textinput.Blink
|
||||
}
|
||||
|
||||
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
var cmd tea.Cmd
|
||||
var (
|
||||
cmd tea.Cmd
|
||||
cmds []tea.Cmd
|
||||
)
|
||||
|
||||
if m.filterInput.Focused() {
|
||||
var matched []string
|
||||
|
||||
search := m.filterInput.Value()
|
||||
if len(search) >= minCharsUntilFilter {
|
||||
matches := fuzzy.Find(search, m.datasheets)
|
||||
matches := fuzzy.Find(search, m.dataSheetNames())
|
||||
for _, match := range matches {
|
||||
matched = append(matched, match.Str)
|
||||
}
|
||||
@ -90,12 +153,11 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
if len(matches) > 0 {
|
||||
m.dataSheetsView = matched
|
||||
} else {
|
||||
m.dataSheetsView = m.datasheets
|
||||
m.dataSheetsView = m.dataSheetNames()
|
||||
}
|
||||
} else {
|
||||
m.dataSheetsView = m.datasheets
|
||||
m.dataSheetsView = m.dataSheetNames()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
switch msg := msg.(type) {
|
||||
@ -107,17 +169,25 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
}
|
||||
|
||||
m.filterInput, cmd = m.filterInput.Update(msg)
|
||||
cmds = append(cmds, cmd)
|
||||
|
||||
return m, cmd
|
||||
// TODO figure out how update viewport when filtering
|
||||
// the last item in m.dataSheetsView should be shown
|
||||
m.dataSheetViewport, cmd = m.dataSheetViewport.Update(msg)
|
||||
cmds = append(cmds, cmd)
|
||||
|
||||
return m, tea.Batch(cmds...)
|
||||
}
|
||||
|
||||
func (m model) View() string {
|
||||
body := strings.Builder{}
|
||||
|
||||
// TODO(d1): paginate / trim view to last 10 or something?
|
||||
body.WriteString(strings.Join(m.dataSheetsView, "\n") + "\n")
|
||||
// TODO: paginate / trim view to last 10 or something?
|
||||
sheets := strings.Join(m.dataSheetsView, "\n")
|
||||
panes := lipgloss.JoinHorizontal(lipgloss.Left, sheets, m.dataSheetViewport.View())
|
||||
body.WriteString(panes)
|
||||
|
||||
body.WriteString(m.filterInput.View() + "\n")
|
||||
body.WriteString("\n" + m.filterInput.View())
|
||||
|
||||
return body.String()
|
||||
}
|
||||
@ -130,7 +200,19 @@ func main() {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
p := tea.NewProgram(initialModel(), tea.WithAltScreen())
|
||||
f, err := tea.LogToFile("debug.log", "debug")
|
||||
if err != nil {
|
||||
fmt.Println("fatal:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
p := tea.NewProgram(
|
||||
initialModel(),
|
||||
tea.WithAltScreen(),
|
||||
tea.WithMouseCellMotion(),
|
||||
)
|
||||
|
||||
if err := p.Start(); err != nil {
|
||||
fmt.Printf("oops, something went wrong: %v", err)
|
||||
os.Exit(1)
|
||||
|
Loading…
Reference in New Issue
Block a user