본문 바로가기
Computer/Python

파이썬으로 Hotstring 기능 구현하기 1

by 방구석 과학자 2022. 8. 15.

 

 

파이썬으로 'Hotstring' 기능을 구현해보겠습니다. 여기서 Hotstring 기능이란, 예를 들어 'hw'만 입력하고 스페이스를 치면, 'Hello, world!'와 같이 완성된 단어나 문장을 만드는 방법이라고 정의하겠습니다. 하나의 키, 혹은 동시에 두 개 이상의 키를 눌러 특정 기능을 수행하는 'Hotkey' 기능과 차이점을 명확히 하기 위함입니다.

 

기본 코드

from pynput import keyboard

def on_press(key):
    try:
        print('alphanumeric key {0} pressed'.format(
            key.char))
    except AttributeError:
        print('special key {0} pressed'.format(
            key))

def on_release(key):
    print('{0} released'.format(
        key))
    if key == keyboard.Key.esc:
        # Stop listener
        return False

# Collect events until released
with keyboard.Listener(
        on_press=on_press,
        on_release=on_release) as listener:
    listener.join()

# ...or, in a non-blocking fashion:
listener = keyboard.Listener(
    on_press=on_press,
    on_release=on_release)
listener.start()

 

Hotstring 기능을 구현하기 위해 'pynput' 패키지를 사용하겠습니다. 어떤 키보드 키가 입력되었는지 확인할 수 있는 코드입니다. 위 코드는 여기에서 가져왔습니다. 

 

눌린 키 저장하기

일단 print문은 지저분하니 지우고.. 'hw'입력을 저장하기 위한 빈 리스트를 'keys'라고 정의하겠습니다. on_press 함수를 수정해서 키가 눌릴 때마다 그 눌린 키를 keys에 key.char를 append 하겠습니다. keys가 계속 append 되면 크기가 너무 커지니, 일정 크기 이상이면 맨 앞자리를 지우도록 하겠습니다.

벌써부터 분기점이 생기는데 space를 문자로 볼 것인가 입니다. 저는 space를 두 번 이상 쳤을 때도 특정 문자가 나오도록 만들고 싶기 때문에, space도 문자로 보겠습니다. space는 key.char 속성이 없어 AttributeError가 발생하기 때문에 keys.append()를 except 이후에도 만들어줘야 합니다.

keys = [] 

def on_press(key):
    try:
        keys.append(key.char)
        if len(keys) >= 5: # to prevent too many elements in keys
            del keys[0:len(keys)-5]
        print(keys) # for monitoring
    except AttributeError:
        if key == keyboard.Key.space: # space = ' '
            keys.append(' ')
        if len(keys) >= 5: # to prevent too many elements in keys
            del keys[0:len(keys)-5] 
        print(keys) # for monitoring

 

Typer 함수 만들기

컴퓨터 키보드를 직접 쳐주는 함수를 먼저 만들어봅시다. 키보드 조작을 위해 아래와 같이 controller class를 호출하여 my_key instance를 선언해주겠습니다. 문제는 my_key.press('str')를 실행시키면 str을 직접 타이핑할 순 있지만, 단 하나의 글자만 타이핑이 가능합니다. 따라서, 연속된 글자들, 즉 문장을 타이핑하기 위해서 새로운 typer 함수를 만들어보겠습니다.

from pynput import keyboard

my_key = keyboard.Controller() 

# 하나의 글자는 문제가 없지만
my_key = keyboard.Controller() 
my_key.press('H')

# 두 개 이상의 글자는 ValueError 발생
my_key = keyboard.Controller() 
my_key.press('Hello, world!')

 

방법은 단순하게, 입력된 문장을 글자 하나씩 쪼개서 직접 타이핑 하겠습니다.

def typer(sentence):
    for i in range(len(sentence)):
        my_key.press(sentence[i])
    return

typer('Hello, world!')

Helo, world! # 완전히 타이핑이 안된다!

 

결과는 'l' 하나를 타이핑하지 못했습니다. 키보드를 누르기만 해서 이런 결과가 생긴 것이니, 키보드를 떼는 일도 추가해줍시다. (우리는 키보드를 누르고 뗍니다.)

def typer(sentence):
    for i in range(len(sentence)):
        my_key.press(sentence[i])
        my_key.release(sentence[i])
    return

typer('Hello, world!')

Hello, world! # 제대로 출력이 된다!

 

 

