|
|
@ -60,20 +60,13 @@ func readPDF(name string) (string, error) { |
|
|
|
|
|
|
|
// model offers the core of the state for the entire UI.
|
|
|
|
type model struct { |
|
|
|
filterInput textinput.Model // Fuzzy search interface
|
|
|
|
input textinput.Model // Fuzzy search interface
|
|
|
|
|
|
|
|
datasheets []datasheet // All datasheets under cwd
|
|
|
|
datasheetsView []string // Filtered view on all datasheets
|
|
|
|
datasheetViewport viewport.Model // Viewport for the PDF content
|
|
|
|
} |
|
|
|
datasheetNames []string // All datasheet names (caching)
|
|
|
|
filteredDatasheets []string // Filtered view on all datasheets
|
|
|
|
|
|
|
|
// datasheetNames lists all datasheet names.
|
|
|
|
func (m model) datasheetNames() []string { |
|
|
|
// TODO: cache this somewhere, it's called several times... in the model?
|
|
|
|
var names []string |
|
|
|
for _, datasheet := range m.datasheets { |
|
|
|
names = append(names, datasheet.filename) |
|
|
|
} |
|
|
|
return names |
|
|
|
datasheetViewport viewport.Model // Viewport for the PDF content
|
|
|
|
} |
|
|
|
|
|
|
|
// datasheetFromName retrieves a datasheet via a name.
|
|
|
@ -98,7 +91,9 @@ func initialModel() model { |
|
|
|
input := textinput.New() |
|
|
|
input.Focus() |
|
|
|
|
|
|
|
var ds []datasheet |
|
|
|
var datasheets []datasheet |
|
|
|
var datasheetNames []string |
|
|
|
|
|
|
|
// TODO: handle error in interface?
|
|
|
|
_ = filepath.Walk(".", func(path string, info os.FileInfo, err error) error { |
|
|
|
if err != nil { |
|
|
@ -112,12 +107,15 @@ func initialModel() model { |
|
|
|
// we could run this in a goroutine somewhere
|
|
|
|
// this currently slows down startup time
|
|
|
|
contents, _ := readPDF(path) |
|
|
|
d := datasheet{ |
|
|
|
|
|
|
|
datasheet := datasheet{ |
|
|
|
filename: name, |
|
|
|
absPath: path, |
|
|
|
contents: contents, |
|
|
|
} |
|
|
|
ds = append(ds, d) |
|
|
|
|
|
|
|
datasheets = append(datasheets, datasheet) |
|
|
|
datasheetNames = append(datasheetNames, name) |
|
|
|
} |
|
|
|
|
|
|
|
return nil |
|
|
@ -125,14 +123,16 @@ func initialModel() model { |
|
|
|
|
|
|
|
// TODO: set width/heigh to match terminal
|
|
|
|
viewp := viewport.New(60, 30) |
|
|
|
viewp.SetContent(ds[len(ds)-1].contents) |
|
|
|
selectedDatasheet := datasheets[len(datasheets)-1].contents |
|
|
|
viewp.SetContent(selectedDatasheet) |
|
|
|
|
|
|
|
m := model{ |
|
|
|
filterInput: input, |
|
|
|
datasheets: ds, |
|
|
|
input: input, |
|
|
|
datasheets: datasheets, |
|
|
|
datasheetNames: datasheetNames, |
|
|
|
filteredDatasheets: datasheetNames, |
|
|
|
datasheetViewport: viewp, |
|
|
|
} |
|
|
|
m.datasheetsView = m.datasheetNames() |
|
|
|
|
|
|
|
return m |
|
|
|
} |
|
|
@ -149,29 +149,29 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { |
|
|
|
cmds []tea.Cmd |
|
|
|
) |
|
|
|
|
|
|
|
if m.filterInput.Focused() { |
|
|
|
var matched []string |
|
|
|
if m.input.Focused() { |
|
|
|
var matchedDatasheets []string |
|
|
|
|
|
|
|
search := m.filterInput.Value() |
|
|
|
search := m.input.Value() |
|
|
|
if len(search) >= minCharsUntilFilter { |
|
|
|
matches := fuzzy.Find(search, m.datasheetNames()) |
|
|
|
matches := fuzzy.Find(search, m.datasheetNames) |
|
|
|
for _, match := range matches { |
|
|
|
matched = append(matched, match.Str) |
|
|
|
matchedDatasheets = append(matchedDatasheets, match.Str) |
|
|
|
} |
|
|
|
|
|
|
|
if len(matches) > 0 { |
|
|
|
m.datasheetsView = matched |
|
|
|
m.filteredDatasheets = matchedDatasheets |
|
|
|
} else { |
|
|
|
m.datasheetsView = m.datasheetNames() |
|
|
|
m.filteredDatasheets = m.datasheetNames |
|
|
|
} |
|
|
|
} else { |
|
|
|
m.datasheetsView = m.datasheetNames() |
|
|
|
m.filteredDatasheets = m.datasheetNames |
|
|
|
} |
|
|
|
|
|
|
|
// TODO: implement cursor for scrolling up/down filtered
|
|
|
|
// results so we can view the PDF contents as desired
|
|
|
|
// it's currently just the last one (closest to input)
|
|
|
|
lastdatasheet := m.datasheetsView[len(m.datasheetsView)-1] |
|
|
|
lastdatasheet := m.filteredDatasheets[len(m.filteredDatasheets)-1] |
|
|
|
viewportText := m.datasheetFromName(lastdatasheet) |
|
|
|
m.datasheetViewport.SetContent(viewportText) |
|
|
|
} |
|
|
@ -185,7 +185,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
m.filterInput, cmd = m.filterInput.Update(msg) |
|
|
|
m.input, cmd = m.input.Update(msg) |
|
|
|
cmds = append(cmds, cmd) |
|
|
|
|
|
|
|
m.datasheetViewport, cmd = m.datasheetViewport.Update(msg) |
|
|
@ -199,14 +199,14 @@ func (m model) View() string { |
|
|
|
body := strings.Builder{} |
|
|
|
|
|
|
|
// TODO: paginate / trim view to last 10 or something?
|
|
|
|
sheets := strings.Join(m.datasheetsView, "\n") |
|
|
|
sheets := strings.Join(m.filteredDatasheets, "\n") |
|
|
|
|
|
|
|
// TODO: style further with lipgloss, e.g. borders, margins, etc.
|
|
|
|
panes := lipgloss.JoinHorizontal(lipgloss.Left, sheets, m.datasheetViewport.View()) |
|
|
|
|
|
|
|
body.WriteString(panes) |
|
|
|
|
|
|
|
body.WriteString("\n" + m.filterInput.View()) |
|
|
|
body.WriteString("\n" + m.input.View()) |
|
|
|
|
|
|
|
return body.String() |
|
|
|
} |
|
|
|