mirror of
https://github.com/gen2brain/cbconvert
synced 2025-10-14 02:28:51 +02:00
Add Cancel, split file
This commit is contained in:
875
cbconvert.go
875
cbconvert.go
File diff suppressed because it is too large
Load Diff
422
cbconvert_arch.go
Normal file
422
cbconvert_arch.go
Normal file
@@ -0,0 +1,422 @@
|
||||
package cbconvert
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"archive/zip"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gen2brain/go-unarr"
|
||||
)
|
||||
|
||||
// archiveSave saves workdir to CBZ archive.
|
||||
func (c *Convertor) archiveSave(fileName string) error {
|
||||
if c.Opts.Archive == "zip" {
|
||||
return c.archiveSaveZip(fileName)
|
||||
} else if c.Opts.Archive == "tar" {
|
||||
return c.archiveSaveTar(fileName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// archiveSaveZip saves workdir to CBZ archive.
|
||||
func (c *Convertor) archiveSaveZip(fileName string) error {
|
||||
if c.OnCompress != nil {
|
||||
c.OnCompress()
|
||||
}
|
||||
|
||||
var zipName string
|
||||
if c.Opts.Recursive {
|
||||
err := os.MkdirAll(filepath.Join(c.Opts.OutDir, filepath.Dir(fileName)), 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||
}
|
||||
|
||||
zipName = filepath.Join(c.Opts.OutDir, filepath.Dir(fileName), fmt.Sprintf("%s%s.cbz", baseNoExt(fileName), c.Opts.Suffix))
|
||||
} else {
|
||||
zipName = filepath.Join(c.Opts.OutDir, fmt.Sprintf("%s%s.cbz", baseNoExt(fileName), c.Opts.Suffix))
|
||||
}
|
||||
|
||||
zipFile, err := os.Create(zipName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||
}
|
||||
|
||||
z := zip.NewWriter(zipFile)
|
||||
|
||||
files, err := os.ReadDir(c.Workdir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
r, err := os.ReadFile(filepath.Join(c.Workdir, file.Name()))
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||
}
|
||||
|
||||
info, err := file.Info()
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||
}
|
||||
|
||||
zipInfo, err := zip.FileInfoHeader(info)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||
}
|
||||
|
||||
zipInfo.Method = zip.Deflate
|
||||
w, err := z.CreateHeader(zipInfo)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||
}
|
||||
|
||||
_, err = w.Write(r)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err = z.Close(); err != nil {
|
||||
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||
}
|
||||
|
||||
if err = zipFile.Close(); err != nil {
|
||||
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||
}
|
||||
|
||||
err = os.RemoveAll(c.Workdir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// archiveSaveTar saves workdir to CBT archive.
|
||||
func (c *Convertor) archiveSaveTar(fileName string) error {
|
||||
if c.OnCompress != nil {
|
||||
c.OnCompress()
|
||||
}
|
||||
|
||||
var tarName string
|
||||
if c.Opts.Recursive {
|
||||
err := os.MkdirAll(filepath.Join(c.Opts.OutDir, filepath.Dir(fileName)), 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||
}
|
||||
|
||||
tarName = filepath.Join(c.Opts.OutDir, filepath.Dir(fileName), fmt.Sprintf("%s%s.cbt", baseNoExt(fileName), c.Opts.Suffix))
|
||||
} else {
|
||||
tarName = filepath.Join(c.Opts.OutDir, fmt.Sprintf("%s%s.cbt", baseNoExt(fileName), c.Opts.Suffix))
|
||||
}
|
||||
|
||||
tarFile, err := os.Create(tarName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||
}
|
||||
|
||||
tw := tar.NewWriter(tarFile)
|
||||
|
||||
files, err := os.ReadDir(c.Workdir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
r, err := os.ReadFile(filepath.Join(c.Workdir, file.Name()))
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||
}
|
||||
|
||||
info, err := file.Info()
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||
}
|
||||
|
||||
header, err := tar.FileInfoHeader(info, info.Name())
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||
}
|
||||
|
||||
err = tw.WriteHeader(header)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||
}
|
||||
|
||||
_, err = tw.Write(r)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err = tw.Close(); err != nil {
|
||||
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||
}
|
||||
|
||||
if err = tarFile.Close(); err != nil {
|
||||
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||
}
|
||||
|
||||
err = os.RemoveAll(c.Workdir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// archiveList lists contents of archive.
|
||||
func (c *Convertor) archiveList(fileName string) ([]string, error) {
|
||||
var contents []string
|
||||
|
||||
archive, err := unarr.NewArchive(fileName)
|
||||
if err != nil {
|
||||
return contents, fmt.Errorf("archiveList: %w", err)
|
||||
}
|
||||
defer archive.Close()
|
||||
|
||||
contents, err = archive.List()
|
||||
if err != nil {
|
||||
return contents, fmt.Errorf("archiveList: %w", err)
|
||||
}
|
||||
|
||||
return contents, nil
|
||||
}
|
||||
|
||||
// archiveComment returns ZIP comment.
|
||||
func (c *Convertor) archiveComment(fileName string) (string, error) {
|
||||
zr, err := zip.OpenReader(fileName)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("archiveComment: %w", err)
|
||||
}
|
||||
defer zr.Close()
|
||||
|
||||
return zr.Comment, nil
|
||||
}
|
||||
|
||||
// archiveSetComment sets ZIP comment.
|
||||
func (c *Convertor) archiveSetComment(fileName, commentBody string) error {
|
||||
zr, err := zip.OpenReader(fileName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSetComment: %w", err)
|
||||
}
|
||||
defer zr.Close()
|
||||
|
||||
zf, err := os.CreateTemp(os.TempDir(), "cbc")
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSetComment: %w", err)
|
||||
}
|
||||
|
||||
tmpName := zf.Name()
|
||||
defer os.Remove(tmpName)
|
||||
|
||||
zw := zip.NewWriter(zf)
|
||||
err = zw.SetComment(commentBody)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSetComment: %w", err)
|
||||
}
|
||||
|
||||
for _, item := range zr.File {
|
||||
ir, err := item.OpenRaw()
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSetComment: %w", err)
|
||||
}
|
||||
|
||||
item := item
|
||||
|
||||
it, err := zw.CreateRaw(&item.FileHeader)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSetComment: %w", err)
|
||||
}
|
||||
|
||||
_, err = io.Copy(it, ir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSetComment: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
err = zw.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSetComment: %w", err)
|
||||
}
|
||||
|
||||
err = zf.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSetComment: %w", err)
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(tmpName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSetComment: %w", err)
|
||||
}
|
||||
|
||||
err = os.WriteFile(fileName, data, 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveSetComment: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// archiveFileAdd adds file to archive.
|
||||
func (c *Convertor) archiveFileAdd(fileName, newFileName string) error {
|
||||
zr, err := zip.OpenReader(fileName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||
}
|
||||
defer zr.Close()
|
||||
|
||||
zf, err := os.CreateTemp(os.TempDir(), "cbc")
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||
}
|
||||
|
||||
tmpName := zf.Name()
|
||||
defer os.Remove(tmpName)
|
||||
|
||||
zw := zip.NewWriter(zf)
|
||||
|
||||
for _, item := range zr.File {
|
||||
if item.Name == newFileName {
|
||||
continue
|
||||
}
|
||||
|
||||
ir, err := item.OpenRaw()
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||
}
|
||||
|
||||
item := item
|
||||
|
||||
it, err := zw.CreateRaw(&item.FileHeader)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||
}
|
||||
|
||||
_, err = io.Copy(it, ir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
info, err := os.Stat(newFileName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||
}
|
||||
|
||||
newData, err := os.ReadFile(newFileName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||
}
|
||||
|
||||
zipInfo, err := zip.FileInfoHeader(info)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||
}
|
||||
|
||||
zipInfo.Method = zip.Deflate
|
||||
w, err := zw.CreateHeader(zipInfo)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||
}
|
||||
|
||||
_, err = w.Write(newData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||
}
|
||||
|
||||
err = zw.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||
}
|
||||
|
||||
err = zf.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(tmpName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||
}
|
||||
|
||||
err = os.WriteFile(fileName, data, 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// archiveFileRemove removes files from archive.
|
||||
func (c *Convertor) archiveFileRemove(fileName, pattern string) error {
|
||||
zr, err := zip.OpenReader(fileName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||
}
|
||||
defer zr.Close()
|
||||
|
||||
zf, err := os.CreateTemp(os.TempDir(), "cbc")
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||
}
|
||||
|
||||
tmpName := zf.Name()
|
||||
defer os.Remove(tmpName)
|
||||
|
||||
zw := zip.NewWriter(zf)
|
||||
|
||||
for _, item := range zr.File {
|
||||
matched, err := filepath.Match(pattern, item.Name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||
}
|
||||
|
||||
if matched {
|
||||
continue
|
||||
}
|
||||
|
||||
ir, err := item.OpenRaw()
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||
}
|
||||
|
||||
item := item
|
||||
|
||||
it, err := zw.CreateRaw(&item.FileHeader)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||
}
|
||||
|
||||
_, err = io.Copy(it, ir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
err = zw.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||
}
|
||||
|
||||
err = zf.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(tmpName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||
}
|
||||
|
||||
err = os.WriteFile(fileName, data, 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
184
cbconvert_func.go
Normal file
184
cbconvert_func.go
Normal file
@@ -0,0 +1,184 @@
|
||||
package cbconvert
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// imageToRGBA converts an image.Image to *image.RGBA.
|
||||
func imageToRGBA(src image.Image) *image.RGBA {
|
||||
if dst, ok := src.(*image.RGBA); ok {
|
||||
return dst
|
||||
}
|
||||
|
||||
b := src.Bounds()
|
||||
dst := image.NewRGBA(b)
|
||||
draw.Draw(dst, dst.Bounds(), src, b.Min, draw.Src)
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// imageToGray converts an image.Image to *image.Gray.
|
||||
func imageToGray(src image.Image) *image.Gray {
|
||||
if dst, ok := src.(*image.Gray); ok {
|
||||
return dst
|
||||
}
|
||||
|
||||
b := src.Bounds()
|
||||
dst := image.NewGray(b)
|
||||
draw.Draw(dst, dst.Bounds(), src, b.Min, draw.Src)
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// imagesFromPath returns list of found image files for given directory.
|
||||
func imagesFromPath(path string) ([]string, error) {
|
||||
var images []string
|
||||
|
||||
walkFiles := func(fp string, f os.FileInfo, err error) error {
|
||||
if !f.IsDir() && f.Mode()&os.ModeType == 0 {
|
||||
if f.Size() > 0 && (isImage(fp)) {
|
||||
images = append(images, fp)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
f, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return images, fmt.Errorf("imagesFromPath: %w", err)
|
||||
}
|
||||
|
||||
stat, err := os.Stat(f)
|
||||
if err != nil {
|
||||
return images, fmt.Errorf("imagesFromPath: %w", err)
|
||||
}
|
||||
|
||||
if !stat.IsDir() && stat.Mode()&os.ModeType == 0 {
|
||||
if isImage(f) {
|
||||
images = append(images, f)
|
||||
}
|
||||
} else {
|
||||
err = filepath.Walk(f, walkFiles)
|
||||
if err != nil {
|
||||
return images, fmt.Errorf("imagesFromPath: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return images, nil
|
||||
}
|
||||
|
||||
// imagesFromSlice returns list of found image files for given slice of files.
|
||||
func imagesFromSlice(files []string) []string {
|
||||
var images []string
|
||||
|
||||
for _, f := range files {
|
||||
if isImage(f) {
|
||||
images = append(images, f)
|
||||
}
|
||||
}
|
||||
|
||||
return images
|
||||
}
|
||||
|
||||
// isArchive checks if file is archive.
|
||||
func isArchive(f string) bool {
|
||||
var types = []string{".rar", ".zip", ".7z", ".tar", ".cbr", ".cbz", ".cb7", ".cbt"}
|
||||
for _, t := range types {
|
||||
if strings.ToLower(filepath.Ext(f)) == t {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// isDocument checks if file is document.
|
||||
func isDocument(f string) bool {
|
||||
var types = []string{".pdf", ".xps", ".epub", ".mobi"}
|
||||
for _, t := range types {
|
||||
if strings.ToLower(filepath.Ext(f)) == t {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// isImage checks if file is image.
|
||||
func isImage(f string) bool {
|
||||
var types = []string{".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff", ".tif", ".webp", ".avif", ".jxl"}
|
||||
for _, t := range types {
|
||||
if strings.ToLower(filepath.Ext(f)) == t {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// isNonImage checks for allowed files in archive.
|
||||
func isNonImage(f string) bool {
|
||||
var types = []string{".nfo", ".xml", ".txt"}
|
||||
for _, t := range types {
|
||||
if strings.ToLower(filepath.Ext(f)) == t {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// isSize checks size of file.
|
||||
func isSize(a, b int64) bool {
|
||||
if a > 0 {
|
||||
if b < int64(a)*(1024*1024) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// isGrayScale checks if image is grayscale.
|
||||
func isGrayScale(img image.Image) bool {
|
||||
model := img.ColorModel()
|
||||
if model == color.GrayModel || model == color.Gray16Model {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// baseNoExt returns base name without extension.
|
||||
func baseNoExt(filename string) string {
|
||||
return strings.TrimSuffix(filepath.Base(filename), filepath.Ext(filename))
|
||||
}
|
||||
|
||||
// copyFile copies reader to file.
|
||||
func copyFile(reader io.Reader, filename string) error {
|
||||
err := os.MkdirAll(filepath.Dir(filename), 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("copyFile: %w", err)
|
||||
}
|
||||
|
||||
file, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return fmt.Errorf("copyFile: %w", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
_, err = io.Copy(file, reader)
|
||||
if err != nil {
|
||||
return fmt.Errorf("copyFile: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@@ -58,7 +58,6 @@ func main() {
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||
go func() {
|
||||
for range c {
|
||||
fmt.Println("\naborting")
|
||||
if err := os.RemoveAll(conv.Workdir); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
@@ -114,7 +113,7 @@ func main() {
|
||||
|
||||
conv.OnCompress = func() {
|
||||
if !opts.Quiet {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Compressing %d of %d...\r", conv.CurrFile, conv.Nfiles)
|
||||
fmt.Fprintf(os.Stderr, "Compressing %d of %d...\r", conv.CurrFile, conv.Nfiles)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +155,7 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\r")
|
||||
fmt.Fprintf(os.Stderr, "\r")
|
||||
}
|
||||
|
||||
// parseFlags parses command line flags.
|
||||
@@ -228,34 +227,34 @@ func parseFlags() (cbconvert.Options, []string) {
|
||||
flag.NewFlagSet("version", flag.ExitOnError)
|
||||
|
||||
flag.Usage = func() {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Usage: %s <command> [<flags>] [file1 dir1 ... fileOrDirN]\n\n", filepath.Base(os.Args[0]))
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\nCommands:\n")
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\n convert\n \tConvert archive or document\n\n")
|
||||
fmt.Fprintf(os.Stderr, "Usage: %s <command> [<flags>] [file1 dir1 ... fileOrDirN]\n\n", filepath.Base(os.Args[0]))
|
||||
fmt.Fprintf(os.Stderr, "\nCommands:\n")
|
||||
fmt.Fprintf(os.Stderr, "\n convert\n \tConvert archive or document\n\n")
|
||||
convert.VisitAll(func(f *flag.Flag) {
|
||||
_, _ = fmt.Fprintf(os.Stderr, " --%s\n \t", f.Name)
|
||||
_, _ = fmt.Fprintf(os.Stderr, "%v (default %q)\n", f.Usage, f.DefValue)
|
||||
fmt.Fprintf(os.Stderr, " --%s\n \t", f.Name)
|
||||
fmt.Fprintf(os.Stderr, "%v (default %q)\n", f.Usage, f.DefValue)
|
||||
})
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\n cover\n \tExtract cover\n\n")
|
||||
fmt.Fprintf(os.Stderr, "\n cover\n \tExtract cover\n\n")
|
||||
cover.VisitAll(func(f *flag.Flag) {
|
||||
_, _ = fmt.Fprintf(os.Stderr, " --%s\n \t", f.Name)
|
||||
_, _ = fmt.Fprintf(os.Stderr, "%v (default %q)\n", f.Usage, f.DefValue)
|
||||
fmt.Fprintf(os.Stderr, " --%s\n \t", f.Name)
|
||||
fmt.Fprintf(os.Stderr, "%v (default %q)\n", f.Usage, f.DefValue)
|
||||
})
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\n thumbnail\n \tExtract cover thumbnail (freedesktop spec.)\n\n")
|
||||
fmt.Fprintf(os.Stderr, "\n thumbnail\n \tExtract cover thumbnail (freedesktop spec.)\n\n")
|
||||
thumbnail.VisitAll(func(f *flag.Flag) {
|
||||
_, _ = fmt.Fprintf(os.Stderr, " --%s\n \t", f.Name)
|
||||
_, _ = fmt.Fprintf(os.Stderr, "%v (default %q)\n", f.Usage, f.DefValue)
|
||||
fmt.Fprintf(os.Stderr, " --%s\n \t", f.Name)
|
||||
fmt.Fprintf(os.Stderr, "%v (default %q)\n", f.Usage, f.DefValue)
|
||||
})
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\n meta\n \tCBZ metadata\n\n")
|
||||
fmt.Fprintf(os.Stderr, "\n meta\n \tCBZ metadata\n\n")
|
||||
meta.VisitAll(func(f *flag.Flag) {
|
||||
_, _ = fmt.Fprintf(os.Stderr, " --%s\n \t", f.Name)
|
||||
_, _ = fmt.Fprintf(os.Stderr, "%v (default %q)\n", f.Usage, f.DefValue)
|
||||
fmt.Fprintf(os.Stderr, " --%s\n \t", f.Name)
|
||||
fmt.Fprintf(os.Stderr, "%v (default %q)\n", f.Usage, f.DefValue)
|
||||
})
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\n version\n \tPrint version\n\n")
|
||||
fmt.Fprintf(os.Stderr, "\n version\n \tPrint version\n\n")
|
||||
}
|
||||
|
||||
if len(os.Args) < 2 {
|
||||
flag.Usage()
|
||||
_, _ = fmt.Fprintf(os.Stderr, "no command\n")
|
||||
fmt.Fprintf(os.Stderr, "no command\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user