Typing text with accented vowels using AppleScript

Hello.

I’m trying to write in a text the accented vowels using AppleScript, but I can’t get it.

This is the code I tried, but it doesn’t work properly.

use AppleScript version "2.4"
use scripting additions

set x1 to "á"
set x2 to "a"
tell application "System Events" to keystroke x1 & " " & x2 -- a a (Not the desired result)
-- However,
display dialog x1 & " " & x2 -- á a

set y1 to id of x1 -- 225
set y2 to id of x2 --97

set z1 to character id y1
set z2 to character id y2
tell application "System Events" to keystroke (z1 & " " & z2) -- a a (is also not the desired result)
display dialog z1 & " " & z2 -- á a

Thank you very much for any suggestions.

I think I vaguely remember someone writing about this previously but I don’t recall where or its outcome.

However, as I understand it, keystroke works for lower ASCII characters but not for upper (or beyond). This is somewhat complicated by the keyboard layout that you’re using… for example, a German keyboard layout has a primary keys for various umlaut characters (e.g. ä, ö, ü) and thus you could use the keystroke command with them; a French keyboard layout meanwhile, might have accent grave or cédille keys.

You might instead try key code:

tell application "TextEdit" to activate
tell application "System Events"
	key code 14 using option down -- option-e for acute accent «´»
	key code 0 -- letter a… or á with previous key code
	keystroke " a"
end tell
--> á a

Update: I just tried what I suggested above and tested out the basic French keyboard layout. When both the Script Editor and TextEdit documents are set to French, then the following takes place:

tell application "TextEdit" to activate
tell application "System Events"

	keystroke "é e"
	
end tell
--> é e

-- When only one is set to French…
--> a e

Thanks for replying, @Mockman

My keyboard is Spanish and these are the results I have been able to get.

tell application "TextEdit" to activate
tell application "System Events"
	--key code 14 using option down -- option-e for acute accent «´»  -- €
	--key code 0 -- letter a… or á with previous key code  -- a
	--keystroke " a"  -- a
	--key code 0 using option down -- å
	
	
	--set num to ASCII number "á" -- 135
	--set theChar to ASCII character 135
	--keystroke theChar -- a
	
	
	--set theChar to ASCII character 239 -- ´ (?)  
	--keystroke theChar -- > a
end tell

I will keep looking, but I don’t know where to look anymore.

I imagine you must have a solution.

On an English keyboard, the ‘e’ key is used to combine other characters with the acute accent using the option key. On a Spanish keyboard (Spanish - ISO), that combination apparently generates the Euro symbol.

The objective is to use the key codes to represent what keys you would type to generate a character — in this case, the accented á.

On that keyboard, to type that character, it looks like you type the ‘´’ key followed by the letter ‘a’. Looking up the ‘Spanish - ISO’ keyboard in the Input Sources, the ´ key is to the left of the return key. (On the ‘Spanish’ keyboard, the first key is to the right of the ‘p’.)

The key code for that key is 39 (or 33) so:

tell application "TextEdit" to activate
tell application "System Events"
	
	key code 39 -- acute accent «´»
	key code 0 -- letter «a»
	
end tell

Thank you very much, @Mockman
It works! :-))

tell application "TextEdit" to activate
tell application "System Events"
	
	keystroke return
	key code 39 -- acute accent «´»
	key code 0 -- letter «a»
	--á
	
	key code 39
	key code 14 -- e
	--é
	
	key code 39
	key code 34 -- i
	--í
	
	key code 39
	key code 31 -- o
	--ó
	
	key code 39
	key code 32 -- u
	--ú
	keystroke return & space
	
	set str to "El último café cálido quedó frío" -- The last hot coffee remained cold
	set the clipboard to str
	keystroke (the clipboard as text) -- El altimo cafa calido queda frao (¡!)
	-- This is one of the situations of interest is the handling of the clipboard with strings containing accented vowels.	
	-- Another is searching for accented words in the Finder search box.	
	keystroke return
	
	keystroke "El "
	key code 39
	key code 32
	
	keystroke "ltimo caf"
	key code 39
	key code 14
	
	keystroke " c"
	key code 39
	key code 0
	
	keystroke "lido qued"
	key code 39
	key code 31
	
	keystroke " fr"
	key code 39
	key code 34
	
	keystroke "o"
	
	--result
	--áéíóú
	--El altimo cafa calido queda frao
	--El último café cálido quedó frío
	
end tell

Now a new challenge arises: making use of it.

The practical problems are the use of the clipboard with words containing accented vowels, and especially when it is used to enter information in the Finder search box to perform searches. The results are disastrous because of the presence of characters that do not correspond to those desired.

How could it be made easier to use ? I did an exercise to print a string, (really heavy and painful); using a script based on “text item delimiters” it is possible to correct the strings.

This script removes from the clipboard the changes caused by the presence of accented vowels and allows you to continue working with the same vowels, but without accentuation.

