Skip to content

Instantly share code, notes, and snippets.

@harrtho
Last active February 4, 2020 00:21
Show Gist options
  • Save harrtho/52526c70930faa58ccccb5e27e8f7d92 to your computer and use it in GitHub Desktop.
Save harrtho/52526c70930faa58ccccb5e27e8f7d92 to your computer and use it in GitHub Desktop.
(*
Written by hypert.
Based on Sean Long's "Copy Safari Tabs" (http://www.macosxhints.com/article.php?story=20060129175300877),
Mark Hunte's "Save Safari Tabs" (http://www.macosxhints.com/article.php?story=20051121170745971),
and Adam Brin's "Safari Tabs" (http://www.macosxhints.com/article.php?story=20040917211924222).
*)
property NEW_FOLDER_KEY : "n"
property PASTE_KEY : "v"
property CLOSE_TAB_KEY : "w"
property NEXT_TAB_KEY : "}"
property MORE_TABS : 0
property TAB_CHECK : 50
property DEBUG : false
on run {}
tell application "Safari"
activate
set windowName to my GetWindowName()
if DEBUG then display dialog windowName
my give_window_focus(windowName)
-- Get the Bookmarks folder name
set folderName to the text returned of (display dialog "Enter the bookmark folder name" default answer windowName)
-- get urls for tabs; urls is a list which is setup as "pairs" of info, the 1st part of the pair is the address, the 2nd part is the title
set urls to my get_urls_for_tabs(windowName)
-- Adding the bookmark folder doesn't work if the frontmost window/tab is the Bookmarks window
-- Check for it & close it if necessary
my CheckForBookmarksTab()
-- Create the Bookmarks folder
my CreateBookmarkFolder(folderName)
-- Add the URLs for each of the tabs in the Bookmarks folde
my AddBookmarksToFolder(urls)
display dialog "Bookmarks stored in folder '" & folderName & "'" buttons {"OK"} default button "OK"
end tell
end run
on GetWindowName()
tell application "Safari"
-- I prefer to bookmark the tabs in just the front window:
return ((name of window 1) as string)
-- Alternately, you could comment out the above return() and prompt the user to pick a window:
set safari_win_name_list to {}
repeat with i from 1 to number of items in windows
set this_win to item i of windows
if ((name of this_win) as string) is not equal "downloads" then
set end of safari_win_name_list to (name of this_win) as string
end if
end repeat
set tab_source_win to (choose from list safari_win_name_list with title "Choose Safari Window" with prompt "Bookmark all tabs from this window:")
return tab_source_win -- could be "false" if they hit "Cancel"!
end tell
end GetWindowName
on CheckForBookmarksTab()
tell application "Safari"
if (name of window 1) as string is equal to "Bookmarks" then
tell application "System Events"
tell process "Safari"
keystroke CLOSE_TAB_KEY using [command down]
end tell
end tell
end if
end tell
end CheckForBookmarksTab
on CreateBookmarkFolder(folderName)
tell application "System Events"
tell process "Safari"
-- add bookmark folder
keystroke NEW_FOLDER_KEY using [shift down, command down]
keystroke folderName
keystroke return
delay 2
keystroke (ASCII character 9)
delay 1
end tell
end tell
end CreateBookmarkFolder
on AddBookmarksToFolder(urls)
tell application "Safari"
set i to 1
repeat while i is less than number of items in urls
set this_url to item i of urls
set this_title to item (i + 1) of urls
if (this_url is not equal to "bookmarks://") then
set the clipboard to this_url
tell application "System Events"
tell process "Safari"
-- It's possible we might need to add "delay 1" commands before and/or after pasting in this_url
keystroke PASTE_KEY using {command down}
end tell
end tell
set the clipboard to this_title
tell application "System Events"
tell process "Safari"
-- It's possible we might need to add "delay 1" commands before and/or after pasting in this_title
keystroke return
keystroke PASTE_KEY using {command down}
keystroke return
end tell
end tell
end if
set i to i + 2
end repeat
end tell
end AddBookmarksToFolder
on get_urls_for_tabs(window_name)
-- tab_list will contain "pairs" of info, the 1st part of the pair is the address, the 2nd part is the title
set tab_list to {}
tell application "Safari"
-- get number of tabs
set num_tabs to my get_num_tabs(window_name)
-- get current page URL if not tabs and bail
if num_tabs = 0 then
set end of tab_list to URL of document of window named window_name
set end of tab_list to (name of window window_name) as string
else
-- loop thru every tab
if DEBUG then display dialog "Number of tabs: " & num_tabs
set group_num to my get_group_num_for_tabs(window_name)
set loopedAround to false
set tabNum to 0
-- Select 1st tab:
my click_tab(window_name, group_num, 1)
set firstTabAddress to (URL of document of window 1) as string
repeat until loopedAround
set window_name to name of window 1
set address to (URL of document of window window_name) as string
if address is not equal to "" then
if DEBUG then display dialog "Address is " & address
if DEBUG then display dialog "Title is " & (name of window window_name) as string
set end of tab_list to address
set end of tab_list to (name of window window_name) as string
end if
my nextTab()
set tabNum to tabNum + 1
if (tabNum > TAB_CHECK) then
-- That's a LOT of tabs. Check w/ user to make sure we're not in an infinite loop.
display dialog "We've gone through " & TAB_CHECK & " tabs without looping back to the beginning. Keep going?"
end if
-- Checked if we've looped around to the first tab again.
if MORE_TABS = 1 then
-- The "More Tabs" menu was found, indicating that there are more tabs than can be displayed at once.
if tabNum > num_tabs then
set address to (URL of document of window 1) as string
-- If the current tab's address is the same as firstTabAddress, chances are we've looped back to the first tab.
-- Wish I could truly find a way to pick tabs in the "More Tabs" section, or query which tab number is currently
-- selected, then I wouldn't need to compare addresses (and we'd handle all duplicate addresses).
if address is equal to firstTabAddress then
set loopedAround to true
end if
end if
else
-- The "More Tabs" menu was not found, so we can just stop after going thru all the tabs.
if tabNum > num_tabs then
set loopedAround to true
end if
end if
end repeat
end if
end tell
return tab_list
end get_urls_for_tabs
on click_tab(window_name, group_num, button_num)
tell application "System Events"
tell process "Safari"
click button button_num of group group_num of window named window_name
end tell
end tell
end click_tab
on get_num_tabs(window_name)
set tabs to 0
tell application "System Events"
tell process "Safari"
set group_num to my get_group_num_for_tabs(window_name)
if group_num > 0 then
set tabs to (count buttons) of group group_num of window named window_name
set MORE_TABS to (count menu buttons) of group group_num of window named window_name
end if
end tell
end tell
return tabs
end get_num_tabs
on give_window_focus(window_name)
tell application "System Events"
tell process "Safari"
perform action "AXRaise" of window named window_name
end tell
end tell
end give_window_focus
on get_group_num_for_tabs(window_name)
set ret_val to 0
tell application "System Events"
tell process "Safari"
-- Tabs are usually in the second to last group
set group_num to (count groups) of window named window_name
set group_num to group_num - 1
-- But if there are no tabs the second to last group is possibly the bookmark bar
set num_buttons to (count buttons) of group group_num of window named window_name
if num_buttons > 0 then
set help_txt to help of button 1 of group group_num of window named window_name
set bookmark_test to offset of "Show all bookmarks" in help_txt
if bookmark_test > 0 then
--we are in the bookmark group (no tabs)
set ret_val to 0
else
set ret_val to group_num
end if
end if
end tell
end tell
return ret_val
end get_group_num_for_tabs
on nextTab()
tell application "Safari" to activate
tell application "System Events"
tell process "Safari"
--click menu item nextTabMenuItem of menu windowMenu of menu bar 1
keystroke NEXT_TAB_KEY using [command down]
end tell
end tell
end nextTab
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment