É possível digitar caracteres especiais no AppleScript?

6

O inseto:

Para determinados caracteres e símbolos especiais, o AppleScript não keystroke o caractere real e, em vez disso, simplesmente digite a letra a.


Um exemplo:

O seguinte código AppleScript:

tell application "System Events" to keystroke "² ³ é ½ ₭"

digita a seguinte sequência de texto (não importa em qual aplicativo eu esteja):

a a a a a

Uma solução alternativa:

Um pode efetivamente "Digite" o texto, colocando os caracteres especiais na área de transferência e, em seguida, colando a área de transferência, da seguinte forma:

set the clipboard to "² ³ é ½ ₭"
tell application "System Events" to keystroke "v" using command down

Evito usar o método acima para colocar texto na área de transferência no AppleScript, porque ele necessariamente converte a área de transferência em rich text, no processo.

Eu prefiro empregar o método fornecido aqui , para garantir que o texto simples seja colocado na área de transferência. Mas esse método converte caracteres especiais em mojibake.

Por exemplo, usando a mesma string acima, esse método coloca o seguinte texto na área de transferência:

² ³ é ½ ₭

Você pode contabilizar manualmente esse problema, no entanto, adicionando um replace_chars declaração para cada caractere especial.


A questão:

Existe uma maneira de digitar caracteres especiais via AppleScript, sem ter que envolver a prancheta?

Por exemplo, existe alguma maneira de adicionar os caracteres especiais desejados a um "banco" ou arquivo de sistema em algum lugar, para que System Events aplicativo está familiarizado com eles?


rubik's sphere
fonte

Respostas:

6

É possível com CoreGraphics ( CGEventPost ), é um C API (não funciona em um Cocoa-AppleScript), mas é possível chamar um executável de um AppleScript.


Aqui está o método para criar o executável com o Xcode (versão 8.3.3):

Você pode fazer isso sozinho (você pode baixar Xcode de Loja de aplicativos ), ou peça a uma pessoa de confiança para criar o executável.

1- Abra o Xcode, selecione o menu " Arquivo "- & gt;" Novo "- & gt;" Projeto ... " enter image description here


2- Selecione Mac OS e Ferramenta de linha de comando , Clique no " Próximo "botão. enter image description here


3- Diga TypeCharactersselecione Objetivo-C como idioma, clique no botão " Próximo "botão. enter image description here


4- Salve o projeto na pasta desejada.


5- Na janela do Xcode, selecione o main.m ícone, limpe o texto na janela e cole um desses dois códigos:

O código precisa de um loop por causa de um bug, o CGEventKeyboardSetUnicodeString() método trunca uma string que excede vinte caracteres, ou é um limite (não documentado).

Este código usa um loop para digitar uma lista de caracteres em cada iteração, a lista pode conter de um a vinte caracteres. (É rápido, 1 segundo para digitar 2400 caracteres em um documento do TextEdit no meu computador.)

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        if (argc > 1) {
            NSString *theString = [NSString stringWithUTF8String:argv[1]];
            NSUInteger len = [theString length];
            NSUInteger n, i = 0;
            CGEventRef keyEvent = CGEventCreateKeyboardEvent(nil, 0, true);
            unichar uChars[20];
            while (i < len) {
                n = i + 20;
                if (n>len){n=len;}
                [theString getCharacters:uChars range:NSMakeRange(i, n-i)];
                CGEventKeyboardSetUnicodeString(keyEvent, n-i, uChars);
                CGEventPost(kCGHIDEventTap, keyEvent); // key down
                CGEventSetType(keyEvent, kCGEventKeyUp);
                CGEventPost(kCGHIDEventTap, keyEvent); // key up (type 20 characters maximum)
                CGEventSetType(keyEvent, kCGEventKeyDown);
                i = n;
                [NSThread sleepForTimeInterval:0.004]; // wait 4/1000 of second, 0.002 it's OK on my computer, I use 0.004 to be safe, increase it If you still have issues
            }
            CFRelease(keyEvent);
        }
    }
    return 0;
}

Este código usa um loop para digitar um caractere em cada iteração (é mais lento que o primeiro código).

#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        if (argc > 1) {
            NSString *theString = [NSString stringWithUTF8String:argv[1]];
            UniChar uChar;
            CGEventRef keyEvent = CGEventCreateKeyboardEvent(nil, 0, true);
            for (int i = 0; i < [theString length]; i++)
            {
                uChar = [theString characterAtIndex:i];
                CGEventKeyboardSetUnicodeString(keyEvent, 1, &uChar);
                CGEventPost(kCGHIDEventTap, keyEvent); // key down
                CGEventSetType(keyEvent, kCGEventKeyUp);
                CGEventPost(kCGHIDEventTap, keyEvent); // key up (type the character)
                CGEventSetType(keyEvent, kCGEventKeyDown);
                [NSThread sleepForTimeInterval:0.001]; // wait 1/1000 of second, no need of this line on my computer, I use 0.001 to be safe, increase it If you still have issues
            }
            CFRelease(keyEvent);
        }
    }
    return 0;
}

Nota : Este código funciona em MacOS Sierra e deve trabalhar em o capitão , mas não em um mais antigo OS .

enter image description here


6- Selecione o menu " produtos "- & gt;" Construir ".


