Character ID Script

I occasionally need to know the ID or description of a character in a document, and I wrote the following script for this purpose. A few comments:

  • This script can be tested by opening it in Script Editor, selecting one or more characters, and running the script.

  • Some characters are not visible or may be difficult to recognize, and in these circumstances the script provides a description of the character.

  • When multiple characters are selected, the script reports the ID of the leftmost-selected character, although there is an option to show the ID of all selected characters.

  • The character descriptions are based on what I believe to be commonly-accepted usage, rather than any recognized standard.

  • The script appears to work with most applications that have an Edit > Copy menu item, although I have encountered an occasional odd result with Safari, which appears due to HTML formatting.

  • I run this script by way of FastScripts but there are many other options.

-- Revised 2021.04.27

on main()
	set maxSelectionAllowed to 200
	set maxCharactersDisplayed to 30
	set characterData to {{0, "null"}, {9, "horizontal tab"}, {10, "line feed"}, {11, "vertical tab"}, {12, "form feed"}, {13, "carriage return"}, {32, "space"}, {34, "double quote"}, {39, "single quote"}, {45, "hyphen"}, {96, "backtick"}, {8194, "en space"}, {8195, "em space"}, {8211, "en dash"}, {8212, "em dash"}, {8216, "left single quote"}, {8217, "right single quote"}, {8220, "left double quote"}, {8221, "right double quote"}}
	
	set the clipboard to "No Text"
	tell application "System Events"
		set appName to (name of first process whose frontmost is true)
		tell process appName to click menu item "Copy" of menu "Edit" of menu bar 1
	end tell
	
	repeat 6 times
		set selectedText to the clipboard
		if selectedText ≠ "No Text" then exit repeat
		delay 0.05
	end repeat
	
	if selectedText = "No Text" then
		errorDialog("A character was not selected. The active application is " & appName & ".")
	else
		set theID to id of (text 1 of selectedText)
		set theDescription to quote & (text 1 of selectedText) & quote
	end if
	
	repeat with aList in characterData
		if (item 1 of aList) = theID then
			set theDescription to (item 2 of aList)
			exit repeat
		end if
	end repeat
	
	set selectedTextCount to (count selectedText)
	
	if selectedTextCount > 1 then
		display dialog "Application:  " & appName & linefeed & "Character:  " & theDescription & linefeed & "ID:  " & theID buttons {"Show All", "OK"} cancel button 2 default button 2 with title "Character ID" with icon note
	else
		display dialog "Application:  " & appName & linefeed & "Character:  " & theDescription & linefeed & "ID:  " & theID buttons {"OK"} cancel button 1 default button 1 with title "Character ID" with icon note
	end if
	
	if button returned of result = "Show All" then
		if selectedTextCount > maxSelectionAllowed then errorDialog("The selected string exceeds " & (maxSelectionAllowed as text) & " characters and cannot be displayed.")
		set text item delimiters to space
		set theIDs to (text items of (id of selectedText)) as text
		set text item delimiters to ""
		if selectedTextCount > maxCharactersDisplayed then
			set selectedText to "See selection in Application"
		else
			set selectedText to quote & selectedText & quote
		end if
		display dialog "Application:  " & appName & linefeed & "String:  " & selectedText & linefeed & "IDs:  " & theIDs buttons {"OK"} cancel button 1 default button 1 with title "Character ID" with icon note
	end if
end main

on errorDialog(dialogText)
	display dialog dialogText buttons {"OK"} cancel button 1 default button 1 with title "Character ID" with icon stop
end errorDialog

main()

The following is a description of the “id” property of text objects from the AppleScript Language Guide. It provides some helpful background information, and special note should be made of the statement that a character can be composed of more than one code point, which can limit the usefulness of my script in certain circumstances.

https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/reference/ASLR_classes.html#//apple_ref/doc/uid/TP40000983-CH1g-DontLinkElementID_611

To use your script without FastScripts, and in any application, including Safari.app, you can hide the script editor:


on main()
	set maxSelectionAllowed to 200
	set maxCharactersDisplayed to 30
	set characterData to {{0, "null"}, {9, "horizontal tab"}, {10, "line feed"}, {11, "vertical tab"}, {12, "form feed"}, {13, "carriage return"}, {32, "space"}, {34, "double quote"}, {39, "single quote"}, {45, "hyphen"}, {96, "backtick"}, {8194, "en space"}, {8195, "em space"}, {8211, "en dash"}, {8212, "em dash"}, {8216, "left single quote"}, {8217, "right single quote"}, {8220, "left double quote"}, {8221, "right double quote"}}
	
	set the clipboard to "No Text"
	tell application "System Events"
		set appName to name of first process whose frontmost is true
		if appName is in {"Script Editor", "Script Debugger"} then
			set visible of process appName to false
			set appName to name of first process whose frontmost is true
		end if
		tell process appName to click menu item "Copy" of menu "Edit" of menu bar 1
	end tell
	
	repeat 6 times
		set selectedText to the clipboard
		if selectedText ≠ "No Text" then exit repeat
		delay 0.05
	end repeat
	
	if selectedText = "No Text" then
		errorDialog("A character was not selected. The active application is " & appName & ".")
	else
		set theID to id of (text 1 of selectedText)
		set theDescription to quote & (text 1 of selectedText) & quote
	end if
	
	repeat with aList in characterData
		if (item 1 of aList) = theID then
			set theDescription to (item 2 of aList)
			exit repeat
		end if
	end repeat
	
	set selectedTextCount to (count selectedText)
	activate me
	if selectedTextCount > 1 then
		display dialog "Application: " & appName & linefeed & "Character: " & theDescription & linefeed & "ID: " & theID buttons {"Show All", "OK"} cancel button 2 default button 2 with title "Character ID" with icon note
	else
		display dialog "Application: " & appName & linefeed & "Character: " & theDescription & linefeed & "ID: " & theID buttons {"OK"} cancel button 1 default button 1 with title "Character ID" with icon note
	end if
	
	
	if button returned of result = "Show All" then
		if selectedTextCount > maxSelectionAllowed then errorDialog("The selected string exceeds " & (maxSelectionAllowed as text) & " characters and cannot be displayed.")
		set text item delimiters to space
		set theIDs to (text items of (id of selectedText)) as text
		set text item delimiters to ""
		if selectedTextCount > maxCharactersDisplayed then
			set selectedText to "See selection in Application"
		else
			set selectedText to quote & selectedText & quote
		end if
		display dialog "Application: " & appName & linefeed & "String: " & selectedText & linefeed & "IDs: " & theIDs buttons {"OK"} cancel button 1 default button 1 with title "Character ID" with icon note
	end if
end main

on errorDialog(dialogText)
	display dialog dialogText buttons {"OK"} cancel button 1 default button 1 with title "Character ID" with icon stop
end errorDialog

main()