ebi
ebi

Reputation: 118

Change active finder tab

Is it possible to change the active Finder tab over applescript? I would like to create scripts to change the tabs with cmd-[0-9].

For Safari there is the possibility to set current tab to tab2 but that seems to be not the case with Finder.

Upvotes: 2

Views: 874

Answers (2)

user12638282
user12638282

Reputation: 109

Updated version for macOS Sonoma (14.0):

tell application "System Events"
    tell application process "Finder"
        tell front window
            tell tab group 1
                tell first radio button
                    perform action "AXPress"
                end tell
            end tell
        end tell
    end tell
end tell

JXA version:

"use strict";

function run() {
  const SystemEvents = Application("System Events");
  const Finder = SystemEvents.applicationProcesses.byName("Finder");
  const tabIndex = ObjC.unwrap(
    $.NSProcessInfo.processInfo.arguments.objectAtIndex(4)
  );
  const mainWindow = Finder.windows().find(x =>
    x.attributes.byName("AXMain").value()
  );
  mainWindow.tabGroups
    .at(0)
    .radioButtons.at(tabIndex)
    .actions.byName("AXPress")
    .perform();
}

JXA version can be invoked via osascript -l JavaScript /path/to/script.js [0-9].

To create a keyboard shortcut for Command-[0-9], you can use Hammerspoon:

local function activateFinderTab(tab)
  -- hs.task is used instead of hs.osascript to avoid memory leaks. See:
  -- https://github.com/Hammerspoon/hammerspoon/issues/1980#issuecomment-450214714
  hs.task
    .new("/usr/bin/osascript", nil, {
      "-l",
      "JavaScript",
      "/path/to/activate_finder_tab.js",
      tab,
    })
    :start()
end

local hotkeys = {}
for i = 1, 9 do
  local key = tostring(i)
  hotkeys[#hotkeys + 1] = hs.hotkey.new("cmd", key, function()
    activateFinderTab(key)
  end)
end

local hotkeyEventTable = {
  [hs.application.watcher.activated] = function(bindings)
    for i = 1, #bindings do
      bindings[i]:enable()
    end
  end,

  [hs.application.watcher.deactivated] = function(bindings)
    for i = 1, #bindings do
      bindings[i]:disable()
    end
  end,
}

appwatcher = hs.application.watcher
  .new(function(appName, event, app)
    if app:bundleID() == "com.apple.finder" then
      local fn = hotkeyEventTable[event]
      if fn then fn(hotkeys) end
    end
  end)
  :start()

Alternatively, you can setup the keybinding with Automator:

  1. Open Automator.

  2. Create a new document with the type Quick Action.

  3. Under Workflow receives, select "no input" and for application choose "Finder".

  4. In the lefthand pane, search for "Run JavaScript" (or "Run AppleScript" to use the other version) and drag that action to the righthand pane.

  5. Copy-paste the above script, but hardcode tabIndex to 1:

const tabIndex = 1;
  1. Save as "Activate Finder Tab 1".

  2. Open System Settings > Keyboard > Keyboard Shortcuts… > Services.

Under General, there should be the Activate Finder Tab 1 service listed. Double-click on none to assign a keyboard shortcut. You can also set this on the command line via:

defaults write com.apple.finder NSUserKeyEquivalents -dict-add "Activate Finder Tab 1" "@1"
  1. Repeat these steps for tabs 2-9.

Upvotes: 0

fartheraway
fartheraway

Reputation: 383

Yes.

Actions supported by each app is defined in applescript Dictionary. Just because something work in one built-in app doesn't mean it will carry over to another.

Solution 1 is to call System Event and invoke keystroke for Previous Tab or Next Tab.

Solution 2: since you want to refer to tabs by its postion, use UI scripting. This way the scripting can switch to any tab that fits a certain criteria.

tell application "System Events" to tell process "Finder" to tell window 1 to tell radio button 1 to click

Upvotes: 3

Related Questions