package inject import ( "context" "errors" "os/exec" "strings" ) type Runner func(ctx context.Context, name string, args ...string) ([]byte, error) func DefaultRunner(ctx context.Context, name string, args ...string) ([]byte, error) { cmd := exec.CommandContext(ctx, name, args...) return cmd.CombinedOutput() } type XdotoolPaster struct { Run Runner } func NewXdotoolPaster(run Runner) XdotoolPaster { if run == nil { run = DefaultRunner } return XdotoolPaster{Run: run} } func (p XdotoolPaster) Paste(ctx context.Context) error { out, err := p.Run(ctx, "xdotool", "key", "--clearmodifiers", "ctrl+v") if err != nil { return formatRunError(out, err) } return nil } type XdotoolTyper struct { Run Runner } func NewXdotoolTyper(run Runner) XdotoolTyper { if run == nil { run = DefaultRunner } return XdotoolTyper{Run: run} } func (t XdotoolTyper) TypeText(ctx context.Context, text string) error { if strings.TrimSpace(text) == "" { return errors.New("empty transcript") } out, err := t.Run(ctx, "xdotool", "type", "--clearmodifiers", "--delay", "1", text) if err != nil { return formatRunError(out, err) } return nil } func formatRunError(out []byte, err error) error { if len(out) > 0 { return errors.New(strings.TrimSpace(string(out))) } return err }