2024-06-18 18:21:03 -04:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2024-06-20 14:38:00 -04:00
|
|
|
"io/fs"
|
2024-06-18 18:21:03 -04:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"slices"
|
|
|
|
"time"
|
|
|
|
|
2024-07-27 19:37:01 -04:00
|
|
|
"git.burning.moe/celediel/gt/internal/filemode"
|
2024-06-18 18:21:03 -04:00
|
|
|
"git.burning.moe/celediel/gt/internal/files"
|
|
|
|
"git.burning.moe/celediel/gt/internal/filter"
|
2024-07-28 21:06:41 -04:00
|
|
|
"git.burning.moe/celediel/gt/internal/interactive"
|
|
|
|
"git.burning.moe/celediel/gt/internal/interactive/modes"
|
2024-06-18 18:21:03 -04:00
|
|
|
|
|
|
|
"github.com/adrg/xdg"
|
|
|
|
"github.com/charmbracelet/log"
|
|
|
|
"github.com/urfave/cli/v2"
|
|
|
|
"golang.org/x/term"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
appname string = "gt"
|
|
|
|
appdesc string = "xdg trash cli"
|
|
|
|
appversion string = "v0.0.1"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2024-07-16 00:05:21 -04:00
|
|
|
loglvl string
|
|
|
|
f *filter.Filter
|
|
|
|
o, b, a, g, p, m string
|
|
|
|
sm, lg string
|
|
|
|
ung, unp string
|
|
|
|
fo, do, sh, ni bool
|
2024-07-16 14:12:37 -04:00
|
|
|
askconfirm, all bool
|
2024-07-16 00:05:21 -04:00
|
|
|
workdir, ogdir cli.Path
|
|
|
|
recursive bool
|
|
|
|
termwidth int
|
|
|
|
termheight int
|
2024-06-18 18:21:03 -04:00
|
|
|
|
|
|
|
trashDir = filepath.Join(xdg.DataHome, "Trash")
|
|
|
|
|
2024-06-25 00:54:46 -04:00
|
|
|
beforeAll = func(ctx *cli.Context) (err error) {
|
2024-06-18 18:21:03 -04:00
|
|
|
// setup log
|
|
|
|
log.SetReportTimestamp(true)
|
|
|
|
log.SetTimeFormat(time.TimeOnly)
|
|
|
|
if l, e := log.ParseLevel(loglvl); e == nil {
|
|
|
|
log.SetLevel(l)
|
|
|
|
// Some extra info for debug level
|
|
|
|
if log.GetLevel() == log.DebugLevel {
|
|
|
|
log.SetReportCaller(true)
|
|
|
|
}
|
2024-07-28 21:29:55 -04:00
|
|
|
} else {
|
|
|
|
log.Errorf("unknown log level '%s' (possible values: debug, info, warn, error, fatal, default: warn)", loglvl)
|
2024-06-18 18:21:03 -04:00
|
|
|
}
|
|
|
|
|
2024-06-20 14:38:00 -04:00
|
|
|
// read the term height and width for tables
|
2024-06-19 18:55:01 -04:00
|
|
|
w, h, e := term.GetSize(int(os.Stdout.Fd()))
|
2024-06-18 18:21:03 -04:00
|
|
|
if e != nil {
|
|
|
|
w = 80
|
2024-06-19 18:55:01 -04:00
|
|
|
h = 24
|
2024-06-18 18:21:03 -04:00
|
|
|
}
|
|
|
|
termwidth = w
|
2024-06-19 18:55:01 -04:00
|
|
|
termheight = h
|
2024-06-18 18:21:03 -04:00
|
|
|
|
2024-06-20 14:38:00 -04:00
|
|
|
// ensure trash directories exist
|
|
|
|
if _, e := os.Stat(trashDir); os.IsNotExist(e) {
|
|
|
|
if err := os.Mkdir(trashDir, fs.FileMode(0755)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if _, e := os.Stat(filepath.Join(trashDir, "info")); os.IsNotExist(e) {
|
|
|
|
if err := os.Mkdir(filepath.Join(trashDir, "info"), fs.FileMode(0755)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if _, e := os.Stat(filepath.Join(trashDir, "files")); os.IsNotExist(e) {
|
|
|
|
if err := os.Mkdir(filepath.Join(trashDir, "files"), fs.FileMode(0755)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-18 18:21:03 -04:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-06-25 00:54:46 -04:00
|
|
|
// action launches interactive mode if run without args, or trashes files as args
|
|
|
|
action = func(ctx *cli.Context) error {
|
|
|
|
var (
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
|
|
|
|
if f == nil {
|
2024-07-27 19:37:01 -04:00
|
|
|
md, e := filemode.Parse(m)
|
2024-07-16 00:05:21 -04:00
|
|
|
if e != nil {
|
|
|
|
return e
|
|
|
|
}
|
|
|
|
f, err = filter.New(o, b, a, g, p, ung, unp, fo, do, false, sm, lg, md)
|
2024-06-25 00:54:46 -04:00
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(ctx.Args().Slice()) != 0 {
|
2024-07-27 19:42:23 -04:00
|
|
|
// args, so try to trash files
|
2024-06-30 18:04:28 -04:00
|
|
|
var files_to_trash files.Files
|
|
|
|
for _, arg := range ctx.Args().Slice() {
|
2024-07-03 18:05:17 -04:00
|
|
|
file, e := files.NewDisk(arg)
|
2024-06-30 18:04:28 -04:00
|
|
|
if e != nil {
|
|
|
|
log.Fatalf("cannot trash '%s': No such file or directory", arg)
|
|
|
|
}
|
|
|
|
files_to_trash = append(files_to_trash, file)
|
|
|
|
}
|
2024-07-27 19:42:23 -04:00
|
|
|
return files.ConfirmTrash(askconfirm, files_to_trash, trashDir)
|
2024-06-25 00:54:46 -04:00
|
|
|
} else {
|
2024-07-27 19:42:23 -04:00
|
|
|
// no ags, so do interactive mode
|
|
|
|
var (
|
|
|
|
infiles files.Files
|
|
|
|
selected files.Files
|
|
|
|
mode modes.Mode
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
infiles, err = files.FindTrash(trashDir, ogdir, f)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if len(infiles) <= 0 {
|
|
|
|
var msg string
|
|
|
|
if f.Blank() {
|
|
|
|
msg = "trash is empty"
|
|
|
|
} else {
|
|
|
|
msg = "no files to show"
|
|
|
|
}
|
|
|
|
fmt.Println(msg)
|
|
|
|
return nil
|
|
|
|
}
|
2024-07-28 21:06:41 -04:00
|
|
|
selected, mode, err = interactive.Select(infiles, termwidth, termheight, false, false, false, workdir, modes.Interactive)
|
2024-07-27 19:42:23 -04:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
switch mode {
|
|
|
|
case modes.Cleaning:
|
|
|
|
for _, file := range selected {
|
|
|
|
log.Debugf("gonna clean %s", file.Name())
|
|
|
|
}
|
|
|
|
if err := files.ConfirmClean(askconfirm, selected); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
case modes.Restoring:
|
|
|
|
for _, file := range selected {
|
|
|
|
log.Debugf("gonna restore %s", file.Name())
|
|
|
|
}
|
|
|
|
if err := files.ConfirmRestore(askconfirm, selected); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
case modes.Interactive:
|
|
|
|
return nil
|
|
|
|
default:
|
|
|
|
return fmt.Errorf("got bad mode %s", mode)
|
|
|
|
}
|
|
|
|
return nil
|
2024-06-25 00:54:46 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
beforeCommands = func(ctx *cli.Context) (err error) {
|
2024-06-18 18:21:03 -04:00
|
|
|
// setup filter
|
|
|
|
if f == nil {
|
2024-07-27 19:37:01 -04:00
|
|
|
md, e := filemode.Parse(m)
|
2024-07-16 00:05:21 -04:00
|
|
|
if e != nil {
|
|
|
|
return e
|
|
|
|
}
|
|
|
|
f, err = filter.New(o, b, a, g, p, ung, unp, fo, do, false, sm, lg, md, ctx.Args().Slice()...)
|
2024-06-18 18:21:03 -04:00
|
|
|
}
|
|
|
|
log.Debugf("filter: %s", f.String())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-06-25 00:54:46 -04:00
|
|
|
beforeTrash = func(_ *cli.Context) (err error) {
|
2024-06-22 00:52:59 -04:00
|
|
|
if f == nil {
|
2024-07-27 19:37:01 -04:00
|
|
|
md, e := filemode.Parse(m)
|
2024-07-16 00:05:21 -04:00
|
|
|
if e != nil {
|
|
|
|
return e
|
|
|
|
}
|
|
|
|
f, err = filter.New(o, b, a, g, p, ung, unp, fo, do, !sh, sm, lg, md)
|
2024-06-22 00:52:59 -04:00
|
|
|
}
|
|
|
|
log.Debugf("filter: %s", f.String())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-06-18 18:21:03 -04:00
|
|
|
after = func(ctx *cli.Context) error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-06-25 00:54:46 -04:00
|
|
|
doTrash = &cli.Command{
|
2024-06-18 18:21:03 -04:00
|
|
|
Name: "trash",
|
|
|
|
Aliases: []string{"tr"},
|
2024-06-20 00:54:50 -04:00
|
|
|
Usage: "Trash a file or files",
|
2024-06-25 00:54:46 -04:00
|
|
|
Flags: slices.Concat(trashFlags, filterFlags),
|
|
|
|
Before: beforeTrash,
|
2024-06-18 18:21:03 -04:00
|
|
|
Action: func(ctx *cli.Context) error {
|
2024-06-22 00:52:59 -04:00
|
|
|
var files_to_trash files.Files
|
2024-06-28 14:30:23 -04:00
|
|
|
var selectall bool
|
2024-06-22 00:52:59 -04:00
|
|
|
for _, arg := range ctx.Args().Slice() {
|
2024-07-03 18:05:17 -04:00
|
|
|
file, e := files.NewDisk(arg)
|
2024-07-28 22:00:19 -04:00
|
|
|
if e != nil || workdir != "" {
|
2024-06-22 00:52:59 -04:00
|
|
|
log.Debugf("%s wasn't really a file", arg)
|
|
|
|
f.AddFileName(arg)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
files_to_trash = append(files_to_trash, file)
|
2024-06-28 14:30:23 -04:00
|
|
|
selectall = true
|
2024-06-18 18:21:03 -04:00
|
|
|
}
|
2024-06-22 00:52:59 -04:00
|
|
|
|
|
|
|
// if none of the args were files, then process find files based on filter
|
|
|
|
if len(files_to_trash) == 0 {
|
2024-07-03 18:05:17 -04:00
|
|
|
fls, err := files.FindDisk(workdir, recursive, f)
|
2024-06-22 00:52:59 -04:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if len(fls) == 0 {
|
|
|
|
fmt.Println("no files to trash")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
files_to_trash = append(files_to_trash, fls...)
|
2024-06-28 14:30:23 -04:00
|
|
|
selectall = !f.Blank()
|
2024-06-18 18:21:03 -04:00
|
|
|
}
|
|
|
|
|
2024-07-28 21:06:41 -04:00
|
|
|
selected, _, err := interactive.Select(files_to_trash, termwidth, termheight, false, selectall, false, workdir, modes.Trashing)
|
2024-06-19 18:55:01 -04:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(selected) <= 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-07-27 19:42:23 -04:00
|
|
|
return files.ConfirmTrash(askconfirm, selected, trashDir)
|
2024-06-18 18:21:03 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2024-06-25 00:54:46 -04:00
|
|
|
doList = &cli.Command{
|
2024-06-18 18:21:03 -04:00
|
|
|
Name: "list",
|
|
|
|
Aliases: []string{"ls"},
|
2024-06-20 00:54:50 -04:00
|
|
|
Usage: "List trashed files",
|
2024-07-15 18:33:37 -04:00
|
|
|
Flags: slices.Concat(listFlags, alreadyintrashFlags, filterFlags),
|
2024-06-25 00:54:46 -04:00
|
|
|
Before: beforeCommands,
|
2024-06-18 18:21:03 -04:00
|
|
|
Action: func(ctx *cli.Context) error {
|
|
|
|
log.Debugf("searching in directory %s for files", trashDir)
|
|
|
|
|
|
|
|
// look for files
|
2024-07-03 18:05:17 -04:00
|
|
|
fls, err := files.FindTrash(trashDir, ogdir, f)
|
2024-06-18 18:21:03 -04:00
|
|
|
|
|
|
|
var msg string
|
2024-07-03 13:17:08 -04:00
|
|
|
log.Debugf("filter '%s' is blark? %t in %s", f, f.Blank(), ogdir)
|
2024-06-30 19:56:13 -04:00
|
|
|
if f.Blank() && ogdir == "" {
|
2024-06-18 18:21:03 -04:00
|
|
|
msg = "trash is empty"
|
|
|
|
} else {
|
|
|
|
msg = "no files to show"
|
|
|
|
}
|
|
|
|
|
2024-06-19 18:55:01 -04:00
|
|
|
if len(fls) == 0 {
|
2024-06-18 18:21:03 -04:00
|
|
|
fmt.Println(msg)
|
|
|
|
return nil
|
|
|
|
} else if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// display them
|
2024-07-28 21:06:41 -04:00
|
|
|
_, _, err = interactive.Select(fls, termwidth, termheight, true, false, ni, workdir, modes.Listing)
|
2024-06-18 18:21:03 -04:00
|
|
|
|
2024-06-19 18:55:01 -04:00
|
|
|
return err
|
2024-06-18 18:21:03 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2024-06-25 00:54:46 -04:00
|
|
|
doRestore = &cli.Command{
|
2024-06-18 18:21:03 -04:00
|
|
|
Name: "restore",
|
|
|
|
Aliases: []string{"re"},
|
2024-06-20 00:54:50 -04:00
|
|
|
Usage: "Restore a trashed file or files",
|
2024-07-16 14:12:37 -04:00
|
|
|
Flags: slices.Concat(cleanRestoreFlags, alreadyintrashFlags, filterFlags),
|
2024-06-25 00:54:46 -04:00
|
|
|
Before: beforeCommands,
|
2024-06-18 18:21:03 -04:00
|
|
|
Action: func(ctx *cli.Context) error {
|
|
|
|
log.Debugf("searching in directory %s for files", trashDir)
|
|
|
|
|
|
|
|
// look for files
|
2024-07-03 18:05:17 -04:00
|
|
|
fls, err := files.FindTrash(trashDir, ogdir, f)
|
2024-06-19 18:55:01 -04:00
|
|
|
if len(fls) == 0 {
|
2024-06-18 18:21:03 -04:00
|
|
|
fmt.Println("no files to restore")
|
|
|
|
return nil
|
|
|
|
} else if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-07-28 21:06:41 -04:00
|
|
|
selected, _, err := interactive.Select(fls, termwidth, termheight, false, all, all, workdir, modes.Restoring)
|
2024-06-19 18:55:01 -04:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(selected) <= 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-07-27 19:42:23 -04:00
|
|
|
return files.ConfirmRestore(askconfirm || all, selected)
|
2024-06-18 18:21:03 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2024-06-25 00:54:46 -04:00
|
|
|
doClean = &cli.Command{
|
2024-06-18 18:21:03 -04:00
|
|
|
Name: "clean",
|
|
|
|
Aliases: []string{"cl"},
|
2024-06-20 00:54:50 -04:00
|
|
|
Usage: "Clean files from trash",
|
2024-07-16 14:12:37 -04:00
|
|
|
Flags: slices.Concat(cleanRestoreFlags, alreadyintrashFlags, filterFlags),
|
2024-06-25 00:54:46 -04:00
|
|
|
Before: beforeCommands,
|
2024-06-18 18:21:03 -04:00
|
|
|
Action: func(ctx *cli.Context) error {
|
2024-07-03 18:05:17 -04:00
|
|
|
fls, err := files.FindTrash(trashDir, ogdir, f)
|
2024-06-19 18:55:01 -04:00
|
|
|
if len(fls) == 0 {
|
2024-06-18 18:21:03 -04:00
|
|
|
fmt.Println("no files to clean")
|
|
|
|
return nil
|
|
|
|
} else if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-07-28 21:06:41 -04:00
|
|
|
selected, _, err := interactive.Select(fls, termwidth, termheight, false, all, all, workdir, modes.Cleaning)
|
2024-06-19 18:55:01 -04:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(selected) <= 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-07-27 19:42:23 -04:00
|
|
|
return files.ConfirmClean(askconfirm, selected)
|
2024-06-18 18:21:03 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2024-06-25 00:54:46 -04:00
|
|
|
globalFlags = []cli.Flag{
|
2024-06-18 18:21:03 -04:00
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "log",
|
2024-06-20 00:59:04 -04:00
|
|
|
Usage: "log level",
|
2024-06-18 18:21:03 -04:00
|
|
|
Value: "warn",
|
|
|
|
Aliases: []string{"l"},
|
|
|
|
Destination: &loglvl,
|
|
|
|
},
|
2024-06-20 00:51:56 -04:00
|
|
|
&cli.BoolFlag{
|
|
|
|
Name: "confirm",
|
2024-06-20 00:59:04 -04:00
|
|
|
Usage: "ask for confirmation before executing any action",
|
2024-06-20 00:51:56 -04:00
|
|
|
Value: false,
|
|
|
|
Aliases: []string{"c"},
|
|
|
|
DisableDefaultText: true,
|
|
|
|
Destination: &askconfirm,
|
|
|
|
},
|
2024-06-18 18:21:03 -04:00
|
|
|
}
|
|
|
|
|
2024-06-25 00:54:46 -04:00
|
|
|
filterFlags = []cli.Flag{
|
2024-06-18 18:21:03 -04:00
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "match",
|
2024-06-20 00:59:04 -04:00
|
|
|
Usage: "operate on files matching regex `PATTERN`",
|
2024-06-18 18:21:03 -04:00
|
|
|
Aliases: []string{"m"},
|
|
|
|
Destination: &p,
|
|
|
|
},
|
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "glob",
|
2024-06-20 00:59:04 -04:00
|
|
|
Usage: "operate on files matching `GLOB`",
|
2024-06-18 18:21:03 -04:00
|
|
|
Aliases: []string{"g"},
|
|
|
|
Destination: &g,
|
|
|
|
},
|
2024-06-18 18:56:55 -04:00
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "not-match",
|
2024-06-20 00:59:04 -04:00
|
|
|
Usage: "operate on files not matching regex `PATTERN`",
|
2024-06-18 18:56:55 -04:00
|
|
|
Aliases: []string{"M"},
|
|
|
|
Destination: &unp,
|
|
|
|
},
|
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "not-glob",
|
2024-06-20 00:59:04 -04:00
|
|
|
Usage: "operate on files not matching `GLOB`",
|
2024-06-18 18:56:55 -04:00
|
|
|
Aliases: []string{"G"},
|
|
|
|
Destination: &ung,
|
|
|
|
},
|
2024-06-18 18:21:03 -04:00
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "on",
|
2024-06-20 00:59:04 -04:00
|
|
|
Usage: "operate on files modified on `DATE`",
|
2024-07-16 14:12:37 -04:00
|
|
|
Aliases: []string{"O"},
|
2024-06-18 18:21:03 -04:00
|
|
|
Destination: &o,
|
|
|
|
},
|
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "after",
|
2024-06-20 00:59:04 -04:00
|
|
|
Usage: "operate on files modified before `DATE`",
|
2024-07-16 14:12:37 -04:00
|
|
|
Aliases: []string{"A"},
|
2024-06-18 18:21:03 -04:00
|
|
|
Destination: &a,
|
|
|
|
},
|
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "before",
|
2024-06-20 00:59:04 -04:00
|
|
|
Usage: "operate on files modified after `DATE`",
|
2024-07-16 14:12:37 -04:00
|
|
|
Aliases: []string{"B"},
|
2024-06-18 18:21:03 -04:00
|
|
|
Destination: &b,
|
|
|
|
},
|
2024-06-19 22:13:10 -04:00
|
|
|
&cli.BoolFlag{
|
2024-06-20 00:59:04 -04:00
|
|
|
Name: "files-only",
|
|
|
|
Usage: "operate on files only",
|
2024-06-30 18:50:27 -04:00
|
|
|
Aliases: []string{"F"},
|
2024-06-20 00:59:04 -04:00
|
|
|
DisableDefaultText: true,
|
|
|
|
Destination: &fo,
|
2024-06-19 22:13:10 -04:00
|
|
|
},
|
|
|
|
&cli.BoolFlag{
|
2024-06-20 00:59:04 -04:00
|
|
|
Name: "dirs-only",
|
|
|
|
Usage: "operate on directories only",
|
2024-06-30 18:50:27 -04:00
|
|
|
Aliases: []string{"D"},
|
2024-06-20 00:59:04 -04:00
|
|
|
DisableDefaultText: true,
|
|
|
|
Destination: &do,
|
2024-06-19 22:13:10 -04:00
|
|
|
},
|
2024-06-30 21:39:23 -04:00
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "min-size",
|
|
|
|
Usage: "operate on files larger than `SIZE`",
|
|
|
|
Aliases: []string{"N"},
|
|
|
|
Destination: &sm,
|
|
|
|
},
|
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "max-size",
|
|
|
|
Usage: "operate on files smaller than `SIZE`",
|
|
|
|
Aliases: []string{"X"},
|
|
|
|
Destination: &lg,
|
|
|
|
},
|
2024-07-16 00:05:21 -04:00
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "mode",
|
|
|
|
Usage: "operate on files matching mode `MODE`",
|
|
|
|
Aliases: []string{"x"},
|
|
|
|
Destination: &m,
|
|
|
|
},
|
2024-06-18 18:21:03 -04:00
|
|
|
}
|
|
|
|
|
2024-06-25 00:54:46 -04:00
|
|
|
trashFlags = []cli.Flag{
|
2024-06-18 18:21:03 -04:00
|
|
|
&cli.BoolFlag{
|
|
|
|
Name: "recursive",
|
2024-06-20 00:59:04 -04:00
|
|
|
Usage: "operate on files recursively",
|
2024-06-18 18:21:03 -04:00
|
|
|
Aliases: []string{"r"},
|
|
|
|
Destination: &recursive,
|
|
|
|
Value: false,
|
|
|
|
DisableDefaultText: true,
|
|
|
|
},
|
|
|
|
&cli.PathFlag{
|
|
|
|
Name: "work-dir",
|
2024-06-20 00:59:04 -04:00
|
|
|
Usage: "operate on files in this `DIRECTORY`",
|
2024-06-18 18:21:03 -04:00
|
|
|
Aliases: []string{"w"},
|
|
|
|
Destination: &workdir,
|
|
|
|
},
|
2024-06-30 20:48:12 -04:00
|
|
|
&cli.BoolFlag{
|
|
|
|
Name: "hidden",
|
|
|
|
Usage: "operate on hidden files",
|
|
|
|
Aliases: []string{"H"},
|
|
|
|
DisableDefaultText: true,
|
|
|
|
Destination: &sh,
|
|
|
|
},
|
2024-06-18 18:21:03 -04:00
|
|
|
}
|
2024-06-18 20:02:49 -04:00
|
|
|
|
2024-06-25 00:54:46 -04:00
|
|
|
alreadyintrashFlags = []cli.Flag{
|
2024-06-18 20:02:49 -04:00
|
|
|
&cli.PathFlag{
|
|
|
|
Name: "original-path",
|
2024-06-20 00:59:04 -04:00
|
|
|
Usage: "operate on files trashed from this `DIRECTORY`",
|
2024-07-16 14:12:37 -04:00
|
|
|
Aliases: []string{"o"},
|
2024-06-18 20:02:49 -04:00
|
|
|
Destination: &ogdir,
|
|
|
|
},
|
|
|
|
}
|
2024-07-15 18:33:37 -04:00
|
|
|
|
|
|
|
listFlags = []cli.Flag{
|
|
|
|
&cli.BoolFlag{
|
2024-07-16 14:20:49 -04:00
|
|
|
Name: "non-interactive",
|
|
|
|
Usage: "list files and quit",
|
|
|
|
Aliases: []string{"n"},
|
|
|
|
Destination: &ni,
|
|
|
|
DisableDefaultText: true,
|
2024-07-15 18:33:37 -04:00
|
|
|
},
|
|
|
|
}
|
2024-07-16 14:12:37 -04:00
|
|
|
|
|
|
|
cleanRestoreFlags = []cli.Flag{
|
|
|
|
&cli.BoolFlag{
|
|
|
|
Name: "all",
|
|
|
|
Usage: "operate on all files in trash",
|
|
|
|
Aliases: []string{"a"},
|
|
|
|
Destination: &all,
|
|
|
|
DisableDefaultText: true,
|
|
|
|
},
|
|
|
|
}
|
2024-06-18 18:21:03 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
app := &cli.App{
|
2024-06-20 01:44:07 -04:00
|
|
|
Name: appname,
|
|
|
|
Usage: appdesc,
|
|
|
|
Version: appversion,
|
2024-06-25 00:54:46 -04:00
|
|
|
Before: beforeAll,
|
2024-06-20 01:44:07 -04:00
|
|
|
After: after,
|
|
|
|
Action: action,
|
2024-06-25 00:54:46 -04:00
|
|
|
Commands: []*cli.Command{doTrash, doList, doRestore, doClean},
|
|
|
|
Flags: globalFlags,
|
2024-06-20 12:30:15 -04:00
|
|
|
EnableBashCompletion: true,
|
2024-06-20 01:44:07 -04:00
|
|
|
UseShortOptionHandling: true,
|
2024-06-18 18:21:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := app.Run(os.Args); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|