Mahou icon indicating copy to clipboard operation
Mahou copied to clipboard

Делать первые буквы предложений прописными и исправлять ДВе ПРописные буквы автоматически

Open yuklov opened this issue 5 years ago • 40 comments

изображение

На MS Word, LibreOffice и других текстовых редакторах есть такие функции.

  1. Делать первые буквы предложений прописными
  2. Исправлять ДВе ПРописные буквы

Но такая функция нету у других программ.

Можно это сделать через сниппеты или добавить их как отдельные функции на программу?

Если добавить эти возможности, программа будет еще комфортнее. И сразу добавить нужно правило-исключение для текстовых редакторов. Там у же есть такая функция и может создать "недоразумение".

yuklov avatar Feb 06 '20 13:02 yuklov

Хм, а ведь это можно с использованием regex-сниппетов сделать:

->regex/^([А-ЯA-Z])([А-ЯA-Z][а-яa-z])([a-zA-ZА-Яа-я]+)(?!.*? )/
====>$1\L$2$3 <====

WEst => West, ЯГода => Ягода, ЗЕленый => Зеленый.

BladeMight avatar Feb 06 '20 19:02 BladeMight

  • Еще можно использовать для этого функцию гор. клавишу "Выделенные слова в заглавный регистр"

BladeMight avatar Feb 06 '20 19:02 BladeMight

Я уже как то писал про это. Но выделить слово, нажать горячую клавишу это не проще чем ткнуть мышкой, стереть букву и написать правильно. Функция имеет смысл только в автоматическом режиме. А то с горячими клавишами программа со временем превратилась в монстра. Достаточно отключение капса, смена раскладки и конвертация всего текста+выделенного текста. Может стоит выпустить лайт-версию?

MishGa avatar Feb 07 '20 08:02 MishGa

Хм, а ведь это можно с использованием regex-сниппетов сделать:

->regex/^([А-ЯA-Z])([А-ЯA-Z][а-яa-z])([a-zA-ZА-Яа-я]+)(?!.*? )/
====>$1\L$2$3 <====

WEst => West, ЯГода => Ягода, ЗЕленый => Зеленый.

А можно делать первые буквы предложений прописными? Писал такой код:

->regex/^([a-zа-яўқғҳ])|(?<=[\.!?]\s)([a-zа-яўқғҳ])/
====>\U$1\U$2<====

Все нормально в коде? В тесте работает, но в сниппетах не работает. Вот: https://regex101.com/r/bYT9dM/3 https://regex101.com/r/bYT9dM/4

yuklov avatar Feb 07 '20 08:02 yuklov

->regex/^([А-ЯA-Z])([А-ЯA-Z][а-яa-z])([a-zA-ZА-Яа-я]+)(?!.*? )/
====>$1\L$2$3 <====

Это не работал с такими словами: КТо, ЧТо. Изменил код:

->regex/^([А-ЯЎҚҒҲA-Z])([А-ЯЎҚҒҲA-Z][а-яўқғҳa-z]+)(?!.*? )/
====>$1\L$2<====

Теперь работает. Нормально?

yuklov avatar Feb 07 '20 09:02 yuklov

А можно делать первые буквы предложений прописными?

Через сниппеты? Но в сниппетах максимум 2 Слова. Так что ^ значит начало слова а не строки в Mahou. Вот такой будет работать:

->regex/(?<=[\.!?]\s)([a-zа-яўқғҳ])/
====>\U$1\E<====

В тесте работает, но в сниппетах не работает.

Из-за | в сниппетах они неправильно инициализировались, сделал исправление в 77260eb

->regex/^([А-ЯЎҚҒҲA-Z])([А-ЯЎҚҒҲA-Z][а-яўқғҳa-z]+)(?!.*? )/ ====>$1\L$2<==== Теперь работает. Нормально?

Да только могут быть и дополнительные БУКВЫ в верхнем регистре, после двух в начала, так что можно и вот так:

->regex/^([А-ЯA-Z])([А-ЯA-Z][а-яa-z])([a-zA-ZА-Яа-я]*)(?!.*? )/
====>$1\L$2$3<====

WHaAt => Whaat

BladeMight avatar Feb 07 '20 14:02 BladeMight

WHaAt => Whaat

Да... Понял.

yuklov avatar Feb 07 '20 15:02 yuklov

Вот такой будет работать

Обновил Mahou, поставил код. Сделает буквы прописным. Но после конвертации первой буквы следующего предложения предыдущие буквы снова становятся строчными:

