Мой велосипед или о том как я сэкономил свои нервные клетки

от автора

Приветствую хабровчане!

Вот уже пол года как мой основной Desktop работает на Ubuntu, о плюсах и минусах Linux писать не буду, пост не об этом.
Так вот… я к сожалению не владею слепым методом набора текста, да и не было смысла обучаться так как в окнах меня вполне сносно спасала программа PuntoSwitcher которой пользовался около 5-ти лет, однако её аналог Xneur на Ubuntu мягко говоря работал «не очень» и вовсе не работал в Skype.

Некоторое время я мирился с этим, потом пробовал безуспешно написать небольшую программку на Java.

Требования к программе:

  1. Быстрый запуск
  2. Иконка в трее для выхода из приложения и отмены конвертации
  3. Конвертация по глобальной комбинации клавиш

— это тот функционал которым я и пользовался в PuntoSwitcher.

image


И вот буквально этой ночью я решил пойти другим путём и задействовать sh.

Не претендую на универсальность метода, но на Kubuntu 15.10 работает как надо.

Принцип работы:

  1. На ярлык sh скрипта вешается комбинация клавиш
  2. После запуска с помощью xclip получаем выделенный текст
  3. Конвертируем его в противоположную раскладку
  4. Утилитой xdotool вставляем новый текст заместо выделенного
  5. Меняем раскладку на противоположную что бы продолжать набирать текст.

От слов к делу:

 #!/bin/bash   oldtemp=`xclip -o` #скопировали текст temp=`'/home/username/desktop/switch' "$oldtemp"` #конвертируем текст xdotool keydown Shift+Control_L #сменили раскладку sleep 1  xdotool keyup Shift+Control_L xdotool type "$temp" #печатаем новый текст notify-send "$oldtemp -> $temp" -t 2000 #сообщение о том что сменили раскладку (опционально) exit 0 

xdotool keydown / xdotool keyup использовал вместо xdotool key потому как последнее у меня срабатывало через раз.

Теперь про конвертацию текста.
Для этого я решил использовать отдельно программу написанную на с++ которая бы принимала текст, понимала в какую сторону его нужно конвертировать и отдавала бы уже нормальный текст в консоль.

До этого на С++ писать не приходилось, благо функционала у этой утилиты на уровне «Hello world».

Беременным детям со слабой психикой не смотреть

#include <iostream>  using namespace std;  std::string Toreplace(std::string text, std::string s, std::string d){     for(int index=0; index=text.find(s, index), index!=std::string::npos;)    {         text.replace(index, s.length(), d);         index+=d.length();     }     return text; }  int GetCurentLang(std::string str){     int thislang = 0;     const char *cstr = str.c_str();     std::string russtr[66] = {"й","ц","у","к","е","н","г","ш","щ","з","х","ъ","ф","ы","в","а","п","р","о","л","д","ж","э","я","ч","с","м","и","т","ь","б","ю","ё","Й","Ц","У","К","Е","Н","Г","Ш","Щ","З","Х","Ъ","Ф","Ы","В","А","П","Р","О","Л","Д","Ж","Э","Я","Ч","С","М","И","Т","Ь","Б","Ю","Ё"};     std::string engstr[56] =  {"q","w","e","r","t","y","u","i","o","p","[","]","a","s","d","f","g","h","j","k","l","z","x","c","v","b","n","m","<",">","Q","W","E","R","T","Y","U","I","O","P","A","S","D","F","G","H","J","K","L","Z","X","C","V","B","N","M"};     for (int i = 0; i < str.length() && thislang == 0; i++){         for (int a = 0; a < 66; a++){             if (russtr[a].compare(new char (cstr[i])) == true) {                 thislang = 1;             }         }         for (int a = 0; a < 56; a++){             if (engstr[a].compare(new char (cstr[i])) == true) {                 thislang = 2;             }         }     }     return thislang; }  std::string TranslateToRu(std::string str){     std::string translate = str;     std::string replacein[67] = {"q","w","e","r","t","y","u","i","o","p","[","]","a","s","d","f","g","h","j","k","l",";","'","z","x","c","v","b","n","m",",",".","/","Q","W","E","R","T","Y","U","I","O","P","[","]","A","S","D","F","G","H","J","K","L",";","'","Z","X","C","V","B","N","M",",",".","/","&"};     std::string replaceto[67] = {"й","ц","у","к","е","н","г","ш","щ","з","х","ъ","ф","ы","в","а","п","р","о","л","д","ж","э","я","ч","с","м","и","т","ь","б","ю",".","Й","Ц","У","К","Е","Н","Г","Ш","Щ","З","Х","Ъ","Ф","Ы","В","А","П","Р","О","Л","Д","Ж","Э","Я","Ч","С","М","И","Т","Ь","Б","Ю",".","?"};     for (int i = 0; i < 67; i++){         translate = Toreplace(translate, replacein[i], replaceto[i]);     }     return translate; }  std::string TranslateToEng(std::string str){     std::string translate = str;     std::string replacein[67] = {"й","ц","у","к","е","н","г","ш","щ","з","х","ъ","ф","ы","в","а","п","р","о","л","д","ж","э","я","ч","с","м","и","т","ь","б","ю",".","Й","Ц","У","К","Е","Н","Г","Ш","Щ","З","Х","Ъ","Ф","Ы","В","А","П","Р","О","Л","Д","Ж","Э","Я","Ч","С","М","И","Т","Ь","Б","Ю",".","?"};     std::string replaceto[67] = {"q","w","e","r","t","y","u","i","o","p","[","]","a","s","d","f","g","h","j","k","l",";","'","z","x","c","v","b","n","m",",",".","/","Q","W","E","R","T","Y","U","I","O","P","[","]","A","S","D","F","G","H","J","K","L",";","'","Z","X","C","V","B","N","M","<",">","/","&"};     for (int i = 0; i < 67; i++){         translate = Toreplace(translate, replacein[i], replaceto[i]);     }     return translate; }     int main(int argc, char *argv[]) {     std::string translate;     int currentlang = GetCurentLang(argv[1]);     if (currentlang == 2){         translate = TranslateToRu(argv[1]);     }else if (currentlang == 1){         translate = TranslateToEng(argv[1]);     }else{         translate = "";     }       cout << translate << endl;     return 0; } 

GetCurentLang Принимает весь текст целиком и ищет первый символ в русской или английской раскладке, если первый встретившийся нам символ в английской раскладке то значит нужно всё переводить в русскую (символы разумеется игнорируем)

TranslateToEng, TranslateToRu массив с буквами для каждого направления свой что бы в дальнейшем настроить замену более гибко.

почему std::string а не char[] — как я уже говорил с С++ не знаком, а в char[] кириллица не умещается… (или что-то вроде этого)

Пока конвертация идёт в одну сторону, т.е если написать:
Бвшм шв=ЭьфштЭЮdjnБ.вшмЮ

на выходе получим:

<div id='main'>djn</div> 

целесообразно было бы «djn» конвертировать тоже, но тогда встанет вопрос с неправильным определением символов ",. /" и т.д
помимо этого текст выделенный через Ctrl+A в xclip не попадает, наверное вместо этого нужно использовать:

xdotool keyup Control_L+С 

ссылка на оригинал статьи https://habrahabr.ru/post/279499/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *