Files
epuppy/cmd/store.go
T.v.Dein 08f470e0d5 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
2025-10-17 14:10:45 +02:00

111 lines
2.6 KiB
Go

/*
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 (
"bufio"
"errors"
"fmt"
"log"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
)
var (
nonprintable = regexp.MustCompile(`[^a-zA-Z0-9\-\._]+`)
slugify = regexp.MustCompile(`[/\\]`)
suffix = regexp.MustCompile(`\.[a-z]+$`)
)
func StoreProgress(conf *Config, progress int) error {
cfgpath := conf.GetConfigDir()
if err := Mkdir(cfgpath); err != nil {
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 fmt.Errorf("failed to open state file %s: %w", filename, err)
}
defer func() {
if err := fd.Close(); err != nil {
log.Fatal(err)
}
}()
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 fmt.Errorf("failed to write to state file %s: %w", filename, err)
}
return nil
}
func GetProgress(conf *Config) (int64, error) {
cfgpath := conf.GetConfigDir()
filename := filepath.Join(cfgpath, Slug(conf.Document))
fd, err := os.OpenFile(filename, os.O_RDONLY, 0644)
if err != nil {
return 0, nil // ignore errors and return no progress
}
defer func() {
if err := fd.Close(); err != nil {
log.Fatal(err)
}
}()
scanner := bufio.NewScanner(fd)
var line string
for scanner.Scan() {
line = scanner.Text()
break
}
return strconv.ParseInt(strings.TrimSpace(line), 10, 64)
}
func Mkdir(dir string) error {
if _, err := os.Stat(dir); errors.Is(err, os.ErrNotExist) {
err := os.MkdirAll(dir, os.ModePerm)
if err != nil {
return fmt.Errorf("failed to create directory %s: %w", dir, err)
}
}
return nil
}
// FIXME: check https://github.com/gosimple/slug
func Slug(input string) string {
slug := slugify.ReplaceAllString(input, "-")
slug = suffix.ReplaceAllString(slug, "")
return nonprintable.ReplaceAllString(slug, "")
}