7- Selecione os TypeCharacters ícone no produtos pasta, clique com o botão direito do mouse e selecione a opção " Mostrar no Finder "menu no menu contextual.

enter image description here


8- Do Finder, mova o " TypeCharacters "arquivo para a pasta desejada, saia Xcode , Isso é tudo.


De um AppleScript , chame o executável, assim

set myString to "ùéèà ² ³ é ½ ₭ "
do shell script "'/full path/of/TypeCharacters' " & quoted form of myString
jackjr300
fonte
Resposta incrível. Esta solução funciona perfeitamente no OS X 10.11.6 também. Eu não poderia sonhar com uma solução melhor. Eu também aprecio as imagens detalhadas. Muitíssimo obrigado!!!
rubik's sphere
Eu descobri um bug: se o comprimento de myString excede 20 caracteres, a seqüência será truncada. Ou seja, qualquer texto que segue o vigésimo caractere não será digitado. Você sabe como consertar isso?
rubik's sphere
Agora, eu uso um loop para digitar cada caractere (testado com uma seqüência de 2000 ou mais caracteres), atualizei o código na minha resposta.
jackjr300
Sua nova solução resolveu o problema. Obrigado! Nota lateral, você removeu o #import <Foundation/Foundation.h> linha do seu código na sua edição, mas essa linha ainda é necessária para uma compilação bem-sucedida. Eu sei que esta linha de código está lá por padrão, mas existe alguma ambiguidade porque suas instruções dizem para "limpe o texto na janela."
rubik's sphere
Eu acho que a nova solução tem um novo bug. De vez em quando, o texto digitado perderá um caractere ou alterará a ordem do texto. Isso ocorre independentemente do tamanho da string. Aqui está um exemplo real: A string que o arquivo TypeCharacters recebeu foi = 278,932 mas a seguinte string foi digitada: =2 78,93.
rubik's sphere
4

Uma solução alternativa (com a área de transferência):

1 - Você pode usar um método de cacau de um shell:

set tString to "² ³ é ½ ₭"
my stringToClipboard(tString)
tell application "System Events" to keystroke "v" using command down

on stringToClipboard(t1)
    do shell script "/usr/bin/python -c 'import sys;from AppKit import NSPasteboard, NSPasteboardTypeString; cb=NSPasteboard.generalPasteboard();cb.declareTypes_owner_([NSPasteboardTypeString], None);cb.setString_forType_(sys.argv[1].decode(\"utf8\"), NSPasteboardTypeString)' " & quoted form of t1
end stringToClipboard

2 - Ou um applet Cocoa-AppleScript:

use framework "AppKit"
use scripting additions
set tString to "² ³ é ½ ₭"
my stringToClipboard(tString)
tell application "System Events" to keystroke "v" using command down

on stringToClipboard(t1)
    set ca to current application
    set cb to ca's NSPasteboard's generalPasteboard()
    cb's declareTypes:{ca's NSPasteboardTypeString} owner:(missing value)
    cb's setString:t1 forType:(ca's NSPasteboardTypeString)
end stringToClipboard
jackjr300
fonte
3

A fim de keystroke um caractere, esse caractere precisa ser mapeado para uma tecla real no teclado selecionado.

Por exemplo, eu posso keystroke é e ² muito bem, porque eu estou usando o Francês - PC layout de teclado. No entanto, um teclado QWERTY americano padrão não possui essas teclas e não será capaz de keystroke eles.


fonte
2

Você pode definir todos os seus conjuntos de caracteres especiais como variáveis, como este

on specialKeys(input)
    tell application "System Events"
        keystroke input
    end tell
end specialKeys


set characterSet1 to "²³é½₭ "
set characterSet2 to "³ "
set characterSet3 to "é "
set characterSet4 to "¬Ω "
set characterSet5 to "₭ "
set characterSet6 to characterSet1 & characterSet2 & characterSet3 & characterSet4 & characterSet5

specialKeys(characterSet1)
-- ² ³ é ½ ₭ is the result from calling specialKeys(characterSet1) After adding the text replacement for “a a a a a” in my keyboard preferences

Alguns caracteres especiais são pressionados corretamente quando você os define como variáveis. Qualquer um dos caracteres especiais que você definir como variáveis ​​que não digitam corretamente, você pode adicionar “substituições de texto” nas preferências do sistema para o seu teclado.

Certifique-se de selecionar todos os itens e arrastá-los para sua área de trabalho ou qualquer outro lugar. Isso criará um arquivo .plist que será um backup das configurações originais. Você pode arrastar esse arquivo de volta a qualquer momento.

enter image description here

enter image description here

Em seguida, no ScriptEditor, certifique-se de ter as substituições de texto ativadas no submenu "substituições" do menu de edição.

enter image description here

enter image description here

wch1zpink
fonte
2
o "Substituição de texto" A solução alternativa funciona como desejado na maioria dos aplicativos do OS X (por exemplo, TextEdit, Notes, Editor de scripts, etc.), mas eu estava esperando por uma solução que funcionasse em cada campo de texto em qualquer aplicativo. Pedindo muito, eu sei! Eu ainda acho que esta é uma solução muito inteligente, então +1. Obrigado pela resposta.
rubik's sphere