mirror of
https://codeberg.org/scip/epuppy.git
synced 2025-12-16 12:01:00 +01:00
Ui features (#6)
* fix #3: added h ui command to toggle ui * fix #4: added -N flag to disable colors * fixed styling of line numbers (-n) * fix #5 add usage section * add pkg/epub module readme * add license terms to all file headers * fixed usage printing * added basic unit tests * run the tests only on linux due to the use of base64 utitlity
This commit is contained in:
22
.github/workflows/ci.yaml
vendored
22
.github/workflows/ci.yaml
vendored
@@ -21,9 +21,29 @@ jobs:
|
|||||||
- name: build
|
- name: build
|
||||||
run: go build
|
run: go build
|
||||||
|
|
||||||
|
test:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
version: [1.24.9]
|
||||||
|
os: [ubuntu-latest]
|
||||||
|
name: Test
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Set up Go ${{ matrix.os }}
|
||||||
|
uses: actions/setup-go@v6
|
||||||
|
with:
|
||||||
|
go-version: '${{ matrix.version }}'
|
||||||
|
id: go
|
||||||
|
|
||||||
|
- name: checkout
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: test
|
||||||
|
run: go test -cover ./...
|
||||||
|
|
||||||
|
|
||||||
golangci:
|
golangci:
|
||||||
name: lint
|
name: Lintercheck
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/setup-go@v6
|
- uses: actions/setup-go@v6
|
||||||
|
|||||||
62
README.md
62
README.md
@@ -27,6 +27,66 @@ long run.
|
|||||||
- Showing the help
|
- Showing the help
|
||||||

|

|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
To read an ebook, just give a filename as argument to `epuppy`.
|
||||||
|
|
||||||
|
Add the option `-s` to store and use a previously stored reading
|
||||||
|
progress.
|
||||||
|
|
||||||
|
Sometimes you may be unhappy with the colors. Depending on your
|
||||||
|
terminal style you can enable dark mode with `-D`, light mode is the
|
||||||
|
default. You can also configure custom colors in a config file in
|
||||||
|
`$HOME/.config/epuppy/confit.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
# color setting for dark mode
|
||||||
|
colordark = {
|
||||||
|
body = "#ffffff",
|
||||||
|
title = "#7cfc00",
|
||||||
|
chapter = "#ffff00"
|
||||||
|
}
|
||||||
|
|
||||||
|
# color setting for light mode
|
||||||
|
colorlight = {
|
||||||
|
body = "#000000",
|
||||||
|
title = "#8470ff",
|
||||||
|
chapter = "#00008b"
|
||||||
|
}
|
||||||
|
|
||||||
|
# always use dark mode
|
||||||
|
dark = true
|
||||||
|
```
|
||||||
|
|
||||||
|
There are also cases where your current terminal just doesn't have the
|
||||||
|
capabilites for this stuff. I stumbled upon such a case during an SSH
|
||||||
|
session from my Android phone to a FreeBSD server. For this you can
|
||||||
|
either just disable colors with `-N` or by setting the environment
|
||||||
|
variable `$NO_COLOR` to 1. Or you can just dump the text of the ebook
|
||||||
|
and pipe it to some pager, e.g.:
|
||||||
|
|
||||||
|
```default
|
||||||
|
epuppy -t someebook.epub | less
|
||||||
|
```
|
||||||
|
|
||||||
|
There are also a couple of debug options etc, all options:
|
||||||
|
|
||||||
|
```default
|
||||||
|
Usage epuppy [options] <epub file>
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-D --dark enable dark mode
|
||||||
|
-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
|
||||||
|
-x --xml dump source xml to STDOUT
|
||||||
|
-N --no-color disable colors (or use $NO_COLOR env var)
|
||||||
|
-d --debug enable debugging
|
||||||
|
-h --help show help message
|
||||||
|
-v --version show program version
|
||||||
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
The tool does not have any dependencies. Just download the binary for
|
The tool does not have any dependencies. Just download the binary for
|
||||||
@@ -83,4 +143,4 @@ version 3.
|
|||||||
|
|
||||||
# Author
|
# Author
|
||||||
|
|
||||||
Copyleft (c) 2024 Thomas von Dein
|
Copyleft (c) 2025 Thomas von Dein
|
||||||
|
|||||||
@@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
Copyright © 2025 Thomas von Dein
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
Copyright © 2025 Thomas von Dein
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -16,8 +32,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Version string = `v0.0.3`
|
Version string = `v0.0.4`
|
||||||
Usage string = `Usage epuppy [options] <epub file>
|
Usage string = `This is epuppy, a terminal ui ebook viewer.
|
||||||
|
|
||||||
|
Usage: epuppy [options] <epub file>
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-D --dark enable dark mode
|
-D --dark enable dark mode
|
||||||
@@ -26,24 +44,26 @@ Options:
|
|||||||
-c --config <file> use config <file>
|
-c --config <file> use config <file>
|
||||||
-t --txt dump readable content to STDOUT
|
-t --txt dump readable content to STDOUT
|
||||||
-x --xml dump source xml to STDOUT
|
-x --xml dump source xml to STDOUT
|
||||||
|
-N --no-color disable colors (or use $NO_COLOR env var)
|
||||||
-d --debug enable debugging
|
-d --debug enable debugging
|
||||||
-h --help show help message
|
-h --help show help message
|
||||||
-v --version show program version`
|
-v --version show program version`
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Showversion bool `koanf:"version"` // -v
|
Showversion bool `koanf:"version"` // -v
|
||||||
Debug bool `koanf:"debug"` // -d
|
Debug bool `koanf:"debug"` // -d
|
||||||
StoreProgress bool `koanf:"store-progress"` // -s
|
StoreProgress bool `koanf:"store-progress"` // -s
|
||||||
Darkmode bool `koanf:"dark"` // -D
|
Darkmode bool `koanf:"dark"` // -D
|
||||||
LineNumbers bool `koanf:"line-numbers"` // -n
|
LineNumbers bool `koanf:"line-numbers"` // -n
|
||||||
Dump bool `koanf:"txt"` // -t
|
Dump bool `koanf:"txt"` // -t
|
||||||
XML bool `koanf:"xml"` // -x
|
XML bool `koanf:"xml"` // -x
|
||||||
Config string `koanf:"config"` // -c
|
NoColor bool `koanf:"no-color"` // -n
|
||||||
ColorDark ColorSetting `koanf:"colordark"` // comes from config file only
|
Config string `koanf:"config"` // -c
|
||||||
ColorLight ColorSetting `koanf:"colorlight"` // comes from config file only
|
ColorDark ColorSetting `koanf:"colordark"` // comes from config file only
|
||||||
|
ColorLight ColorSetting `koanf:"colorlight"` // comes from config file only
|
||||||
Colors Colors // generated from user config file or internal defaults, respects dark mode
|
ShowHelp bool `koanf:"help"`
|
||||||
|
Colors Colors // generated from user config file or internal defaults, respects dark mode
|
||||||
Document string
|
Document string
|
||||||
InitialProgress int // lines
|
InitialProgress int // lines
|
||||||
}
|
}
|
||||||
@@ -58,7 +78,6 @@ func InitConfig(output io.Writer) (*Config, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to print to output: %s", err)
|
log.Fatalf("failed to print to output: %s", err)
|
||||||
}
|
}
|
||||||
os.Exit(0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse commandline flags
|
// parse commandline flags
|
||||||
@@ -69,6 +88,8 @@ func InitConfig(output io.Writer) (*Config, error) {
|
|||||||
flagset.BoolP("line-numbers", "n", false, "add line numbers")
|
flagset.BoolP("line-numbers", "n", false, "add line numbers")
|
||||||
flagset.BoolP("txt", "t", false, "dump readable content to STDOUT")
|
flagset.BoolP("txt", "t", false, "dump readable content to STDOUT")
|
||||||
flagset.BoolP("xml", "x", false, "dump xml to STDOUT")
|
flagset.BoolP("xml", "x", false, "dump xml to STDOUT")
|
||||||
|
flagset.BoolP("no-color", "N", false, "disable colors")
|
||||||
|
flagset.BoolP("help", "h", false, "show help")
|
||||||
flagset.StringP("config", "c", "", "read config from file")
|
flagset.StringP("config", "c", "", "read config from file")
|
||||||
|
|
||||||
if err := flagset.Parse(os.Args[1:]); err != nil {
|
if err := flagset.Parse(os.Args[1:]); err != nil {
|
||||||
@@ -117,8 +138,9 @@ func InitConfig(output io.Writer) (*Config, error) {
|
|||||||
if len(flagset.Args()) > 0 {
|
if len(flagset.Args()) > 0 {
|
||||||
conf.Document = flagset.Args()[0]
|
conf.Document = flagset.Args()[0]
|
||||||
} else {
|
} else {
|
||||||
if !conf.Showversion {
|
if !conf.Showversion && !conf.ShowHelp {
|
||||||
flagset.Usage()
|
flagset.Usage()
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,6 +162,11 @@ func InitConfig(output io.Writer) (*Config, error) {
|
|||||||
},
|
},
|
||||||
conf)
|
conf)
|
||||||
|
|
||||||
|
// disable colors if requested by command line
|
||||||
|
if conf.NoColor {
|
||||||
|
_ = os.Setenv("NO_COLOR", "1")
|
||||||
|
}
|
||||||
|
|
||||||
return conf, nil
|
return conf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
57
cmd/pager.go
57
cmd/pager.go
@@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
Copyright © 2025 Thomas von Dein
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
// pager setup using bubbletea
|
// pager setup using bubbletea
|
||||||
@@ -46,18 +62,22 @@ type Meta struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type keyMap struct {
|
type keyMap struct {
|
||||||
Up key.Binding
|
Up key.Binding
|
||||||
Down key.Binding
|
Down key.Binding
|
||||||
Left key.Binding
|
Left key.Binding
|
||||||
Right key.Binding
|
Right key.Binding
|
||||||
Help key.Binding
|
Help key.Binding
|
||||||
Quit key.Binding
|
Quit key.Binding
|
||||||
|
ToggleUI key.Binding
|
||||||
|
Pad key.Binding
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k keyMap) FullHelp() [][]key.Binding {
|
func (k keyMap) FullHelp() [][]key.Binding {
|
||||||
return [][]key.Binding{
|
return [][]key.Binding{
|
||||||
{k.Up, k.Down, k.Left, k.Right}, // first column
|
// every item is one column
|
||||||
{k.Help, k.Quit}, // second column
|
{k.Up, k.Down, k.Left, k.Right},
|
||||||
|
{k.Pad}, // fake key, we use it as spacing between columns
|
||||||
|
{k.Help, k.Quit, k.ToggleUI},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,6 +86,10 @@ func (k keyMap) ShortHelp() []key.Binding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var keys = keyMap{
|
var keys = keyMap{
|
||||||
|
Pad: key.NewBinding(
|
||||||
|
key.WithKeys("__"),
|
||||||
|
key.WithHelp(" ", ""),
|
||||||
|
),
|
||||||
Up: key.NewBinding(
|
Up: key.NewBinding(
|
||||||
key.WithKeys("up", "k"),
|
key.WithKeys("up", "k"),
|
||||||
key.WithHelp("↑", "move up"),
|
key.WithHelp("↑", "move up"),
|
||||||
@@ -75,11 +99,11 @@ var keys = keyMap{
|
|||||||
key.WithHelp("↓", "move down"),
|
key.WithHelp("↓", "move down"),
|
||||||
),
|
),
|
||||||
Left: key.NewBinding(
|
Left: key.NewBinding(
|
||||||
key.WithKeys("left", "h"),
|
key.WithKeys("left"),
|
||||||
key.WithHelp("←", "decrease text width"),
|
key.WithHelp("←", "decrease text width"),
|
||||||
),
|
),
|
||||||
Right: key.NewBinding(
|
Right: key.NewBinding(
|
||||||
key.WithKeys("right", "l"),
|
key.WithKeys("right"),
|
||||||
key.WithHelp("→", "increase text width"),
|
key.WithHelp("→", "increase text width"),
|
||||||
),
|
),
|
||||||
Help: key.NewBinding(
|
Help: key.NewBinding(
|
||||||
@@ -90,6 +114,10 @@ var keys = keyMap{
|
|||||||
key.WithKeys("q", "esc", "ctrl+c"),
|
key.WithKeys("q", "esc", "ctrl+c"),
|
||||||
key.WithHelp("q", "quit"),
|
key.WithHelp("q", "quit"),
|
||||||
),
|
),
|
||||||
|
ToggleUI: key.NewBinding(
|
||||||
|
key.WithKeys("h"),
|
||||||
|
key.WithHelp("h", "toggle ui"),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
type Doc struct {
|
type Doc struct {
|
||||||
@@ -101,6 +129,7 @@ type Doc struct {
|
|||||||
lastwidth int
|
lastwidth int
|
||||||
margin int
|
margin int
|
||||||
marginMod bool
|
marginMod bool
|
||||||
|
hideUi bool
|
||||||
meta *Meta
|
meta *Meta
|
||||||
config *Config
|
config *Config
|
||||||
|
|
||||||
@@ -135,6 +164,8 @@ func (m Doc) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
m.margin -= MarginStep
|
m.margin -= MarginStep
|
||||||
m.marginMod = true
|
m.marginMod = true
|
||||||
}
|
}
|
||||||
|
case key.Matches(msg, m.keys.ToggleUI):
|
||||||
|
m.hideUi = !m.hideUi
|
||||||
}
|
}
|
||||||
|
|
||||||
case tea.WindowSizeMsg:
|
case tea.WindowSizeMsg:
|
||||||
@@ -212,6 +243,10 @@ func (m Doc) View() string {
|
|||||||
helpView = "\n" + m.help.View(m.keys)
|
helpView = "\n" + m.help.View(m.keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if m.hideUi {
|
||||||
|
return fmt.Sprintf("%s\n%s", m.viewport.View(), helpView)
|
||||||
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%s\n%s\n%s%s", m.headerView(), m.viewport.View(), m.footerView(), helpView)
|
return fmt.Sprintf("%s\n%s\n%s%s", m.headerView(), m.viewport.View(), m.footerView(), helpView)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,7 +288,7 @@ func Pager(conf *Config, title, message string) (int, error) {
|
|||||||
if conf.LineNumbers {
|
if conf.LineNumbers {
|
||||||
catn := ""
|
catn := ""
|
||||||
for idx, line := range strings.Split(message, "\n") {
|
for idx, line := range strings.Split(message, "\n") {
|
||||||
catn += fmt.Sprintf("%d: %s\n", idx, line)
|
catn += fmt.Sprintf("%4d: %s\n", idx, line)
|
||||||
}
|
}
|
||||||
message = catn
|
message = catn
|
||||||
}
|
}
|
||||||
|
|||||||
25
cmd/root.go
25
cmd/root.go
@@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
Copyright © 2025 Thomas von Dein
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -27,6 +43,15 @@ func Execute(output io.Writer) int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if conf.ShowHelp {
|
||||||
|
_, err := fmt.Fprintln(output, Usage)
|
||||||
|
if err != nil {
|
||||||
|
return Die(fmt.Errorf("failed to print to output: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
if conf.StoreProgress {
|
if conf.StoreProgress {
|
||||||
progress, err := GetProgress(conf)
|
progress, err := GetProgress(conf)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|||||||
16
cmd/store.go
16
cmd/store.go
@@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
Copyright © 2025 Thomas von Dein
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
16
cmd/view.go
16
cmd/view.go
@@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
Copyright © 2025 Thomas von Dein
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
4
go.mod
4
go.mod
@@ -48,5 +48,7 @@ require (
|
|||||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||||
golang.org/x/net v0.33.0 // indirect
|
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
||||||
|
golang.org/x/net v0.44.0 // indirect
|
||||||
|
golang.org/x/tools v0.37.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
6
go.sum
6
go.sum
@@ -74,6 +74,8 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
|
|||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
|
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||||
|
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
@@ -104,6 +106,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
|||||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||||
|
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
|
||||||
|
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@@ -154,6 +158,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
|||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||||
|
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
|
||||||
|
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
16
main.go
16
main.go
@@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
Copyright © 2025 Thomas von Dein
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
38
main_test.go
Normal file
38
main_test.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
Copyright © 2025 Thomas von Dein
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rogpeppe/go-internal/testscript"
|
||||||
|
)
|
||||||
|
|
||||||
|
// see https://bitfieldconsulting.com/golang/test-scripts
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
testscript.Main(m, map[string]func(){
|
||||||
|
"epuppy": main,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEpuppy(t *testing.T) {
|
||||||
|
testscript.Run(t, testscript.Params{
|
||||||
|
Dir: "t",
|
||||||
|
})
|
||||||
|
}
|
||||||
2
mkrel.sh
2
mkrel.sh
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Copyright © 2024 Thomas von Dein
|
# Copyright © 2025 Thomas von Dein
|
||||||
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
21
pkg/epub/README.md
Normal file
21
pkg/epub/README.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# epub module
|
||||||
|
|
||||||
|
This is a modified version of the [epub
|
||||||
|
module](https://github.com/kapmahc/epub/). I fixed a couple of issues
|
||||||
|
and I added code to retrieve the actual epub content, which the
|
||||||
|
original module doesn't implement. Since the last update on that
|
||||||
|
module was 9 years ago (as I write this), it doesn't make sense to
|
||||||
|
send a PR. And it also makes no sense to me to publish it separately.
|
||||||
|
|
||||||
|
|
||||||
|
# ORIGINAL README
|
||||||
|
|
||||||
|
## epub
|
||||||
|
A pure go implementation of epub file format.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Documents
|
||||||
|
- <http://idpf.org/epub>
|
||||||
|
- <http://www.cnblogs.com/Alex80/p/5127104.html>
|
||||||
|
- <http://www.cnblogs.com/diligenceday/p/4999315.html>
|
||||||
BIN
pkg/epub/test.epub
Normal file
BIN
pkg/epub/test.epub
Normal file
Binary file not shown.
7
t/basic.txtar
Normal file
7
t/basic.txtar
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# no args shall fail
|
||||||
|
! exec epuppy
|
||||||
|
|
||||||
|
# help
|
||||||
|
exec epuppy -h
|
||||||
|
stdout 'This is epuppy'
|
||||||
|
|
||||||
1698
t/read-parse.txtar
Normal file
1698
t/read-parse.txtar
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user