кто? что? где? Когда?

Это только со словами-одиночками.

yuklov avatar Feb 07 '20 15:02 yuklov

Через сниппеты?

Другой способ тоже есть? Можно ли добавить эту функцию в программу?

yuklov avatar Feb 07 '20 15:02 yuklov

Ты точно поставит этот:

->regex/(?<=[\.!?]\s)([a-zа-яўқғҳ])/
====>\U$1\E<====

?

Тут только для слов*(по сути и пустые сойдут) заканчивающихся на .?!

Другой способ тоже есть?

CustomConversion.txt - чем не вариант?

BladeMight avatar Feb 07 '20 15:02 BladeMight

Так что ^ значит начало слова а не строки в Mahou

А можно указать начало строки?

yuklov avatar Feb 07 '20 15:02 yuklov

:exclamation: :exclamation: Нет. Сниппеты не знают что такое начало строки. Они видят(помнят) только слова которые ты вводишь.

BladeMight avatar Feb 07 '20 15:02 BladeMight

Ты точно поставит этот:

Да, точно. Это поставил:

->regex/(?<=[\.!?]\s)([a-zа-яўқғҳ])/
====>\U$1\E<====

yuklov avatar Feb 07 '20 15:02 yuklov

CustomConversion.txt - чем не вариант?

Там нет автоматического перевода. Больше времени тратится.

Ну, ладно. Эту функцию пока не внедряю.

yuklov avatar Feb 07 '20 15:02 yuklov

Обновил Mahou, поставил код. Сделает буквы прописным. Но после конвертации первой буквы следующего предложения предыдущие буквы снова становятся строчными:

Mahou помнит какими ты их вводил, он не запоминает модификацию которая происходит в сниппетах. Из-за этого Mahou вставляет его таким каким он был введен раннее тобой. Можно попробовать сделать regex для двух слов, и ставить им нужный регистр отдельно.

BladeMight avatar Feb 07 '20 16:02 BladeMight

Ок. Понятно.

yuklov avatar Feb 08 '20 04:02 yuklov

CustomConversion.txt - чем не вариант?

Добавил regex. Но переводить все буквы как прописными.

Код: s/([?<=\.!?]\s)([a-zа-яўқғҳ]?)([a-zа-яўқғҳ])/$1\U$2$3/| или s/([\.!?]\s)([a-zа-яўқғҳ])/$1\U$2/|

Результат: nima. haqida? gap? oʻzi! hmm... dedim. => nima. HAQIDA? GAP? OʻZI! HMM... DEDIM.

На тесте сработал: https://regex101.com/r/SSUDmm/1

yuklov avatar Feb 08 '20 05:02 yuklov

А в CustomConversion.txt можно указать начало строки? Ведь они не сниппеты.

yuklov avatar Feb 08 '20 05:02 yuklov

Обновил, Результат все-таки такой: nima. haqida? gap? oʻzi! hmm... dedim. => nima. HAQIDA? GAP? OʻZI! HMM... DEDIM.

Или в коде проблема?

UPD: Редактировал код: s/([\.!?]\s)([a-zа-яўқғҳ])/$1\U$2\E/|

Теперь сработал, результат: nima. haqida? gap? oʻzi! hmm... dedim. => nima. Haqida? Gap? Oʻzi! Hmm... Dedim.

yuklov avatar Feb 08 '20 14:02 yuklov

В 320b910 сделал исправление для CustomConversion.txt теперь там тоже правильные разделения по |.

А в CustomConversion.txt можно указать начало строки? Ведь они не сниппеты

Да, можно.

На тесте сработал: https://regex101.com/r/SSUDmm/1

Это из-за того что в C# regex нет поддержки \U и \L, поэтому я её приделал сам. Но в моей случае нужно указывать где \U или \L должно заканчиваться на \E, полный список, но Mahou пока поддерживает только \U и \L отдельно, т.е. \U$1\E\L$2\E и т.п., нужно явно указывать конец для \U/\L используя \E.

Вот то что тебе нужно:

s/(^|[\.!?]\s)([a-zа-яўқғҳ])/$1\U$2\E/|

test hold. ok. not. cot? sot! hold. => Test hold. Ok. Not. Cot? Sot! Hold.

BladeMight avatar Feb 08 '20 14:02 BladeMight

И еще насчёт:

нужно явно указывать конец для \U/\L используя \E.

Если \E не указано, вместо него используется конец строки $.