Hotstring 함수 만들기

자 이제 keys에 저장된 글자들과 typer 함수를 이용해 hotstring 기능을 구현해봅시다. 

일단 저는 space가 눌렸을 때, 직전에 눌린 키가 'h', 'w' 면 'Hello, world!'를 출력하고 싶습니다. 따라서 특정 글자와 문장을 짝지어주는 함수를 만들어줍니다.

def hotstring(letters, sentence):
    key_word = ''.join(keys[-len(letters):])
    if key_word == letters:
        typer(sentence)
    return

 

 

그리고 'hw '와 'Hello, world!'를 이어주는 함수를 또 하나 만들어줍니다.

def hotstrings():
    hotstring('hw ', 'Hello world!')
    return

 

위 모든 함수들을 소스 코드에 집어넣고 space가 눌렸을 때, hotstrings 함수가 작동되도록 keys에 space가 append 된 직후에 위치시킵니다.

def on_press(key):
    try:
        keys.append(key.char)
        if len(keys) >= 5: # to prevent too many elements in keys
            del keys[0:len(keys)-5]
        print(keys) # for monitoring
    except AttributeError:
        if key == keyboard.Key.space: # space = ' '
            keys.append(' ')
            hotstrings() # hotstrings
        if len(keys) >= 5: # to prevent too many elements in keys
            del keys[0:len(keys)-5] 
        print(keys) # for monitoring

 

위 소스 코드를 작동시킨 후 'hw '를 입력시키면, 'hw Hello world!'가 입력됩니다. 맞습니다. backspace를 빼먹었군요... 키워드의 길이만큼 backspace를 입력하는 함수를 만들어줍시다.

 

Backspace 입력 함수 만들기

아래와 같이 입력된 변수 num만큼 backspace를 입력하는 함수를 만듭니다.

def backspace(num):
    for i in range(num):
        my_key.press(keyboard.Key.backspace)
        my_key.release(keyboard.Key.backspace)
    return

 

위 함수를 hotstring 함수에서 letters의 길이로 입력값을 넣어줍니다.

def hotstring(letters, sentence):
    key_word = ''.join(keys[-len(letters):])
    if key_word == letters:
        backspace(len(letters))
        typer(sentence)
    return

 

완성된 소스 코드

from pynput import keyboard

keys = [] 
my_key = keyboard.Controller() 
    
def typer(sentence):
    for i in range(len(sentence)):
        my_key.press(sentence[i])
        my_key.release(sentence[i])
    return

def backspace(num):
    for i in range(num):
        my_key.press(keyboard.Key.backspace)
        my_key.release(keyboard.Key.backspace)
    return

def hotstring(letters, sentence):
    key_word = ''.join(keys[-len(letters):])
    if key_word == letters:
        backspace(len(letters))
        typer(sentence)
    return

def hotstrings():
    hotstring('hw ', 'Hello world!')
    return

def on_press(key):
    try:
        keys.append(key.char)
        if len(keys) >= 5: # to prevent too many elements in keys
            del keys[0:len(keys)-5]
        print(keys) # for monitoring
    except AttributeError:
        if key == keyboard.Key.space: # space = ' '
            keys.append(' ')
            hotstrings() # hotstrings
        if len(keys) >= 5: # to prevent too many elements in keys
            del keys[0:len(keys)-5] 
        print(keys) # for monitoring

def on_release(key):
    print('{0} released'.format(
        key))
    if key == keyboard.Key.esc:
        # Stop listener
        return False

# Collect events until released
with keyboard.Listener(
        on_press=on_press,
        on_release=on_release) as listener:
    listener.join()

# ...or, in a non-blocking fashion:
listener = keyboard.Listener(
    on_press=on_press,
    on_release=on_release)
listener.start()

자 이제 완성된 소스 코드를 돌리고 'hw '를 입력해보면 'Hello, world!'를 정상적으로 타이핑하는 걸 확인할 수 있습니다. 원하는 문장을 hotstring 함수를 이용해 hotstrings에 추가하여 사용하면 됩니다. 

 

다음은 위 코드를 더 수정하여 좀 더 많은 기능을 추가해보도록 하겠습니다.

반응형

'Computer > Python' 카테고리의 다른 글

정규 표현식 (Regular expression) 1  (1) 2023.12.03
파이썬으로 Hotstring 기능 구현하기 2  (0) 2022.09.03
왜 파이썬인가?  (0) 2022.07.10

댓글