on removeAccents(_str) 
	set oldDelims to AppleScript's text item delimiters
	
	set listWithAccents to {"á", "é", "í", "ó", "ú", "Á", "É", "Í", "Ó", "Ú"}
	set listWithoutAccents to {"a", "e", "i", "o", "u", "A", "E", "I", "O", "U"}
	
	considering case --
		repeat with i from 1 to count of listWithAccents
			set AppleScript's text item delimiters to item i of listWithAccents
			set theTextItems to text items of _str
			set AppleScript's text item delimiters to item i of listWithoutAccents
			set _str to theTextItems as string
		end repeat
	end considering
	
	set AppleScript's text item delimiters to oldDelims
	return _str
end removeAccents

A different question is to correct strings with accents, for example, when using the clipboard with them while writing a script.

Can you think of any suggestions?

If your objective is to ‘flatten’ or strip all of the diacriticals in the clipboard text, then you can run your handler against it like so:

set raised to {"á", "é", "í", "ó", "ú", "Á", "É", "Í", "Ó", "Ú"} as text
--> "áéíóúÁÉÍÓÚ"

set the clipboard to raised
-- now the clipboard contains the above text


set the clipboard to my removeAccents(the clipboard)
--> aeiouAEIOU

ps Your script is missing the underscore in _str in this line:

set theTextItems to text items of str

FWIW, this handler looks like a good candidate to be put into a library script.

Here is a shell alternative that uses the tr command. I bashed my head on this for a long time before I was able to get it to work in an applescript.

Here is the shell command which worked instantly in the Terminal:

% printf 'El último café cálido quedó frío — áéíóúÁÉÍÓÚ' | tr "áéíóúÁÉÍÓÚ" "aeiouAEIOU"
--> "El ultimo cafe calido quedo frio — aeiouAEIOU"

However, when I put the same command into an applescript, it returned only this:

set raised to quoted form of ("El último café cálido quedó frío" & " — áéíóúÁÉÍÓÚ") as text
do shell script "printf " & raised & " | tr \"áéíóúÁÉÍÓÚ\" \"aeiouAEIOU\""
--> "El UUltimo cafUo cUelido quedUI frUAo — UeUoUAUIUUUUUUUUUUUU"

While I concluded that the issue was related to the shell environment, I couldn’t figure out how to proceed but I read of a similar sort of issue on stack overflow that modified the LANG parameter. It wasn’t solved there but eventually I read the man page for pbcopy along with the perpetually insightful TN2065 and came up with this (I added the pbcopy command):

set raised to quoted form of ("El último café cálido quedó frío" & " — áéíóúÁÉÍÓÚ") as text
--> "El último café cálido quedó frío — áéíóúÁÉÍÓÚ"

do shell script "export 'LANG=en_US.UTF-8' ; printf " & raised & " | tr \"áéíóúÁÉÍÓÚ\" \"aeiouAEIOU\" | pbcopy"

When you paste, you should get this:

--> El ultimo cafe calido quedo frio — aeiouAEIOU

Hopefully, it will work with your system as well.

Thank you very much, @Mockman for your time and work.

Your code works perfectly for copying the entered string without accents to the clipboard, performing the same function as removeAccents(_str), but using only a minimal amount of code. I will incorporate it into the “Text Utility” file in my script library.

set the clipboard to ""

set raised to quoted form of ("El último café cálido quedó frío" & " — áéíóúÁÉÍÓÚ") as text

--> "El último café cálido quedó frío — áéíóúÁÉÍÓÚ"

do shell script "export 'LANG=en_US.UTF-8' ; printf " & raised & " | tr \"áéíóúÁÉÍÓÚ\" \"aeiouAEIOU\" | pbcopy"

tell application "System Events" to keystroke (the clipboard as text) --El ultimo cafe calido quedo frio — aeiouAEIOU