BladeMight avatar Feb 08 '20 14:02 BladeMight

Еще одна просьба. Помоги разбираться.

Хотел добавить после знаков .!?:,; поставить один пробел, но сделать исключение для доменов (uz|com|ru|net и т.д.) Код: s/([…,:;\.!?](?!uz|ru|com|net))([а-яўқғҳА-ЯЎҚҒҲa-zA-Z])/$1 $2/

https://regex101.com/r/kaclkP/2/

Но исключение включает в себя и другие слова, которые начинается с uz, ru, com. net. Например: millati.rus Исключение нужно сделать только для ru. Например: mail.ru.

Итоговый результат нужен быть такой:

millati.rus => millati. rus
mail.ru => mail.ru

Что изменить в коде?

yuklov avatar Feb 08 '20 15:02 yuklov

Почему-то перестал работать этот код:

s/(^|[\.!?]\s)([a-zа-яўқғҳ])/$1\U$2\E/

yuklov avatar Feb 08 '20 15:02 yuklov

Что изменить в коде

Вот так: https://regex101.com/r/NNrS7o/1 ?

BladeMight avatar Feb 08 '20 15:02 BladeMight

Почему-то перестал работать этот код:

s/(^|[\.!?]\s)([a-zа-яўқғҳ])/$1\U$2\E/

Может ты забыл | в конце?

BladeMight avatar Feb 08 '20 15:02 BladeMight

Может ты забыл | в конце?

Даааа... 😭

yuklov avatar Feb 08 '20 15:02 yuklov

Видел: https://github.com/BladeMight/Mahou/issues/262#issuecomment-583745236 ?

BladeMight avatar Feb 08 '20 15:02 BladeMight

Видел: #262 (comment) ?

Да и только-что попробовал. Сработал!

Ну, честно скажу, не понял суть и значения полностью. Особенно это (\s|$)). Зачем \s? Думаю, я не нашёл бы такой способ.

Спасибо большое!

yuklov avatar Feb 08 '20 15:02 yuklov

Можно было и так: https://regex101.com/r/NNrS7o/3 (т.е. вместо (\s|$)(хотя это можно было тоже заменить на просто \s) \b(границы слов))

BladeMight avatar Feb 08 '20 15:02 BladeMight

Значит, если поставлю \b (границы слов) после знаков, это укажет, что нужно найти символы (com|net) полностью.

Здесь читал о \b, но не думал тогда это сработает.

vIF

yuklov avatar Feb 08 '20 15:02 yuklov

Этот и этот AutoHotkey-скрипты автоматически переводят вторую заглавную букву в нижний регистр (и возвращают её в верхний, если печатается аббревиатуру).

Проблема — не удаётся нагуглить, как заставить какой-либо из скриптов работать и с русской раскладкой клавиатуры.

Спасибо.

Kristinita avatar May 13 '20 09:05 Kristinita

@Kristinita В скрипте при использовании SendInput, он отправляет "клавиши как текст", а чтобы были разные символы при разной раскладке нужно получить "vk" символа и отправлять его, т.е. само нажатие клавиши вместо конкретного символа, например как тут: (asc и CharToVk), вот пример рабочего скрипта:

скрипт
#SingleInstance Force
; This section is from Laszlo's script at http://www.autohotkey.com/forum/topic9689.html
keys = abcdefghijklmnopqrstuvwxyz
Loop Parse, keys
	HotKey ~+%A_LoopField%, Hoty

Hoty:
	CapCount := SubStr(A_PriorHotKey,2,1)="+" && A_TimeSincePriorHotkey<999 ? CapCount+1 : 1
	if CapCount = 2
		Send % "{BS}{" . CharToVk(SubStr(A_ThisHotKey,3,1)) . "}"
	else if CapCount = 3
		Send % "{Left}{BS}+{" . CharToVk(SubStr(A_PriorHotKey,3,1)) . "}{Right}"
Return


CharToVk(Char)
{
    VK := DllCall("VkKeyScan", "uchar", Asc(Char), "Short")
    If (VK = -1)
        Return
    SetFormat, Integer, H
    VK :=  SubStr(VK & 0xFF, 3)
    StringUpper, VK, VK
    SetFormat, Integer, D
    Return "vk" VK
}

BladeMight avatar May 13 '20 18:05 BladeMight

Если запустить скрипт от "русской раскладки" всё перестаёт работать, поэтому можно использовать VkKeyScanEx чтобы указать явную раскладку, нужна английская(т.к. символы keys= на английской раскладке), (см: MS-Docs): нужно указать "твою" раскладку на которой ты пишешь английскими символами:


CharToVk(Char)
{
    VK := DllCall("VkKeyScanEx", "uchar", Asc(Char), "uint", 0x00000411, "Short")
    If (VK = -1)
        Return
    SetFormat, Integer, H
    VK :=  SubStr(VK & 0xFF, 3)
    StringUpper, VK, VK
    SetFormat, Integer, D
    Return "vk" VK
}

У меня 0x00000411(или 1041) = Японская раскладка, у тебя наверно будет другая.

BladeMight avatar May 13 '20 18:05 BladeMight

Статус: Частично работает 👷🏻

Первый Ваш вариант.

1. Ё

В Вашем варианте:

KIraKira

КИраКира

но:

ЮЛяЮЛя

Можно использовать символы отсюда:

key = ``1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./

Тогда:

ЮЛяЮля

но:

ЁЛкаЁЛка

С ё не знаю, как справиться.

2. Пробел между словами

При запущенном скрипте происходит также такая конвертация:

Нажимаю Shift+упробелShift+к → получается:

У КирыУ киры

Спасибо.

Kristinita avatar May 14 '20 06:05 Kristinita

символы отсюда:

Лучше уж так:

keys := "``1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./"

(во избежания ; как комментатора строки)

Проверка: ЁЛка ЁЖик => Ёлка Ёжик, исходя из правил:

CapCount := SubStr(A_PriorHotKey,2,1)="+" && A_TimeSincePriorHotkey<999 ? CapCount+1 : 1

Клавиша не должна быть + и время ввода последнего символа должно быть меньше 999 мс. Т.е. если ввести Ё подождать 999мс и потом Л то в итоге будет: ЁЛ.

Пробел между словами

Это производиться из-за:

else if CapCount = 3
		Send % "{Left}{BS}+{" . CharToVk(SubStr(A_PriorHotKey,3,1)) . "}{Right}"

Вот на всякий случай весь скрипт еще раз:

Скрипт
#SingleInstance Force
;-------------------------------------------------------------------------------
; The following section auto-corrects two consecutive capital letters in a word.
; For example, "WOrd" becomes "Word".  It is disabled by default since it might
; cause unwanted corrections such as IfEqual->Ifequal.  To enable it, remove
; the /*..*/ symbols from around it.
; This section is from Laszlo's script at http://www.autohotkey.com/forum/topic9689.html
;-------------------------------------------------------------------------------

; The first line of code below is the set of letters, digits, and/or symbols
; that are eligible for this type of correction.  Customize if you wish:
; keys = abcdefghijklmnopqrstuvwxyz
keys := "``1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./"
Loop Parse, keys
	HotKey ~+%A_LoopField%, Hoty

Hoty:
	CapCount := SubStr(A_PriorHotKey,2,1)="+" && A_TimeSincePriorHotkey<999 ? CapCount+1 : 1
	if CapCount = 2
		Send % "{BS}{" . CharToVk(SubStr(A_ThisHotKey,3,1)) . "}"
	else if CapCount = 3
		Send % "{Left}{BS}+{" . CharToVk(SubStr(A_PriorHotKey,3,1)) . "}{Right}"
Return


CharToVk(Char)
{
	VK := DllCall("VkKeyScanEx", "uchar", Asc(Char), "uint", 0x00000411, "Short")
    If (VK = -1)
        Return
    SetFormat, Integer, H
    VK :=  SubStr(VK & 0xFF, 3)
    StringUpper, VK, VK
    SetFormat, Integer, D
    Return "vk" VK
}

BladeMight avatar May 14 '20 17:05 BladeMight

Пробел между словами

Это производиться из-за:

Хотя. может из-за того что пробел не считается символом здесь, и "не сбрасывает" CapCount, вот с исправлением для пробела:

#SingleInstance Force
;-------------------------------------------------------------------------------
; The following section auto-corrects two consecutive capital letters in a word.
; For example, "WOrd" becomes "Word".  It is disabled by default since it might
; cause unwanted corrections such as IfEqual->Ifequal.  To enable it, remove
; the /*..*/ symbols from around it.
; This section is from Laszlo's script at http://www.autohotkey.com/forum/topic9689.html
;-------------------------------------------------------------------------------

; The first line of code below is the set of letters, digits, and/or symbols
; that are eligible for this type of correction.  Customize if you wish:
; keys = abcdefghijklmnopqrstuvwxyz
keys := "``1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./"
Loop Parse, keys
	HotKey ~+%A_LoopField%, Hoty
	
HotKey ~Space, Hoty
HotKey ~+Space, Hoty

Hoty:
	thi := SubStr(A_ThisHotKey,2)
	CapCount := Substr(A_PriorHotKey,2,1)="+" && A_TimeSincePriorHotkey<999 ? CapCount+1 : 1
	cc := thi = "Space" or thi = "+Space"
	if cc
		CapCount := 0
	if CapCount = 2
		Send % "{BS}{" . CharToVk(SubStr(A_ThisHotKey,3,1)) . "}"
	else if CapCount = 3
		Send % "{Left}{BS}+{" . CharToVk(SubStr(A_PriorHotKey,3,1)) . "}{Right}"
Return


CharToVk(Char)
{
	VK := DllCall("VkKeyScanEx", "uchar", Asc(Char), "uint", 0x00000411, "Short")
    If (VK = -1)
        Return
    SetFormat, Integer, H
    VK :=  SubStr(VK & 0xFF, 3)
    StringUpper, VK, VK
    SetFormat, Integer, D
    Return "vk" VK
}

BladeMight avatar May 14 '20 18:05 BladeMight

Статус: По-прежнему есть проблемы

1. Прямое указание раскладки

1.1. Мнение

Считаю, что прямо указывать в скрипте идентификатор клавиатуры — это не лучшее решение, так как это дополнительная работа для пользователей. Если это возможно (как в Вашем первом варианте), то лучше, чтобы пользователи совершали меньше действий.

1.2. Кастомные раскладки

я пользуюсь кастомными раскладками на основе Colemak для русского и английского языков.

При помощи RegScanner нашёл идентификатор для своей английской раскладки

RegScanner

Весь скрипт такой:

#SingleInstance Force
;-------------------------------------------------------------------------------
; The following section auto-corrects two consecutive capital letters in a word.
; For example, "WOrd" becomes "Word".  It is disabled by default since it might
; cause unwanted corrections such as IfEqual->Ifequal.  To enable it, remove
; the /*..*/ symbols from around it.
; This section is from Laszlo's script at http://www.autohotkey.com/forum/topic9689.html
;-------------------------------------------------------------------------------

; The first line of code below is the set of letters, digits, and/or symbols
; that are eligible for this type of correction.  Customize if you wish:
; keys = abcdefghijklmnopqrstuvwxyz
keys := "``1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./"
Loop Parse, keys
	HotKey ~+%A_LoopField%, Hoty

HotKey ~Space, Hoty
HotKey ~+Space, Hoty

Hoty:
	thi := SubStr(A_ThisHotKey,2)
	CapCount := Substr(A_PriorHotKey,2,1)="+" && A_TimeSincePriorHotkey<999 ? CapCount+1 : 1
	cc := thi = "Space" or thi = "+Space"
	if cc
		CapCount := 0
	if CapCount = 2
		Send % "{BS}{" . CharToVk(SubStr(A_ThisHotKey,3,1)) . "}"
	else if CapCount = 3
		Send % "{Left}{BS}+{" . CharToVk(SubStr(A_PriorHotKey,3,1)) . "}{Right}"
Return


CharToVk(Char)
{
	VK := DllCall("VkKeyScanEx", "uchar", Asc(Char), "uint", 0xa0000409, "Short")
    If (VK = -1)
        Return
    SetFormat, Integer, H
    VK :=  SubStr(VK & 0xFF, 3)
    StringUpper, VK, VK
    SetFormat, Integer, D
    Return "vk" VK
}

Результат:

  1. KIraKra
  2. КИраКра

1.3. Запуск скрипта с русской раскладки

Если запустить скрипт от "русской раскладки" всё перестаёт работать, поэтому можно использовать VkKeyScanEx, чтобы указать явную раскладку, нужна английская(т.к. символы keys= на английской раскладке)

По всей видимости, Вы эту ошибку имели в виду:

Error: "q" is not a valid key name.

"q" is not a valid key name.

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

2. Проблемы в скрипте без указания точной раскладки

То есть, когда используется строка:

VK := DllCall("VkKeyScan", "uchar", Asc(Char), "Short")

вместо:

VK := DllCall("VkKeyScanEx", "uchar", Asc(Char), "uint", 0xa0000409, "Short")

2.1. Ё

По-прежнему:

ЁЛкаЁЛка

