From a48caa7fe4018cd23628e59b2e31350f44d7861e Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Sat, 1 Jan 2022 23:19:25 +0100 Subject: [PATCH] add fzf selection --- cmd/piwigo-cli/images_tag.go | 46 ++++++++++++++++++++++++++++- internal/piwigo/piwigotools/tags.go | 34 ++++++++++++++++++++- 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/cmd/piwigo-cli/images_tag.go b/cmd/piwigo-cli/images_tag.go index f7faad0..e17afa1 100644 --- a/cmd/piwigo-cli/images_tag.go +++ b/cmd/piwigo-cli/images_tag.go @@ -4,6 +4,8 @@ import ( "fmt" "net/url" "os" + "regexp" + "sort" "strings" "github.com/celogeek/piwigo-cli/internal/piwigo" @@ -12,7 +14,8 @@ import ( ) type ImagesTagCommand struct { - Id int `short:"i" long:"id" description:"image id to tag" required:"true"` + Id int `short:"i" long:"id" description:"image id to tag" required:"true"` + ExcludeTags string `short:"x" long:"exclude" description:"exclude tag from selection"` } func (c *ImagesTagCommand) Execute(args []string) error { @@ -42,6 +45,10 @@ func (c *ImagesTagCommand) Execute(args []string) error { return err } + sort.Slice(tags.Tags, func(i, j int) bool { + return tags.Tags[i].Name < tags.Tags[j].Name + }) + img, err := imgDetails.Preview(25) if err != nil { return err @@ -61,5 +68,42 @@ func (c *ImagesTagCommand) Execute(args []string) error { t.SetOutputMirror(os.Stdout) t.SetStyle(table.StyleLight) t.Render() + + var exclude *regexp.Regexp + if c.ExcludeTags != "" { + exclude = regexp.MustCompile(c.ExcludeTags) + } + + sel, err := tags.Tags.Select(exclude) + if err != nil { + return err + } + + fmt.Println("Selection:") + selIds := make([]string, len(sel)) + for i, s := range sel { + selIds[i] = fmt.Sprint(s.Id) + fmt.Printf(" - %s\n", s.NameWithAgeAt(&imgDetails.DateCreation)) + } + + fmt.Println("") + fmt.Printf("Confirmed (Y/n)? ") + var answer string + fmt.Scanln(&answer) + + switch answer { + case "", "y", "Y": + fmt.Println("Applying changes...") + data := &url.Values{} + data.Set("image_id", fmt.Sprint(c.Id)) + data.Set("multiple_value_mode", "replace") + data.Set("tag_ids", strings.Join(selIds, ",")) + + if err := p.Post("pwg.images.setInfo", data, nil); err != nil { + return err + } + fmt.Println("Done!") + } + return nil } diff --git a/internal/piwigo/piwigotools/tags.go b/internal/piwigo/piwigotools/tags.go index f5e129d..5c047ef 100644 --- a/internal/piwigo/piwigotools/tags.go +++ b/internal/piwigo/piwigotools/tags.go @@ -2,12 +2,17 @@ package piwigotools import ( "fmt" + "os" + "os/exec" + "regexp" + "strconv" + "strings" ) type Tags []*Tag type Tag struct { - Id int `json:"id"` + Id int `json:"id,string"` Name string `json:"name"` LastModified TimeResult `json:"lastmodified"` Birthdate TimeResult `json:"birthdate"` @@ -31,3 +36,30 @@ func (t *Tag) NameWithAgeAt(createdAt *TimeResult) string { } return t.Name } + +func (t Tags) Select(exclude *regexp.Regexp) ([]*Tag, error) { + fzf := "fzf --multi --height=30% --border --layout=reverse -e --bind=esc:clear-query --with-nth 2 --delimiter=\"\t\"" + cmd := exec.Command("sh", "-c", fzf) + cmd.Stderr = os.Stderr + in, _ := cmd.StdinPipe() + go func() { + defer in.Close() + for i, tag := range t { + if exclude != nil && exclude.MatchString(tag.Name) { + continue + } + in.Write([]byte(fmt.Sprintf("%d\t%s\n", i, tag.Name))) + } + }() + out, _ := cmd.Output() + rows := strings.Split(string(out), "\n") + selections := make([]*Tag, 0, len(rows)) + for _, row := range rows { + i, err := strconv.Atoi(strings.Split(row, "\t")[0]) + if err != nil { + continue + } + selections = append(selections, t[i]) + } + return selections, nil +}