mirror of
https://codeberg.org/scip/epuppy.git
synced 2025-12-18 13:01:04 +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:
@@ -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
|
||||
|
||||
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
|
||||
|
||||
import (
|
||||
@@ -16,8 +32,10 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
Version string = `v0.0.3`
|
||||
Usage string = `Usage epuppy [options] <epub file>
|
||||
Version string = `v0.0.4`
|
||||
Usage string = `This is epuppy, a terminal ui ebook viewer.
|
||||
|
||||
Usage: epuppy [options] <epub file>
|
||||
|
||||
Options:
|
||||
-D --dark enable dark mode
|
||||
@@ -26,24 +44,26 @@ Options:
|
||||
-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`
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Showversion bool `koanf:"version"` // -v
|
||||
Debug bool `koanf:"debug"` // -d
|
||||
StoreProgress bool `koanf:"store-progress"` // -s
|
||||
Darkmode bool `koanf:"dark"` // -D
|
||||
LineNumbers bool `koanf:"line-numbers"` // -n
|
||||
Dump bool `koanf:"txt"` // -t
|
||||
XML bool `koanf:"xml"` // -x
|
||||
Config string `koanf:"config"` // -c
|
||||
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
|
||||
Showversion bool `koanf:"version"` // -v
|
||||
Debug bool `koanf:"debug"` // -d
|
||||
StoreProgress bool `koanf:"store-progress"` // -s
|
||||
Darkmode bool `koanf:"dark"` // -D
|
||||
LineNumbers bool `koanf:"line-numbers"` // -n
|
||||
Dump bool `koanf:"txt"` // -t
|
||||
XML bool `koanf:"xml"` // -x
|
||||
NoColor bool `koanf:"no-color"` // -n
|
||||
Config string `koanf:"config"` // -c
|
||||
ColorDark ColorSetting `koanf:"colordark"` // comes from config file only
|
||||
ColorLight ColorSetting `koanf:"colorlight"` // comes from config file only
|
||||
ShowHelp bool `koanf:"help"`
|
||||
Colors Colors // generated from user config file or internal defaults, respects dark mode
|
||||
Document string
|
||||
InitialProgress int // lines
|
||||
}
|
||||
@@ -58,7 +78,6 @@ func InitConfig(output io.Writer) (*Config, error) {
|
||||
if err != nil {
|
||||
log.Fatalf("failed to print to output: %s", err)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// 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("txt", "t", false, "dump readable content 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")
|
||||
|
||||
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 {
|
||||
conf.Document = flagset.Args()[0]
|
||||
} else {
|
||||
if !conf.Showversion {
|
||||
if !conf.Showversion && !conf.ShowHelp {
|
||||
flagset.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,6 +162,11 @@ func InitConfig(output io.Writer) (*Config, error) {
|
||||
},
|
||||
conf)
|
||||
|
||||
// disable colors if requested by command line
|
||||
if conf.NoColor {
|
||||
_ = os.Setenv("NO_COLOR", "1")
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// pager setup using bubbletea
|
||||
@@ -46,18 +62,22 @@ type Meta struct {
|
||||
}
|
||||
|
||||
type keyMap struct {
|
||||
Up key.Binding
|
||||
Down key.Binding
|
||||
Left key.Binding
|
||||
Right key.Binding
|
||||
Help key.Binding
|
||||
Quit key.Binding
|
||||
Up key.Binding
|
||||
Down key.Binding
|
||||
Left key.Binding
|
||||
Right key.Binding
|
||||
Help key.Binding
|
||||
Quit key.Binding
|
||||
ToggleUI key.Binding
|
||||
Pad key.Binding
|
||||
}
|
||||
|
||||
func (k keyMap) FullHelp() [][]key.Binding {
|
||||
return [][]key.Binding{
|
||||
{k.Up, k.Down, k.Left, k.Right}, // first column
|
||||
{k.Help, k.Quit}, // second column
|
||||
// every item is one 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{
|
||||
Pad: key.NewBinding(
|
||||
key.WithKeys("__"),
|
||||
key.WithHelp(" ", ""),
|
||||
),
|
||||
Up: key.NewBinding(
|
||||
key.WithKeys("up", "k"),
|
||||
key.WithHelp("↑", "move up"),
|
||||
@@ -75,11 +99,11 @@ var keys = keyMap{
|
||||
key.WithHelp("↓", "move down"),
|
||||
),
|
||||
Left: key.NewBinding(
|
||||
key.WithKeys("left", "h"),
|
||||
key.WithKeys("left"),
|
||||
key.WithHelp("←", "decrease text width"),
|
||||
),
|
||||
Right: key.NewBinding(
|
||||
key.WithKeys("right", "l"),
|
||||
key.WithKeys("right"),
|
||||
key.WithHelp("→", "increase text width"),
|
||||
),
|
||||
Help: key.NewBinding(
|
||||
@@ -90,6 +114,10 @@ var keys = keyMap{
|
||||
key.WithKeys("q", "esc", "ctrl+c"),
|
||||
key.WithHelp("q", "quit"),
|
||||
),
|
||||
ToggleUI: key.NewBinding(
|
||||
key.WithKeys("h"),
|
||||
key.WithHelp("h", "toggle ui"),
|
||||
),
|
||||
}
|
||||
|
||||
type Doc struct {
|
||||
@@ -101,6 +129,7 @@ type Doc struct {
|
||||
lastwidth int
|
||||
margin int
|
||||
marginMod bool
|
||||
hideUi bool
|
||||
meta *Meta
|
||||
config *Config
|
||||
|
||||
@@ -135,6 +164,8 @@ func (m Doc) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
m.margin -= MarginStep
|
||||
m.marginMod = true
|
||||
}
|
||||
case key.Matches(msg, m.keys.ToggleUI):
|
||||
m.hideUi = !m.hideUi
|
||||
}
|
||||
|
||||
case tea.WindowSizeMsg:
|
||||
@@ -212,6 +243,10 @@ func (m Doc) View() string {
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -253,7 +288,7 @@ func Pager(conf *Config, title, message string) (int, error) {
|
||||
if conf.LineNumbers {
|
||||
catn := ""
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
import (
|
||||
@@ -27,6 +43,15 @@ func Execute(output io.Writer) int {
|
||||
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 {
|
||||
progress, err := GetProgress(conf)
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
import (
|
||||
|
||||
Reference in New Issue
Block a user