Клавиша не должна быть + и время ввода последнего символа должно быть меньше 999 мс. Т.е. если ввести Ё подождать 999мс и потом Л то в итоге будет: ЁЛ.

Да, я понял это, и стараюсь вводить вторую букву после заглавной Ё быстро → проблема не исчезает.

2.2. Заглавная буква, идущая не сразу после первой заглавной

Прошу прощения, я сразу не смог понять, в чём заключается проблема. Она не в пробеле, как я указывал здесь в п. 2.

Сейчас скрипт делает и такие нежелательные исправления:

  1. LeBronLebron
  2. RegScannerRegscanner
  3. AutoHotkeyAutohotkey
  4. BladeMightBlademight

А нужно, чтобы он исправлял заглавную букву на строчную только тогда, когда пользователь печатает её после второй заглавной. Если следующая заглавная буква идёт не сразу после первой — как в примерах выше — то скрипт ничего делать не должен.

Спасибо.

Kristinita avatar May 19 '20 09:05 Kristinita

KIra → Kra

Такое происходит когда неправильно указана раскладка для VkKeyScanEx, т.е. символ не распознаётся и vk-код не получен:

0xa0000409

Неправильно, нужно указывать раскладку на которой пишешь английские символы, из твоих скриншотов это: 0xa0010409 (единичка пропущена у тебя в коде)

Сейчас скрипт делает и такие нежелательные исправления:

999 мс для тебя это слишком много, и мне кажется AHK сбрасывает значение A_TimeSincePriorHotkey при каждом нажатии каждой клавиши, и поэтому не работает как надо.

вот: Тут добавил "сброс" счетчика после нажатия Shift+<клавиши из keys:

#SingleInstance Force
; This section is from Laszlo's script at http://www.autohotkey.com/forum/topic9689.html

; that are eligible for this type of correction.  Customize if you wish:
; keys = abcdefghijklmnopqrstuvwxyz
keys := "``1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./"
Loop Parse, keys
	HotKey ~+%A_LoopField%, Hoty
	
HotKey ~Space, Hoty
HotKey ~+Space, Hoty

CapCount := 0
myEngLayout := 0xa0010409
TyTime := 999

Hoty:
	thi := SubStr(A_ThisHotKey,2)
	x := Substr(A_PriorHotKey,2,1)
	CapCount := (x="+" && A_TimeSincePriorHotkey<TyTime) ? CapCount+1 : 1
	if x = +
		SetTimer, OffCap, % TyTime
	else
		SetTimer, OffCap, off
	cc := thi = "Space" or thi = "+Space"
	if cc
		CapCount := 0
	if CapCount = 2
		Send % "{BS}{" . CharToVk(SubStr(A_ThisHotKey,3,1)) . "}"
	else if CapCount = 3
		Send % "{Left}{BS}+{" . CharToVk(SubStr(A_PriorHotKey,3,1)) . "}{Right}"
Return

OffCap:
	CapCount := 1
	SetTimer, OffCap, off
Return

CharToVk(Char)
{
	global myEngLayout
	VK := DllCall("VkKeyScanEx", "uchar", Asc(Char), "uint", myEngLayout, "Short")
    If (VK = -1)
        Return
    SetFormat, Integer, H
    VK :=  SubStr(VK & 0xFF, 3)
    StringUpper, VK, VK
    SetFormat, Integer, D
    Return "vk" VK
}

Насчёт 999 мс, их тоже можешь поменять в TyTime(Примерный промежуток времени который между клавишами когда печатаешь). В myEngLayout указываешь твою раскладку английскую(я уже поставил там: 0xa0010409), у меня нет твоей раскладки в системе, если я запущу скрипт с "0xa0010409" будет такой же эффект как ты писал: KIra → Kra, так что нужно указывать правильную.

Считаю, что прямо указывать в скрипте идентификатор клавиатуры — это не лучшее решение

Ну а что поделать? VkKeyScanEx - по другому не работает, а VkKeyScan работает только с раскладкой в которой запущен, что по сути то же самое только он сам выбирает раскладку. Можно переписать скрипт на vk-кодах, тогда не будет зависеть от раскладки, получаем vk-коды:


keys := "``1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./"

