# HG changeset patch # User Sean E. Russell # Date 1633624966 18000 # Thu Oct 07 11:42:46 2021 -0500 # Node ID 504ce1cdd4f166219f64b4c9328da29285da5bf8 # Parent cf31a675b782a4b6aa64e2669797c57343497174 Documentation; add an initial lag before typing, to help with mod-key release; add a (useless) special key type test (useless, because the issue with special keys is in the TypeKey() function, not any quasiauto code); update robotgo to catch my fix merge. diff --git a/README.md b/README.md --- a/README.md +++ b/README.md @@ -41,9 +41,9 @@ There's only one argument: `-ms `, which defines the amount of "lag" between simulated key presses. It is set to default at 50. All other data, it parses from STDIN. -The intended use is as a utility for [kpmenu](https://github.com/AlessioDP/kpmenu). The idea is that you install `quasiauto` and then bind a hotkey to call `[kpmenu](https://github.com/AlessioDP/kpmenu) --autotype`; [kpmenu](https://github.com/AlessioDP/kpmenu) farms out the actual autotyping part to quasiauto. All in all, it would look like this: +The intended use is as a utility for [kpmenu](https://github.com/AlessioDP/kpmenu). The idea is that you install `quasiauto` and then bind a hotkey to call `kpmenu --autotype`; [kpmenu](https://github.com/AlessioDP/kpmenu) farms out the actual autotyping part to quasiauto. All in all, it would look like this: -1. Install [kpmenu](https://github.com/AlessioDP/kpmenu); configure it as your KeePass client. +1. Install [kpmenu](https://github.com/AlessioDP/kpmenu); configure it as your KeePass client. **Until the patch is merged, you need the PR that adds autotype support.** 2. Configure [kpmenu](https://github.com/AlessioDP/kpmenu) to use quasiauto to identify the active window by adding this to `~/.config/kpmenu/config`: ``` [executable] @@ -67,6 +67,33 @@ quasiauto can autotype on behalf of any program that sends it data in the correct format. +On the kpmenu side, there are a few options that can make autotype work better for you: + +``` +--autotypealwaysconfirm Always confirm autotype, even when there's only 1 selection +``` + +This forces kpmenu to *always* ask to start autotype, even if a unique match is made. Without this, autotype can start immediately and -- possibly -- before you've released all of the MOD keys you used to launch autotype, which is less than ideal. I hope to find a way to ensure no keys are pressed before starting autotype, but I don't have a way of doing that right now, so this is a good option to use. + +``` +--autotypeusersel Prompt for autotype entry instead of trying to detect by active window title +``` + +The kpmenu patch runs a program to find the active window. If you want to disable that, and always select the entry yourself, use this option. + +``` +--customAutotypeTyper string Custom executable for autotype typer (default "quasiauto") +``` + +Set this to `quasiauto -ms 100` to change the type delay. + +``` +--customAutotypeWindowID string Custom executable for identifying active window for autotype (default "quasiauto -title") +``` + +quasiauto can identify the active window, but you could also use, e.g. `xdotool getwindowfocus getwindowname`. Set this option to change how window titles are selected. + + Limitations ================ diff --git a/exec.go b/exec.go --- a/exec.go +++ b/exec.go @@ -17,6 +17,9 @@ // Give use time to release the control key var err error metas := regexp.MustCompile("([+^%@]+[a-z~]?)|([^+^%@~]+)|(~)") + lag := time.Duration(s.Keylag) + // Give a little pause before we start doing anything + time.Sleep(lag) for _, seq := range s.SeqEntries { err = nil switch seq.Type { @@ -27,6 +30,7 @@ i := keyMap[seq.Token] if i.isTap { typer.KeyTap(i.val) + time.Sleep(lag) } else { typer.TypeStr(i.val, s.Keylag) } @@ -59,10 +63,12 @@ for _, m := range mods { if str, ok := m.(string); ok { typer.KeyTap(str) + time.Sleep(lag) } } } else if len(mods) == 0 { typer.KeyTap(typing) + time.Sleep(lag) } else { typer.KeyTap(typing, mods...) } diff --git a/exec_test.go b/exec_test.go --- a/exec_test.go +++ b/exec_test.go @@ -10,7 +10,7 @@ func Test_Sequence_Exec(t *testing.T) { parseKeyMap() empty := []int32{} - args := map[string]string{"USERNAME": "user", "PASSWORD": "passw"} + args := map[string]string{"USERNAME": "user", "PASSWORD": "passw", "FIELD2": "=.2#'=<&):[.="} tests := []struct { name string seqEntries SeqEntries @@ -54,6 +54,7 @@ {"Complex raw", []SeqEntry{{"ab^+cdd", nil, RAW}}, []string{"ab", "dd"}, []string{"ctrl", "shift", "c"}, empty}, {"Embedded enter", []SeqEntry{{"ab~cd", nil, RAW}}, []string{"ab", "cd"}, []string{"enter"}, empty}, {"Modified enter", []SeqEntry{{"%~", nil, RAW}}, nil, []string{"alt", "enter"}, empty}, + {"Funny characters", []SeqEntry{{"FIELD2", nil, FIELD}}, []string{"=.2#'=<&):[.="}, nil, empty}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/go.mod b/go.mod --- a/go.mod +++ b/go.mod @@ -4,6 +4,8 @@ require ( github.com/gen2brain/beeep v0.0.0-20210529141713-5586760f0cc1 // indirect - github.com/go-vgo/robotgo v0.99.2 + github.com/go-vgo/robotgo v0.100.0 + github.com/otiai10/curr v1.0.0 // indirect github.com/stretchr/testify v1.7.0 // indirect + gopkg.in/yaml.v2 v2.2.2 // indirect ) diff --git a/go.sum b/go.sum --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:Mid70uvE93zn9wgF92A/r5ixgnvX8Lh68fxp9KQBaI0= github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 h1:5sXbqlSomvdjlRbWyNqkPsJ3Fg+tQZCbgeX1VGljbQY= github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -17,6 +19,8 @@ github.com/go-vgo/robotgo v0.99.1/go.mod h1:0+i2QWRmZtbIF02RwmiGfFj33Judprukd8ls5J6Eajg= github.com/go-vgo/robotgo v0.99.2 h1:5Q1s0EIAb4y76U07Z6xOIKaTP8V37hIx3MW4FZVz2IQ= github.com/go-vgo/robotgo v0.99.2/go.mod h1:0+i2QWRmZtbIF02RwmiGfFj33Judprukd8ls5J6Eajg= +github.com/go-vgo/robotgo v0.100.0 h1:tU03KeKVUfJhqyonxTaM5k28rsQeE0AzqMCplTj7kF0= +github.com/go-vgo/robotgo v0.100.0/go.mod h1:GCjwxRFoUkuekzm02WexYBV0paDLCbrrlKEfxt/CB10= github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c h1:16eHWuMGvCjSfgRJKqIzapE78onvvTbdi1rMkU00lZw= @@ -37,30 +41,45 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/robotn/gohook v0.30.6 h1:hH2KzyRsThtOqQ4M2ZPiOaib4vx70pz1DqgrBm26vPk= github.com/robotn/gohook v0.30.6/go.mod h1:FXryR68cDIho8rjE7MKxt4n4aK2FBqp+d/0HK4oiGP8= +github.com/robotn/gohook v0.31.2 h1:ADIppQ3T0Sd+kaDMb4Vnv6UeSmhNfK0H0HpPWCd8G5I= +github.com/robotn/gohook v0.31.2/go.mod h1:0BQit8783ey63WXFau8TvoaTYfNtsAhqZ0RJaqlYi6E= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7/5AKEIcf1vvnnWAmS0wfnNY= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU= github.com/shirou/gopsutil v3.21.5+incompatible h1:OloQyEerMi7JUrXiNzy8wQ5XN+baemxSl12QgIzt0jc= github.com/shirou/gopsutil v3.21.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v3.21.8+incompatible h1:sh0foI8tMRlCidUJR+KzqWYWxrkuuPIGiO6Vp+KXdCU= +github.com/shirou/gopsutil v3.21.8+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af h1:6yITBqGTE2lEeTPG04SN9W+iWHCRyHqlVYILiSXziwk= github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af/go.mod h1:4F09kP5F+am0jAwlQLddpoMDM+iewkxxt6nxUQ5nq5o= github.com/tklauser/go-sysconf v0.3.6 h1:oc1sJWvKkmvIxhDHeKWvZS4f6AW+YcoguSfRF2/Hmo4= github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= +github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo= +github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ= +github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= github.com/vcaesar/gops v0.20.0 h1:SqP/rzDJh7Dy4/Obrjqv+ZftUig+b46BECj9cQ1mCTw= github.com/vcaesar/gops v0.20.0/go.mod h1:EvpOHW7re4rBSzI1B/Rly0CxfT7C9lLo7Rpgs6IVpF0= +github.com/vcaesar/gops v0.21.2 h1:OwWoJR0zb+AK41TN2adhZUP9lAmaRMzkWwf7Ux5Mx00= +github.com/vcaesar/gops v0.21.2/go.mod h1:BEJGigAc9GORbEegWX9rRon/qwibjDs8p50WYm2KlXw= github.com/vcaesar/imgo v0.12.1 h1:/mmZPL0CQwXtdr73ouoCu8Z9gmfmdgaFYoG0YSZ1gdU= github.com/vcaesar/imgo v0.12.1/go.mod h1:MwS4X0FXkLxshu8jMrHCLEM0S6JOQ6lU3drq5nO9AdE= +github.com/vcaesar/imgo v0.30.0 h1:ODQVX0EFJEh+WkKahCBtE0SqcDCIjl/kjiOplR0Ouh8= +github.com/vcaesar/imgo v0.30.0/go.mod h1:8TGnt5hjaMgwDByvMFIzUDSh5uSea4n1tAbSvnhvA6U= github.com/vcaesar/tt v0.11.0 h1:obQecjgbnAxxC6OYGY6yDvhGRW2PR5wD8Ma2uJH3WGA= github.com/vcaesar/tt v0.11.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= +github.com/vcaesar/tt v0.20.0 h1:9t2Ycb9RNHcP0WgQgIaRKJBB+FrRdejuaL6uWIHuoBA= +github.com/vcaesar/tt v0.20.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= github.com/xxxserxxx/robotgo v0.0.0-20210819184435-3f2f186d5669 h1:gKJL1Ti0ufLgE3rNXB9I9vAnlEfczLZwTvvDwlYFi5U= github.com/xxxserxxx/robotgo v0.0.0-20210819184435-3f2f186d5669/go.mod h1:0+i2QWRmZtbIF02RwmiGfFj33Judprukd8ls5J6Eajg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -68,6 +87,8 @@ golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9 h1:D0iM1dTCbD5Dg1CbuvLC/v/agLc79efSj/L35Q3Vqhs= golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -80,6 +101,10 @@ golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210608053332-aa57babbf139 h1:C+AwYEtBp/VQwoLntUmQ/yx3MS9vmZaKNdw5eOpoQe8= golang.org/x/sys v0.0.0-20210608053332-aa57babbf139/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210925032602-92d5a993a665 h1:QOQNt6vCjMpXE7JSK5VvAzJC1byuN3FgTNSBwf+CJgI= +golang.org/x/sys v0.0.0-20210925032602-92d5a993a665/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -89,3 +114,5 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=