How to highlight text and paste in place with Python keyboard

1k Views Asked by At

I am trying to understand the behavior I am seeing from running my script below and how I can get my desired outcome. Basically I'm using keyboard.add_word_listener() to run a function when the string "test" is typed. It should select the tab trigger key plus the "test" text and then copy it, and then replace it with bbbb and then the copied text.

But if you look at the gif, it doesn't highlight the text. The "bbbb" gets inserted to the left of the "test" text. But it should have replaced the "test" text since it sends ctrl+shift+left which should select the previously entered text. The strange thing is the text still gets copied to the clipboard even though it doesn't look like it got selected. And for some reason it gets pasted in a separate line in the beginning. I don't understand how that is possible. It works on macOS but not Windows.

I also tried replacing ctrl+shift+left,ctrl+shift+left with shift+home but the result is the same.

enter image description here

The script:

import keyboard 
import time

def test():
    keyboard.send("ctrl+shift+left,ctrl+shift+left")
    time.sleep(1)
    keyboard.send("ctrl+c")
    time.sleep(1)
    keyboard.send("b,b,b,b")
    time.sleep(1)
    keyboard.send("ctrl+v")

keyboard.add_word_listener("test",test,['tab'],False,1)

keyboard.wait()
1

There are 1 best solutions below

3
On

I've been scratching my head about why this doesn't work for a while now and I've found a way to make it work.

When you call keyboard.send that method parses the given hotkeys, and tries to send a scan_code for each key that you've specified.

It parses the keys via the keyboard.parse_hotkey method. If we call that method ourselves, we can see what codes we get back:

>>> keyboard.parse_hotkey("ctrl+shift+left")
(((29, 57373), (42, 54), (75,)),)

Here we can see that both ctrl and shift has two codes, each for their right/left counterparts.

As you've discovered as well as me, is if you try to call a hotkey like shift+home the button-combination seems to be working correctly, because your position on the document seems to change. However, it seems like the way (at least on my end) the system handles the calls to shift doesn't work when you call just one of the shift codes.

We can change the hotkey to include both of the codes by calling them individually in the hotkey:

>>> keyboard.parse_hotkey("ctrl+right shift+left shift+left")
(((29, 57373), (54,), (42,), (75,)),)

If we update your code, to include the above hotkey instead, we can see that the expected behavior is happening:

import keyboard
def test():
    keyboard.send("ctrl+right shift+left shift+left")
    keyboard.send("ctrl+c")
    keyboard.send("b,b,b,b")
    keyboard.send("ctrl+v")

keyboard.add_word_listener("test", test, ['tab'], False, 1)
keyboard.wait()

At the time of writing I don't really know exactly why the above code works while your original code doesn't.