myEngLayout := 0x00000411
TyTime := 999
x := ""
Loop Parse, keys
{
	x := x . CharToVk(A_LoopField) . " "
	
}
msgbox, %x%
CharToVk(Char)
{
	global myEngLayout
	VK := DllCall("VkKeyScanEx", "uchar", Asc(Char), "uint", myEngLayout, "Short")
    If (VK = -1)
        Return
    SetFormat, Integer, H
    VK :=  SubStr(VK & 0xFF, 3)
    StringUpper, VK, VK
    SetFormat, Integer, D
    Return "vk" VK
}

Получили:

vkC0 vk31 vk32 vk33 vk34 vk35 vk36 vk37 vk38 vk39 vk30 vkBD vkBB vk51 vk57 vk45 vk52 vk54 
vk59 vk55 vk49 vk4F vk50 vkDB vkDD vkDC vk41 vk53 vk44 vk46 vk47 vk48 vk4A vk4B vk4C vkBA
vkDE vk5A vk58 vk43 vk56 vk42 vk4E vk4D vkBC vkBE vkBF 

Делаем под них AHK:

#SingleInstance Force
; keys := "``1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./"
; Loop Parse, keys
	; HotKey ~+%A_LoopField%, Hoty
keys_vk := "vkC0 vk31 vk32 vk33 vk34 vk35 vk36 vk37 vk38 vk39 vk30 vkBD vkBB vk51 vk57 vk45 vk52 vk54 vk59 vk55 vk49 vk4F vk50 vkDB vkDD vkDC vk41 vk53 vk44 vk46 vk47 vk48 vk4A vk4B vk4C vkBA vkDE vk5A vk58 vk43 vk56 vk42 vk4E vk4D vkBC vkBE vkBF"
Loop Parse, keys_vk, " "
	HotKey ~+%A_LoopField%, Hoty
	
HotKey ~Space, Hoty
HotKey ~+Space, Hoty

CapCount := 0
; myEngLayout := 0xa0010409
TyTime := 999

Hoty:
	thi := SubStr(A_ThisHotKey,2)
	x := Substr(A_PriorHotKey,2,1)
	CapCount := (x="+" && A_TimeSincePriorHotkey<TyTime) ? CapCount+1 : 1
	if x = +
		SetTimer, OffCap, % TyTime
	else
		SetTimer, OffCap, off
	cc := thi = "Space" or thi = "+Space"
	if cc
		CapCount := 0
	if CapCount = 2
		Send % "{BS}{" . SubStr(A_ThisHotKey,3) . "}"
	else if CapCount = 3
		Send % "{Left}{BS}+{" . SubStr(A_PriorHotKey,3) . "}{Right}"
Return

OffCap:
	CapCount := 1
	SetTimer, OffCap, off
Return


; Get Vk Codes
; ----------START
; x := ""
; Loop Parse, keys
; {
	; x := x . CharToVk(A_LoopField) . " "
	
; }
; msgbox, %x%
; CharToVk(Char)
; {
	; global myEngLayout
	; VK := DllCall("VkKeyScanEx", "uchar", Asc(Char), "uint", myEngLayout, "Short")
    ; If (VK = -1)
        ; Return
    ; SetFormat, Integer, H
    ; VK :=  SubStr(VK & 0xFF, 3)
    ; StringUpper, VK, VK
    ; SetFormat, Integer, D
    ; Return "vk" VK
; }
; ----------END

  • этот скрипт работает в любой раскладке, т.к. используются коды клавиш вместо символов. (я решил оставить(закомментировал) прошлые функции внизу, их можешь убрать если не нужны, они не влияют на функционал, начинаются с ; - комментарии)

Клавиша не должна быть +

Тут имеется в виду Shift, т.к. в горячих клавишах AHK: + = Shift, ^ = Ctrl, ! = Alt, # = Win, т.е. Shift+клавиша

BladeMight avatar May 19 '20 22:05 BladeMight

Статус: Частично работает 🌖

1. Исправленные проблемы

Для последнего скрипта:

  1. Запуск из другой раскладки
  2. Ё

2. Сохранившаяся проблема

вот: Тут добавил "сброс" счетчика после нажатия Shift+клавиши из keys:

По-прежнему актуальна 2.2. LeBronLebron, TyTimeTytime и т. д. У Вас воспроизводится эта проблема?

(Если что, да, читал то, что Вы писали про A_TimeSincePriorHotkey и TyTime)

3. Числа и небуквенные символы

Примеры проблем со скриптом:

  1. (Кира)(кира)
  2. ** (выделение текста жирным в Markdown) → *8

