"tab can" by lokate366 is licensed under CC BY-SA 2.0
ETOOMANYTABS#
I have a browser tab problem. I open a lot of tabs in Chrome. I’m not great about closing them. To help me with my tab problem, I use Clutter Free. It prevents duplicate tabs from being opened. This works really well, but I can’t use this extension at $work.
At $work, I’m in an environment where I can only install Chrome extensions which have been approved by the org administrator. I could ask to get a new extension approved. It’s not a particularly onerous process, but I wondered if I could just script something to run on my Mac. That would allow me to solve the problem without a 3rd party Chrome extension.
In the past, I have copy/pasted AppleScript, but I don’t think I’ve ever written any from scratch. Maybe say "You look marvelous"
. That’s probably the extent of it.
I did, however, know that AppleScript can cycle through tabs. So, I came up with a plan to write some AppleScript that could cycle through all of the Chrome tabs on my Mac and close the duplicates. This solution doesn’t prevent duplicates from being opened, but it does close them after the fact and that mostly gets me to the same place.
I came up with the following:
#!/usr/bin/osascript
say "starting tab cleanup"
set urls to {}
tell application "Google Chrome"
activate
repeat with theWindow in every window
set toClose to {}
set tabIndex to 1
repeat with theTab in every tab of theWindow
set tabIsDuplicate to false
repeat with seen in urls
if (seen as string = URL of theTab as string) then
copy tabIndex to the end of toClose
set tabIsDuplicate to true
exit repeat
end if
end repeat
set tabIndex to tabIndex + 1
if tabIsDuplicate is not true then
copy URL of theTab as string to the end of urls
end if
end repeat
set closing to reverse of toClose
repeat with closeIndex in closing
close tab closeIndex of theWindow
end repeat
set numberOfClosed to count of closing
if numberOfClosed > 0 then
say numberOfClosed
say "tabs closed"
end if
end repeat
end tell
say "finished tab cleanup"
This brings Chrome to the forefront and cycles through each open Chrome window. For each window, it cycles through every tab. If the tab’s URL has already been seen, the script stores the tab number in a list of tabs we will need to close. Once all tabs in a window have been checked, we reverse the list of tab numbers that contain duplicate URLs and close them one by one. Then we move on to the next window and continue the process, until we run out of open windows.
You may ask yourself why we need to reverse the list of tab numbers before we close them? We do this because it makes it easier to avoid off-by-one errors. Let’s assume we need to close tabs 3, 5 and 7. Once we close tab 3, tabs 5 and 7 become tabs 4 and 6. We could handle this by decrementing those numbers, but if we just take the list in reverse this will never happen. For instance, with the 3, 5 and 7 scenario, when tab 7 has been closed, tabs 3 and 5 remain in the same position, so there is less state to keep track of.
Caveat Emptor#
The script above will close tabs with extreme prejudice. So, if you’re doing something important in a duplicate tab or you wanted to close the first tab rather than the second, you’re out of luck. This suits my workflow fine, but maybe not yours.
Getting the Script#
You can copy/paste the script directly from this post or download it from my dot files repo. It can be run directly at the command line. You can also run it via the Script Editor
app, which comes with macOS. That’s handy for debugging.
Addendum#
As a satisfied Hammerspoon user, I’ve added this script to my Hammerspoon config. That means I can now run my tab cleanup with a keyboard shortcut. In my case that’s caps lock + a
. I won’t get into Hammerspoon configuration today, but my config file is on GitHub and large parts of it were stolen directly from Mark Fowler. It may be helpful to point out that I’m using Karabiner Elements to map caps lock
to command+control+option+shift
. That config is also on GitHub.