package main import ( "bytes" "context" "io/ioutil" "log" "os" "os/signal" "path/filepath" "regexp" "syscall" "github.com/hanwen/go-fuse/v2/fs" "github.com/hanwen/go-fuse/v2/fuse" ) type ddf struct { Path string fs.Inode } func (r *ddf) OnAdd(ctx context.Context) { files, err := ioutil.ReadDir(r.Path) if err != nil { log.Fatal(err) } for _, file := range files { b, err := ioutil.ReadFile(filepath.Join(r.Path, file.Name())) if err != nil { log.Fatal(err) } b = bytes.ReplaceAll(b, []byte("Actions="), []byte("Actions=appvm;")) raw := string(regexp.MustCompile("Exec=[a-zA-Z0-9]*").Find(b)) var app string if len(raw) > 5 { app = string(raw)[5:] } else { log.Println("Can't find Exec entry for", file.Name()) continue } b = append(b, []byte("\n[Desktop Action appvm]\n")...) b = append(b, []byte("Name=Open in appvm\n")...) b = append(b, []byte("Exec=appvm start "+app+"\n")...) ch := r.NewPersistentInode( ctx, &fs.MemRegularFile{ Data: b, Attr: fuse.Attr{Mode: 0444}, }, fs.StableAttr{}) r.AddChild(file.Name(), ch, false) } } var _ = (fs.NodeOnAdder)((*ddf)(nil)) func setupSigintHandler(server *fuse.Server) { c := make(chan os.Signal) signal.Notify(c, os.Interrupt, syscall.SIGTERM) go func() { <-c server.Unmount() os.Exit(1) }() } func main() { const from = "/var/run/current-system/sw/share/applications/" to := filepath.Join(os.Getenv("HOME"), "/.local/share/applications") os.MkdirAll(to, 0755) server, err := fs.Mount(to, &ddf{Path: from}, nil) if err != nil { log.Fatal(err) } setupSigintHandler(server) server.Wait() }