AppleScript replacement for the Omnikey extension in Safari 13

Omnikey is a Safari extension which allows to search websites from the address field by typing a token and a query.

For example to search for Apple on Wikipedia type we apple

Unfortunately Apple doesn’t support .safariextz extensions in Safari 13 anymore.

This is a simple AppleScript replacement. It gathers the text from the address field and builds the search URL from a list of token / url pairs.

Customizing the shortcuts list is very easy. Add lines with token and url, the query is represented by the {search} placeholder

If you have a backup of your Omnikey shortcuts in JSON format, replace the enclosing square brackets [] with braces {} and remove the dictionary keys in a text editor with find & replace.

You can run the script wrapped in an Automator Service with a keyword shortcut or with third party tools like Keyboard Maestro, FastScripts, Alfred and others.

use AppleScript version "2.5"
use framework "Foundation"
use scripting additions

property |⌘| : a reference to current application
property shortcuts : {{"ama", "https://www.amazon.com/s/?link_code=wsw&_encoding=UTF-8&search-alias=aps&field-keywords={search}&Submit.x=0&Submit.y=0&Submit=Go"}, ¬
	{"imdb", "https://www.imdb.com/find?q={search}&s=all"}, ¬
	{"maps", "https://maps.google.com/maps?hl=en&authuser=0&q={search}&ie=UTF-8"}, ¬
	{"we", "https://en.wikipedia.org/w/index.php?title=Special:Search&search={search}"}, ¬
	{"yt", "https://www.youtube.com/results?search_query={search}"}}

activate application "Safari"
tell application "System Events"
	tell process "Safari"
		try -- Safari is in full screen mode
			set theGroup to 1st group of toolbar 1 of group 1 of window 1 whose class of text field 1 is text field
		on error -- Safari is in standard mode
			set theGroup to 1st group of toolbar 1 of window 1 whose class of text field 1 is text field
		end try
		set textValue to value of text field 1 of theGroup
	end tell
end tell

set spaceOffset to offset of space in textValue
if spaceOffset = 0 then return
set token to text 1 thru (spaceOffset - 1) of textValue
set query to text (spaceOffset + 1) thru -1 of textValue

set nsQuery to |⌘|'s NSString's stringWithString:query
set allowedPathCharacterSet to |⌘|'s NSCharacterSet's URLPathAllowedCharacterSet()
set encodedQuery to nsQuery's stringByAddingPercentEncodingWithAllowedCharacters:allowedPathCharacterSet
repeat with aShortcut in shortcuts
	set {_token, _url} to contents of aShortcut
	if _token is token then
		set queryURL to (|⌘|'s NSString's stringWithString:_url)
		set searchURL to (queryURL's stringByReplacingOccurrencesOfString:"{search}" withString:encodedQuery)
		tell application "Safari" to set URL of current tab of window 1 to (searchURL as text)
		exit repeat
	end if
end repeat

I’m getting the error "Can’t get window 1 of process “Safari.” Invalid index.

Any ideas? Running 10.13.6

The script assumes that there is an open Safari window because you must be able to type into the address field.

Here the same error with 10.13.6

With 10.14.6 it runs perfect.

Safari’s GUI structure no doubt depends on its version, the OS version, and/or how the user’s set it up. Another way to get the address field contents would be to select and copy them, which should be fairly structure-independent. Try replacing this section …

activate application "Safari"
tell application "System Events"
	tell process "Safari"
		try -- Safari is in full screen mode
			set theGroup to 1st group of toolbar 1 of group 1 of window 1 whose class of text field 1 is text field
		on error -- Safari is in standard mode
			set theGroup to 1st group of toolbar 1 of window 1 whose class of text field 1 is text field
		end try
		set textValue to value of text field 1 of theGroup
	end tell
end tell

… with this:

-- Get the existing clipboard contents.
set oldClipboard to (the clipboard)
-- Ensure Safari's the frontmost process.
activate application "Safari"
tell application "System Events"
	set frontmost of application process "Safari" to true
	-- Select and copy the address field contents.
	keystroke "lc" using {command down}
end tell
-- Keep getting the clipboard contents until they change or haven't changed after a certain time. (Adjust as required.)
repeat 2 times
	set textValue to (the clipboard)
	if (textValue is not oldClipboard) then exit repeat
	delay 0.5
end repeat
-- Restore the old contents. (Optional.)
set the clipboard to oldClipboard

Great!
This is how it works.

Sad that apple doesn’t build something like that on its own.

Many thanks!!!