Implement file filters via dbus

This commit is contained in:
Kovid Goyal
2025-07-06 12:17:09 +05:30
parent 0a9d83e11b
commit ebe9842291
3 changed files with 76 additions and 8 deletions

View File

@@ -471,6 +471,7 @@ func (h *Handler) set_state_from_config(_ *Config, opts *Options) (err error) {
h.state.filter_map = nil
h.state.current_filter = ""
if len(opts.FileFilter) > 0 {
opts.FileFilter = utils.Uniq(opts.FileFilter)
has_all_files := false
fmap := make(map[string][]Filter)
seen := utils.NewSet[string](len(opts.FileFilter))
@@ -509,7 +510,7 @@ func (h *Handler) set_state_from_config(_ *Config, opts *Options) (err error) {
var default_cwd string
func main(_ *cli.Command, opts *Options, args []string) (rc int, err error) {
write_output := func(selections []string, interrupted bool) {
write_output := func(selections []string, interrupted bool, current_filter string) {
payload := make(map[string]any)
if err != nil {
if opts.WriteOutputTo != "" {
@@ -538,6 +539,9 @@ func main(_ *cli.Command, opts *Options, args []string) (rc int, err error) {
if opts.WriteOutputTo != "" {
if opts.OutputFormat == "json" {
payload["paths"] = selections
if current_filter != "" {
payload["current_filter"] = current_filter
}
b, _ := json.MarshalIndent(payload, "", " ")
m = string(b)
}
@@ -603,22 +607,22 @@ func main(_ *cli.Command, opts *Options, args []string) (rc int, err error) {
}
err = lp.Run()
if err != nil {
write_output(nil, false)
write_output(nil, false, "")
return 1, err
}
ds := lp.DeathSignalName()
if ds != "" {
fmt.Println("Killed by signal: ", ds)
lp.KillIfSignalled()
write_output(nil, true)
write_output(nil, true, "")
return 1, nil
}
rc = lp.ExitCode()
switch rc {
case 0:
write_output(handler.state.selections, false)
write_output(handler.state.selections, false, handler.state.current_filter)
default:
write_output(nil, true)
write_output(nil, true, "")
}
return
}

View File

@@ -630,12 +630,51 @@ func (self *Portal) ReadAll(namespaces []string) (ReadAllType, *dbus.Error) {
}
type vmap map[string]dbus.Variant
type Filter_expression struct {
Ftype uint32
Val string
}
type Filter struct {
Name string
Expressions []Filter_expression
}
func (f Filter) Equal(o Filter) bool {
return f.Name == o.Name && slices.Equal(f.Expressions, o.Expressions)
}
type ChooseFilesData struct {
Title string
Mode string
Cwd string
SuggestedSaveFileName, SuggestedSaveFilePath string
Handle dbus.ObjectPath
Filters []Filter
}
func (c *ChooseFilesData) set_filters(options vmap) {
if v, found := options["filters"]; found {
v.Store(&c.Filters)
}
if v, found := options["current_filter"]; found {
var x Filter
if err := v.Store(&x); err == nil {
idx := slices.IndexFunc(c.Filters, func(q Filter) bool { return x.Equal(q) })
if idx > -1 {
c.Filters = slices.Delete(c.Filters, idx, idx+1)
}
c.Filters = slices.Insert(c.Filters, 0, x)
}
}
}
func get_matching_filter(name string, all_filters []Filter) (dbus.Variant, bool) {
for _, x := range all_filters {
if x.Name == name {
return dbus.MakeVariant(x), true
}
}
return dbus.Variant{}, false
}
func var_to_bool_or_false(v dbus.Variant) bool {
@@ -666,9 +705,10 @@ func (self *Portal) Cleanup() {
}
type ChooserResponse struct {
Paths []string `json:"paths"`
Error string `json:"error"`
Interrupted bool `json:"interrupted"`
Paths []string `json:"paths"`
Error string `json:"error"`
Interrupted bool `json:"interrupted"`
Current_filter string `json:"current_filter"`
}
func (self *Portal) run_file_chooser(cfd ChooseFilesData) (response uint32, result_dict vmap) {
@@ -753,6 +793,11 @@ func (self *Portal) run_file_chooser(cfd ChooseFilesData) (response uint32, resu
if cfd.Title != "" {
args = append(args, "--title", cfd.Title)
}
for _, fs := range cfd.Filters {
for _, exp := range fs.Expressions {
args = append(args, "--file-filter", fmt.Sprintf("%s:%s:%s", utils.IfElse(exp.Ftype == 0, "glob", "mime"), exp.Val, fs.Name))
}
}
args = append(args, "--write-pid-to", pid_path)
args = append(args, utils.IfElse(cfd.Cwd == "", "~", cfd.Cwd))
cmd := exec.Command(utils.KittyExe(), args...)
@@ -801,6 +846,11 @@ func (self *Portal) run_file_chooser(cfd ChooseFilesData) (response uint32, resu
return prefix + u.EscapedPath()
}, result.Paths)
result_dict = vmap{"uris": dbus.MakeVariant(uris)}
if result.Current_filter != "" {
if v, found := get_matching_filter(result.Current_filter, cfd.Filters); found {
result_dict["current_filter"] = v
}
}
return
}
@@ -817,6 +867,7 @@ func (options vmap) get_bytearray(name string) string {
func (self *Portal) OpenFile(handle dbus.ObjectPath, app_id string, parent_window string, title string, options vmap) (uint32, vmap, *dbus.Error) {
cfd := ChooseFilesData{Title: title, Cwd: options.get_bytearray("current_folder"), Handle: handle}
cfd.set_filters(options)
dir_only := false
if v, found := options["directory"]; found && var_to_bool_or_false(v) {
dir_only = true
@@ -840,6 +891,7 @@ func (self *Portal) SaveFile(handle dbus.ObjectPath, app_id string, parent_windo
SuggestedSaveFileName: options.get_bytearray("current_name"),
SuggestedSaveFilePath: options.get_bytearray("current_file")}
multiple := false
cfd.set_filters(options)
if v, found := options["multiple"]; found && var_to_bool_or_false(v) {
multiple = true
}

View File

@@ -158,6 +158,18 @@ func StableSort[T any](s []T, cmp func(a, b T) int) []T {
return s
}
func Uniq[T comparable](s []T) []T {
seen := NewSet[T](len(s))
ans := make([]T, 0, len(s))
for _, x := range s {
if !seen.Has(x) {
seen.Add(x)
ans = append(ans, x)
}
}
return ans
}
func sort_with_key[T any, C constraints.Ordered](stable bool, s []T, key func(a T) C) []T {
type t struct {
key C