The result is not the best solution, but at least it allows to keep the same vowels, but without accents. :-((

The ideal would be to be able to print the original string keeping the accents.

The alternative (it works) by using ‘key code’ may be useful in some specific cases, but it is not practical for general use.

Thank you very much.

To keystroke some accented letter In the Spanish keyboard you have to key code “´” (right accent) before it. Right accent has key code 33 . Following example is written for Spanish keyboard. With non-Spanish keyboard as current setting it will give wrong result.

tell application "TextEdit"
	make new document
	activate
end tell

tell application "System Events"
	key code 33
	keystroke "a"
	keystroke space & "a"
end tell

.

Following worked for me as well. I added the delay for stability reasons:

tell application "TextEdit" to make new document

tell application "System Events"
	set frontmost of process "TextEdit" to true
	delay 1
	keystroke "El ´ultimo caf´e c´alido qued´o fr´io"
end tell

.

Now, to automate the entire “keystroke” process given the source string:

set sourceString to "El último café cálido quedó frío"

tell application "TextEdit" to make new document

tell application "System Events"
	set frontmost of process "TextEdit" to true
	delay 1
	repeat with j from 1 to length of sourceString
		set aChar to character j of sourceString
		if aChar is not in characters of "áéíóúÁÉÍÓÚ" then
			keystroke aChar
		else
			repeat with i from 1 to 10
				if aChar = character i of "áéíóúÁÉÍÓÚ" then exit repeat
			end repeat
			key code 33
			keystroke character i of "aeiouAEIOU"
		end if
	end repeat
end tell

1 Like

The last script in the handler form:

set sourceString to "El último café cálido quedó frío"

tell application "TextEdit" -- optional, for testing reasons
	make new document -- optional, for testing reasons
	activate -- optional, for testing reasons
end tell -- optional, for testing reasons

keystrokeSpanishAccentedText(sourceString)

on keystrokeSpanishAccentedText(sourceString)
	tell application "System Events"
		delay 1
		repeat with j from 1 to length of sourceString
			set aChar to character j of sourceString
			if aChar is not in characters of "áéíóúÁÉÍÓÚ" then
				keystroke aChar
			else
				repeat with i from 1 to 10
					if aChar = character i of "áéíóúÁÉÍÓÚ" then exit repeat
				end repeat
				key code 33
				keystroke character i of "aeiouAEIOU"
			end if
		end repeat
	end tell
end keystrokeSpanishAccentedText

Hi @KniazidisR

It works! :-))
Thank you very much for explaining me the reasons why it works.
A Spanish keyboard has the acute accent (') assigned to the key to the right of the “ñ” so there is no need to use the key codes.
The process is facilitated by this handler that could be located in a script library so the strange operations are hidden and do not bother anyone.

tell application "TextEdit" to make new document

tell application "System Events"

set frontmost of process "TextEdit" to true

delay 1

set phrase to "El último café cálido quedó frío"

set the clipboard to my replaceAccents(phrase)

keystroke (the clipboard as text) -- El último café cálido quedó frío

end tell

on replaceAccents(_string)

set oldDelims to AppleScript's text item delimiters

set listAccentuatedVowels to {"á", "é", "í", "ó", "ú", "Á", "É", "Í", "Ó", "Ú"}

set listOfUnaccentedVowels to {"´a", "´e", "´i", "´o", "´u", "´A", "´E", "´I", "´O", "´U"}

considering case -- Teniendo en cuenta May y min

repeat with i from 1 to count of listAccentuatedVowels

set AppleScript's text item delimiters to item i of listAccentuatedVowels

set textItems to text items of _string

set AppleScript's text item delimiters to item i of listOfUnaccentedVowels

set _string to textItems as string

end repeat

end considering

set AppleScript's text item delimiters to oldDelims

return _string

end replaceAccents

Thank you very much for your invaluable help.
You have solved an obstacle that I have been thinking about for more than 2 years.

P.S.: While I was preparing my response to your first reply I saw that you have been polishing a more complete script that I have not yet been able to parse.

I have also not been able to provide my code in a suitable form for macscripter to do a correct format. Sorry.

I will study the scripts you have written subsequently.

Thanks.

[I would appreciate if you could try to paste the code from my answer to get it formatted correctly and have a better reading of it.]

I already read your code and understood it.
Maybe your code is a bit more obscure than mine because of the double iteration.

On the other hand, there are errors in your results (some vowels are changed by others, some acute accents are transformed into grave and there are even changes in some consonant).

–El último café cálido quedó frío – > El ùltimo café càlico queude trìo

.
I’ve never used a Spanish keyboard before, so there must be errors in my script. But I won’t fix it, because your text-delimited solution is clearly the best. I will only note that the use of the clipboard in your script is redundant. It works excellently, so the solution is yours, and your “thanks” that has already been said is enough for me.
.

tell application "TextEdit" to make new document

tell application "System Events"
	set frontmost of process "TextEdit" to true
	delay 1
	set phrase to "El último café cálido quedó frío"
	keystroke (my replaceAccents(phrase)) -- EDITED
end tell

on replaceAccents(_string)
	set oldDelims to AppleScript's text item delimiters
	set listAccentuatedVowels to {"á", "é", "í", "ó", "ú", "Á", "É", "Í", "Ó", "Ú"}
	set listOfUnaccentedVowels to {"´a", "´e", "´i", "´o", "´u", "´A", "´E", "´I", "´O", "´U"}
	considering case -- Teniendo en cuenta May y min
		repeat with i from 1 to count of listAccentuatedVowels
			set AppleScript's text item delimiters to item i of listAccentuatedVowels
			set textItems to text items of _string
			set AppleScript's text item delimiters to item i of listOfUnaccentedVowels
			set _string to textItems as string
		end repeat
	end considering
	set AppleScript's text item delimiters to oldDelims
	return _string
end replaceAccents

Hi @KniazidisR

tell application "System Events”
	set frontmost of process "TextEdit" to true
	delay 1
	keystroke "El ´ultimo caf´e c´alido qued´o fr´io" -- Thank you @KniazidisR
end tell

keystroke "El ´ultimo caf´e c´alido qued´o fr´io"

That line is key to the solution of the question and you are the author.

Regards.

Here is more general solution - to keystroke any special characters (present in the current keyboard input source). It uses the clipboard.

set the clipboard to "El último café cálido quedó frío
² ³ é ½ ₭"

tell application "TextEdit" to make new document
tell application "System Events"
	set frontmost of process "TextEdit" to true
	repeat until frontmost of process "TextEdit"
		delay 0.2
	end repeat
	keystroke "v" using command down
end tell