Skip to content

Instantly share code, notes, and snippets.

@gruber
Last active March 3, 2024 22:01
  • Star 40 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save gruber/eb89728474ba59287df79c054e1097a5 to your computer and use it in GitHub Desktop.
An AppleScript for Safari to move all tabs in the frontmost window, from the current tab to the rightmost (last) tab, to a new window.
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
(*
Original script: John Gruber (https://daringfireball.net/linked/2023/12/05/an-applescript-for-safari-split-tabs-to-new-window)
Much more elegant version: Leon Cowle (https://github.com/leoncowle)
Even more elegant version: https://stackoverflow.com/questions/54066100/applescript-to-split-safari-tabs-into-new-window/54089865#54089865
Worth a warning: "moving" tabs with this script doesn't actually move them like
drag-and-drop does. The tabs "moved" by this script will reload in the new window,
so you'll lose (a) the current scroll position, and, more dangerously, (b) any
text you've entered in a text field.
*)
tell application "Safari"
set original_window to front window
set current_tab_index to index of current tab of original_window
set last_tab_index to index of last tab of original_window
make new document
# Account for pinned tabs; if we assume index 1, we'll close a pinned tab:
set new_blank_tab to index of last tab of front window
move tabs current_tab_index thru last_tab_index of original_window to front window
close tab new_blank_tab of front window
end tell
@leoncowle
Copy link

leoncowle commented Dec 6, 2023

Hey John. Curious for your thoughts on my rework of yours. It uses only a single repeat, and also caters for the scenario where you have pinned tabs, so it won't close the wrong (1st pinned) tab in the new window.

use AppleScript version "2.4" -- Yosemite (10.10) or later

tell application "Safari"
	(*
	`tab` properties:
		index
		name
		source (the full HTML of the page)
		URL
		visible
	*)
	
	set _oldw to window 1
	make new document
	set _neww to window 1
	
	-- save # of tabs in new window (e.g. pinned tabs)
	set _newwcount to count tabs of _neww
	
	-- repeat over relevant tabs in old window, 
	-- create them in new window, and close in old window
	set _tabs to tabs of _oldw
	set _tab_count to count _tabs
	repeat with i from _tab_count to 1 by -1
		set _t to item i of _tabs
		tell _neww to make new tab at after tab _newwcount with properties {URL:URL of _t}
		if visible of _t then
			-- we've reached visible tab in old window
			close _t
			exit repeat
		end if
		close _t
	end repeat
	
	-- Close the blank Start Page tab (which will be the 1st tab after all the pinned tabs)
	tell _neww to close tab _newwcount
end tell

@gruber
Copy link
Author

gruber commented Dec 6, 2023

@leoncowle I love it. More concise, more elegant, much easier to follow. I’ve adopted it (although I expanded a few of your variable names), and added what I hope you consider appropriate credit. Thanks! Let me know if you want the credit changed in anyway, like to point to a different website or something.

I was bothered all along by the fact that my original used more than one loop, and because I don’t use pinned tabs, I always forget to account for them in scripts like this. It just didn’t occur to me to reference the old window in a way other than “window 1”.

@leoncowle
Copy link

Thanks @gruber ! Appreciate the kind words. Credit is perfect. (tiny request: remove the errant 'r' in my last name in your DF post update, it's Cowle, not Crowle). Thanks again.

@VRic-on-github
Copy link

Hey that looks fun, can I play too?

I think we can shave a bit more…

(assuming nothing breaks in newer versions — I'm writing this with macOS 10.11.6 / Safari 11.1.2)

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

tell application "Safari"
	set _old_window to window 1
	set _tabs to tabs of _old_window
	-- remember current tab
	tell _old_window to set _current_tab_index to index of current tab
	
	make new document
	set _new_window to window 1
	-- remember # of tabs in new window (e.g. pinned tabs)
	set _new_window_count to count tabs of _new_window
	
	-- move current tab and those to the right of it to new window
	repeat with _each_tab in reverse of _tabs
		set _this_index to index of _each_tab
		move _each_tab to after tab _new_window_count of _new_window
		if _this_index is _current_tab_index then exit repeat
	end repeat
	
	-- Close the blank Start Page tab (which will be the 1st tab after all the pinned tabs)
	tell _new_window to close tab _new_window_count
end tell

@leoncowle
Copy link

leoncowle commented Dec 6, 2023

Love it, @VRic-on-github! Move instead of create+close (plus some other minor improvements). Nice! (and works perfectly on macOS 13.6.1 and Safari 17.1.2)

@barijaona
Copy link

@VRic-on-github works fine on macOS 14.1.2 too

@VRic-on-github
Copy link

Thanks. I suppose move has added benefits too, although I didn't investigate: when moving a tab by drag-and-drop, the tab is just relocated to another window instead of loading a new one with the same URL, which may or may not result in the same page (especially if the original is days or weeks old, or contains edited text fields…)

@ChristopherA
Copy link

I'm a bit confused, as I have a script that I found that does the same thing, and is a lot smaller. Is it missing something important?

# from https://stackoverflow.com/a/55832291

tell application "Safari"
	set original_window to front window
	set tab_index to index of current tab of original_window
	set tab_limit to index of last tab of original_window
	
	make new document
	move tabs tab_index thru tab_limit of original_window to front window
	close first tab of front window
end tell

@leoncowle
Copy link

That's very elegant, ChristopherA! Here is a slightly improved one, building on your response, which additionally caters for the possibility of using pinned tabs:

tell application "Safari"
	set original_window to front window
	set tab_index to index of current tab of original_window
	set tab_limit to index of last tab of original_window
	
	make new document
	set new_blank_tab to index of last tab of front window
	move tabs tab_index thru tab_limit of original_window to front window
	close tab new_blank_tab of front window
end tell

@gruber
Copy link
Author

gruber commented Mar 1, 2024

Agreed, thanks ChristopherA. I’ll update the main gist to this. So elegant.

For what it’s worth, the Stack Overflow link where you give credit is not the source for this however — but it is a rather interesting thread regarding techniques for finding open tabs that match a string or regex pattern! The actual source for this elegant “move tabs” script is

https://stackoverflow.com/questions/54066100/applescript-to-split-safari-tabs-into-new-window/54089865#54089865

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment