Add dump feature, enhance code quality (#1)

This commit is contained in:
T.v.Dein
2025-10-16 12:24:47 +02:00
committed by GitHub
parent d9ed4dee10
commit 6099806e22
10 changed files with 125 additions and 423 deletions

View File

@@ -21,13 +21,13 @@ const (
Options:
-D --dark enable dark mode
-s --store-progress store and use previous (experimental)
-s --store-progress remember reading position
-n --line-numbers add line numbers
-c --config <file> use config <file>
-t --txt dump readable content to STDOUT
-d --debug enable debugging
-h --help show help message
-v --version show program version
`
-v --version show program version`
)
type Config struct {
@@ -36,6 +36,7 @@ type Config struct {
StoreProgress bool `koanf:"store-progress"` // -s
Darkmode bool `koanf:"dark"` // -D
LineNumbers bool `koanf:"line-numbers"` // -n
Dump bool `koanf:"txt"` // -t
Config string `koanf:"config"` // -c
ColorDark ColorSetting `koanf:"colordark"` // comes from config file only
ColorLight ColorSetting `koanf:"colorlight"` // comes from config file only
@@ -64,6 +65,7 @@ func InitConfig(output io.Writer) (*Config, error) {
flagset.BoolP("dark", "D", false, "enable dark mode")
flagset.BoolP("store-progress", "s", false, "store reading progress")
flagset.BoolP("line-numbers", "n", false, "add line numbers")
flagset.BoolP("txt", "t", false, "dump readable content to STDOUT")
flagset.StringP("config", "c", "", "read config from file")
if err := flagset.Parse(os.Args[1:]); err != nil {

View File

@@ -43,7 +43,6 @@ type Meta struct {
lines int
currentline int
initialprogress int
document string
}
type keyMap struct {
@@ -152,9 +151,7 @@ func (m Doc) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.viewport = viewport.New(msg.Width, msg.Height-verticalMarginHeight)
m.viewport.YPosition = headerHeight
m.viewport.SetContent(wordwrap.String(m.content, m.initialwidth))
m.viewport.ScrollDown(m.meta.initialprogress)
m.Rewrap()
m.ready = true
} else {
m.viewport.Width = msg.Width
@@ -171,15 +168,35 @@ func (m Doc) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, tea.Batch(cmds...)
}
// re-calculate word wrapping, also add left margin
// re-calculate word wrapping, add left margin, recalculate line count
func (m *Doc) Rewrap() {
var content string
// width has changed, either because the terminal size changed or
// because the user added some margin
if m.lastwidth != m.viewport.Width || m.marginMod {
m.viewport.SetContent(wordwrap.String(m.content, m.viewport.Width-(m.margin*2)))
content = wordwrap.String(m.content, m.viewport.Width-(m.margin*2))
m.lastwidth = m.viewport.Width
m.marginMod = false
m.viewport.Style = viewstyle.MarginLeft(m.margin)
}
// bootstrapping, initialize with default width
if !m.ready {
content = wordwrap.String(m.content, m.initialwidth)
}
// wrapping has changed, update viewport and line count
if content != "" {
m.viewport.SetContent(content)
m.meta.lines = len(strings.Split(content, "\n"))
}
// during bootstrapping: jump to last remembered position, if any
if !m.ready {
m.viewport.ScrollDown(m.meta.initialprogress)
}
}
func (m Doc) View() string {
@@ -188,8 +205,7 @@ func (m Doc) View() string {
}
// update current line for later saving
// FIXME: doesn't work correctly yet
m.meta.currentline = int(float64(m.viewport.TotalLineCount()) * m.viewport.ScrollPercent())
m.meta.currentline = int(float64(m.meta.lines) * m.viewport.ScrollPercent())
var helpView string
if m.help.ShowAll {
@@ -261,7 +277,7 @@ func Pager(conf *Config, title, message string) (int, error) {
)
if _, err := p.Run(); err != nil {
return 0, fmt.Errorf("could not run pager:", err)
return 0, fmt.Errorf("could not run pager: %w", err)
}
if conf.Debug {

View File

@@ -4,6 +4,7 @@ import (
"bufio"
"errors"
"fmt"
"log"
"os"
"path/filepath"
"regexp"
@@ -21,20 +22,28 @@ func StoreProgress(conf *Config, progress int) error {
cfgpath := conf.GetConfigDir()
if err := Mkdir(cfgpath); err != nil {
return err
return fmt.Errorf("failed to mkdir config path %s: %w", cfgpath, err)
}
filename := filepath.Join(cfgpath, Slug(conf.Document))
fd, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
return fmt.Errorf("failed to open state file %s: %w", filename, err)
}
defer fd.Close()
defer func() {
if err := fd.Close(); err != nil {
log.Fatal(err)
}
}()
_, err = fd.WriteString(fmt.Sprintf("%d\n", progress))
if err := fd.Truncate(0); err != nil {
return fmt.Errorf("failed to truncate state file %s: %w", filename, err)
}
_, err = fmt.Fprintf(fd, "%d\n", progress)
if err != nil {
return err
return fmt.Errorf("failed to write to state file %s: %w", filename, err)
}
return nil
@@ -49,7 +58,11 @@ func GetProgress(conf *Config) (int64, error) {
if err != nil {
return 0, nil // ignore errors and return no progress
}
defer fd.Close()
defer func() {
if err := fd.Close(); err != nil {
log.Fatal(err)
}
}()
scanner := bufio.NewScanner(fd)
var line string

View File

@@ -2,6 +2,7 @@ package cmd
import (
"fmt"
"log"
"os"
"path/filepath"
"strings"
@@ -24,6 +25,10 @@ func ViewText(conf *Config) (int, error) {
return 0, err
}
if conf.Dump {
return fmt.Println(string(data))
}
return Pager(conf, conf.Document, string(data))
}
@@ -32,7 +37,12 @@ func ViewEpub(conf *Config) (int, error) {
if err != nil {
return 0, err
}
defer book.Close()
defer func() {
if err := book.Close(); err != nil {
log.Fatal(err)
}
}()
buf := strings.Builder{}
head := strings.Builder{}
@@ -61,10 +71,22 @@ func ViewEpub(conf *Config) (int, error) {
}
buf.WriteString("\r\n\r\n")
buf.WriteString(conf.Colors.Body.Render(content.Body))
if conf.Dump {
// avoid excess whitespaces when printing to stdout
buf.WriteString(content.Body)
} else {
buf.WriteString(conf.Colors.Body.Render(content.Body))
}
buf.WriteString("\r\n\r\n\r\n\r\n")
chapter++
}
}
if conf.Dump {
return fmt.Println(buf.String())
}
return Pager(conf, head.String(), buf.String())