я не смог — по крайней мере для английской/русской раскладок, — подобрать случаи, когда включение в число keys_vk клавиш, где нет буквенных английских/русских символов, приносило бы пользу, а не вред. Полагаю, лучше убрать virtual key codes для клавиш с цифрами и знаками препинания (OEM_MINUS, OEM_PLUS, OEM_5, OEM_2). Значение keys_vk будет в таком случае следующим:

keys_vk := "vkC0 vk51 vk57 vk45 vk52 vk54 vk59 vk55 vk49 vk4F vk50 vkDB vkDD vk41 vk53 vk44 vk46 vk47 vk48 vk4A vk4B vk4C vkBA vkDE vk5A vk58 vk43 vk56 vk42 vk4E vk4D vkBC vkBE"

4. Mahou

Не то, что баг, но когда скрипт запущен, Mahou начинает странно себя вести. Полагаю, это по крайней мере следует отразить в описании скрипта.

Пишу Кира → 2 раза нажимаю на шорткат команды Convert last line → результат:

КираPbhtирак

Первый раз Mahou конвертирует правильно → обратно — уже нет.

Спасибо.

Kristinita avatar May 25 '20 08:05 Kristinita

@Kristinita

Сохранившаяся проблема

Числа и небуквенные символы

Тут скорее из-за самого "принципа работы", скрипт не "распознаёт символы" как Mahou, для этого понадобиться узнавать текущую раскладку и брать символ через ToUnicodeEx, а скрипт просто регистрирует клавиши по vk-кодам и делает простую логику:

  1. при нажатии клавиши с (shift) верхним регистром дважды:
    • сделать чтобы второй ввод был нижнего регистра
  2. при нажатии клавиши с (shift) верхним регистром трижды:
    • вернуть всё к верхнему регистру

1 и 2: при условии что ввод предыдущего символа был не позже 999мс.

Так же я добавил в него "сброс", чтобы после определенного времени сбрасывался "счётчкик" введенных символов в верхнем регистре.

Можно лучше разделить время "сброса" и "ввод предыдущего символа" на разные значения, например при 300 и 999 работает вполне нормально:

#SingleInstance Force
keys_vk := "vkC0 vk31 vk32 vk33 vk34 vk35 vk36 vk37 vk38 vk39 vk30 vkBD vkBB vk51 vk57 vk45 vk52 vk54 vk59 vk55 vk49 vk4F vk50 vkDB vkDD vkDC vk41 vk53 vk44 vk46 vk47 vk48 vk4A vk4B vk4C vkBA vkDE vk5A vk58 vk43 vk56 vk42 vk4E vk4D vkBC vkBE vkBF"
Loop Parse, keys_vk, " "
	HotKey ~+%A_LoopField%, Hoty
	
HotKey ~Space, Hoty
HotKey ~+Space, Hoty

CapCount := 0
PriTime = := 999
TyTime := 300

Hoty:
	thi := SubStr(A_ThisHotKey,2)
	x := Substr(A_PriorHotKey,2,1)
	CapCount := (x="+" && A_TimeSincePriorHotkey<PriTime) ? CapCount+1 : 1
	SetTimer, OffCap, off
	if x = +
		SetTimer, OffCap, % TyTime
	cc := thi = "Space" or thi = "+Space"
	if cc
		CapCount := 0
	if CapCount = 2
		Send % "{BS}{" . SubStr(A_ThisHotKey,3) . "}"
	else if CapCount = 3
		Send % "{Left}{BS}+{" . SubStr(A_PriorHotKey,3) . "}{Right}"
Return

OffCap:
	CapCount := 0
	SetTimer, OffCap, off
Return

BLadeMIght -> BladeMight BladeMight -> BladeMight RegScanner -> RegScanner LeBron -> LeBron

небуквенные символы

Можно попробовать исключить vk коды этих клавиш, однако на разных раскладках будут разные клавиши... Поэтому возможно будет проблематично...

Mahou начинает странно себя вести

Скрипт влияет на ввод, и Mahou ловит то что вводит скрипт, тут ничего не поделаешь, придется выбирать. Можно попробовать в сниппетах сделать похожее правило используя regex, однако в Mahou сниппеты срабатывают только на конце слов, т.е. при нажатии на пробел:

->regex/^([А-ЯA-Z])([А-ЯA-Z][а-яa-z])([a-zA-ZА-Яа-я]*)(?!.*? )/
====>$1\L$2$3 <====

Этот сниппет работает только с буквами(исходя из Regex), поэтому с ним не будет проблем с символами.

BladeMight avatar May 25 '20 19:05 BladeMight