воскресенье, 4 августа 2019 г.

Ещё одна переключалка введённого текста

For english version of this post please click link.

Я знаю про Punto Switcher, X Neural Switcher и некоторые другие подобные им программы для изменения раскладки введённого текста с одной на другую:
Руддщб Цщкдв! → Hello, World! (и/или наоборот, Hello, World! → Руддщб Цщкдв!)


Но в программах, запущенных под Wine, у меня большие проблемы с XNeur, а Punto юзабелен только для Windows и Mac OS. Кроме того, их функциональность для меня излишня, т.к. автоматического переключения мне не требуется (я и в Windows автоматику Punto Switcher'а отключал всегда) как и многого другого, что они предлагают. Несомненно, эти программы предоставляют и другие полезные возможности, но мне достаточно, чтобы при нажатии комбинации клавиш расположенный слева от курсора или выделенный текст изменялся с раскладки, на которой был введён ошибочно на ту, в которой должен был быть введён и чтобы это работало в запущенных через Wine приложениях.

Ну и, руководствуясь советами диванных аналитиков из Интернета, которые практически по любому поводу могут предложить "Нужна программа? Напиши сам!", я в итоге написал скрипт на Python 3, который "переключает" введённый текст.

Скрипт вызывается только в момент, когда вам требуется исправить текст, и производит несколько простых действий:
– вырезает кусок текста (текст слева от курсора до начала строки или, в зависимости от параметров запуска, это либо выделенный текст, либо последнее слово – последовательность символов после ближайшего пробела слева);
– меняет каждый символ вырезанного текста одной раскладки на найденный соответствующий символ другой (пытается определить с какой на какую переключать по первым трём символам);
– вставляет преобразованный текст обратно.

Особенности работы скрипта:
– требуется установленный Python 3 и компоненты для автоматизации работы с системой (имитируются нажатия комбинаций клавиш для вырезания текста в буфер обмена и последующую вставку из него изменённого текста);
– графический интерфейс отсутствует;
– все изменения, связанные с работой скрипта, вносятся непосредственно в него;
– последовательность символов вы можете задать самостоятельно, изменив таким образом языки переключения;
– не найденные в раскладках символы пропускаются;
– в случае смешанного текста символы обеих раскладок будут преобразованы в другие (Руддщб World! → Hello, Цщкдв!)
– никакого постоянного сканирования клавиатурных нажатий не происходит;
– комбинация клавиш для запуска скрипта задаётся вами самостоятельно (используйте различные комбинации для запуска с разными параметрами)

Работа скрипта не проверялась в Windows!
В Ubuntu-подобных дистрибутивах для функционирования может потребоваться установка дополнительных компонентов (не считая самого Python 3). Выяснить это можно, запустив скрипт через команду в терминале. Стоит "установить задержку" чтобы успеть переключиться на окно с текстом перед началом работы скрипта:
sleep 3 && python3 <путь_к_скрипту>
(чтобы не писать вручную весь путь, просто перетащите файл в окно терминала с помощью drag-n-drop; у вас будет столько секунд перед началом его выполнения, сколько указано числом после команды sleep)

Команды для установки дополнительных компонентов через терминал (с привилегиями супер-пользователя):
sudo apt install python3-pip
sudo pip3 install setuptools
sudo pip3 install pyperclip pyautogui xlib
sudo apt install python3-tk python3-dev

Ну и, конечно, текст скрипта вы можете найти ниже. Я размещаю его как open source в надежде, что это облегчит кому-то жизнь и/или работу за компьютером. Сохраните этот текст в файл с расширением "py", стандартным для скриптов на Python, например "Swtchr.py":

#! /usr/bin/python3

"""
# Этот скрипт написан на Python 3.
# Это упрощённый аналог XNeur и PuntoSwitcher, который работает с запущенными в Wine приложениями
#
# Использование: Назначить в системе комбинацию клавиш (типа [Ctrl]+[R_Win]) на скрипт
#                и применять её для ручного переключения введённого в неверной раскладке текста.
#
# Требования: необходим подключённый модуль работы с буфером обмена
#               'pyperclip',
#             а также модули автоматизации работы
#               'pyautogui' и 'xlib'
#
# Михаил Винаков, 2019-06-14
# 2019-08-01: Добавлена возможность запуска с параметрами -lastword и -selected
"""


import pyautogui, time, sys

no_pyperclip = False

clpbrd_strg = ""
layout_01 = "`~@#$%^&" +\
            "qwertyuiop[]QWERTYUIOP{}asdfghjkl;'\\ASDFGHJKL:\"|zxcvbnm,./ZXCVBNM<>?"
layout_02 = "ёЁ\"№;%:?" +\
            "йцукенгшщзхъЙЦУКЕНГШЩЗХЪфывапролджэ\\ФЫВАПРОЛДЖЭ/ячсмитьбю.ЯЧСМИТЬБЮ,"

try:                                    # Пробное импортирование необходимого модуля
    import pyperclip                    # В случае неудачи выполнение скрипта бессмысленно
except ImportError:
    no_pyperclip = True

def computing():
    if no_pyperclip == True:
        print("Требуется модуль работы с буфером обмена: pyperclip")
        quit()
    elif len(layout_01) != len(layout_02):
        print("Наборы символов раскладок (layout_01 и layout_02) не совпадают по длине!")
        quit()
    else:
        workaround()

def workaround():
    pyperclip.copy("")

    time.sleep(.1)
    if len(sys.argv) < 2:
        pyautogui.hotkey("shift", "home")

        time.sleep(.3)
        pyautogui.hotkey("ctrl", "x")
    elif sys.argv[1] == "-selected":
        pyautogui.hotkey("ctrl", "x")
    elif sys.argv[1] == "-lastword":
        pyautogui.hotkey("shift", "ctrl", "left")

        time.sleep(.3)
        pyautogui.hotkey("ctrl", "x")
    else:
        print("Неизвестный параметр запуска:", sys.argv[1])
        quit()
    fixed_text = magic(pyperclip.paste())
    pyperclip.copy(fixed_text)

    time.sleep(.1)
    pyautogui.hotkey("ctrl", "v")

def magic(text):
    if len(text) < 1:
        quit()
    elif len(text) < 3:                 # Сравним каких символов больше
        first_x = 1                     # Для сравнения желательны нечётные числа
    else:
        first_x = 3

    chars_01, chars_02 = 0, 0
    for i in range(first_x):            # Какой раскладки первых символов больше: 01 или 02?
        if text[i] in layout_01:
            chars_01 += 1
        elif text[i] in layout_02:
            chars_02 += 1
    if chars_01 > chars_02:             # Разные последовательности, исходя из полученного
        layout = layout_01 + layout_02 + layout_01
    else:
        layout = layout_02 + layout_01 + layout_02

    new_text = ""
    for c in range(len(text)):          # Пропуск символов, которых "нет в раскладках"
        if not text[c] in layout:
            new_text = new_text + text[c]
        else:
            new_text = new_text + layout[layout.find(text[c])+len(layout_01)]
    return new_text

clpbrd_strg = pyperclip.paste()         # Сохранение текущего содержимого буфера обмена
computing()
pyperclip.copy(clpbrd_strg)             # Восстановление содержимого буфера обмена
clpbrd_strg = ""


Обнаружил, что с приложениями под Wine после выполнения скрипта "залипает" правая клавиша [Ctrl], которую я использую в комбинации для вызова. Проблему удалось решить добавив несколько дополнительных строк в конец скрипта. Они имитируют нажатие и отпускание правой клавиши [Ctrl]:

# Для устранения проблемы с залипанием правого [Ctrl]
pyautogui.keyDown("ctrlright")
time.sleep(.1)
pyautogui.keyUp("ctrlright")


Кроме запуска в обычном режиме, когда изменяется текст слева от курсора и до начала строки (имитация выделения нажатием [Shift] + [Home]), предусмотрена возможность запуска с параметрами:
– "-lastword" – для последнего слов перед курсором
– "-selected" – для заранее выделенного фрагмента текста

6 комментариев:

  1. Всё работает, спасибо огромное!

    ОтветитьУдалить
  2. Спасибо.
    Работает в Linux Mint 20.2 Mate,
    Но не хватает опции для смены выделенного написанного КаПСоМ >> кАпсОм

    ОтветитьУдалить
    Ответы
    1. Это тоже выполнимо. Надо добавить дополнительную обработку и новый ключ запуска, при нахождении которого в параметрах и будет запускаться обработка. Самому мне неактуально, для борьбы со случайными срабатываниями я отключал CapsLock до тех пор, пока не нашёл ему отличное применение – использовать в качестве Compose Key.

      Удалить
  3. Ubuntu 22.04.1 64-bit Gnome 42.4 Wayland
    подтверждаю, скрипт работает, но далеко не во всех приложениях, например в Nautilus и gedit не работает....

    ОтветитьУдалить
    Ответы
    1. Сталкивался с подобным в нескольких приложениях тоже. Но при этом не работало только переключение текста перед курсором. При выделении куска текста и использовании комбинации для переключения выделенного куска, срабатывало. Не уверен, может ли быть дело в использовании Wayland, всё-таки я больше "диванный программист".

      Удалить

Если у вас есть что сказать и/или вы не согласны с изложенным в посте – оставьте комментарий. Регистрации не требуется.

If you think I'm wrong and/or you have to say something – fill free to write comment. No sign up required.