How to duplicate an iTerm tab using AppleScript

The terminal is my number one programming tool. And, as such, I need it to be as much ‘out of my way’ as possible, so that using the terminal doesn’t make me waste time. And wasting time is exactly what it forces me to do when I have to open a new tab in the same directory as an already existing tab. Whether you do this

  • by browsing the disk until finding the folder, then creating a new tab, writing cd and dragging the path of the directory; or
  • by browsing the file hierarchy with Quicksilver and then triggering a Quicksilver action to open the folder in iTerm;

or whatever other way you do this, it’s definitely a time waste.

Adding a new keyboard shortcut to iTerm 2

Many applications have a ⌘ D shortcut that allows you to duplicate whatever document the application works with. Why doesn’t a terminal emulator have that shortcut to duplicate a terminal tab? iTerm 2 certainly doesn’t have one, but it does have a preference panel where you can add new keyboard shortcuts:

To add a new global shortcut, just click on the + button. This will open the shortcut addition dialog, where you’ll enter the keyboard shortcut (⌘ D), the action to trigger (Send text), and the command to be sent to the terminal (duplicate-iterm-tab) when the shortcut is triggered:

Notice that the command duplicate-iterm-tab is to be executed when sent to the terminal, so a line feed must be entered at the end. Since pressing ↩ in the dialog will apply changes, to enter a new line you must press ⌥ ↩ instead.

Finally, click OK to create the new shortcut and then you’ll see the new shortcut in the Keys preference panel:

An AppleScript that duplicates the iTerm tab in use

The following AppleScript code should be written to the Duplicate iTerm tab.scpt file, and will get the working directory of the current iTerm tab and create a new tab, changing to that very same directory, and setting the same tab title (thus duplicating the tab you’ve selected before pressing ⌘ D):

-- Duplicate iTerm tab.scpt
tell application "iTerm"
	tell the current terminal
		tell the current session
			set the_name to get name
			set tty_name to do shell script "basename " & (get tty)
			set working_dir to do shell script "pwd-tty " & tty_name
		end tell

		launch session "Default Session"
		tell the last session
			set name to the_name
			write text "cd '" & working_dir & "'"
		end tell
	end tell
end tell

Necessary files for the shortcut to work

For the keyboard shortcut to work from iTerm 2, the Duplicate iTerm tab.scpt file must be placed in some directory of your choice (I’ve chosen ~/shell-config/osx-automation/Duplicate iTerm tab.scpt), and the following files are needed alongside:

  • duplicate-iterm-tab, the shell script that will be run by iTerm 2 when the keyboard shortcut is triggered, and that will execute the AppleScript
  • pwd-tty, a shell script used by the AppleScript to find out the current working directory of the TTY whose name is passed as the first command line argument

Both shell scripts must be in the PATH. I’ll keep them in ~/shell-config/bin, since files placed in there are by default in the PATH (according to how I’ve set up my Bash configuration). If you don’t want to add them to the PATH, you can just change the AppleScript code, writing the absolute path to each script instead.

The file duplicate-iterm-tab has the following content:

#!/bin/sh
#
# Runs the 'Duplicate iTerm tab' AppleScript, enabling iTerm 2 to run this AppleScript when a
# given keyboard shortcut is triggered.
osascript '~/shell-config/osx-automation/Duplicate iTerm tab.scpt'

Please note that you must change the path of the AppleScript to whatever directory you’ve placed it into.

The file pwd-tty has the following content:

#!/bin/sh
#
# Finds out the current working directory of the TTY whose name is passed as the first command
# line argument.
#
# Based on http://superuser.com/questions/220679/how-to-get-tty-shell-working-directory

TTY=$1
PID=`ps -f | grep $TTY | head -n 1 | awk '{ print $2; }'`
lsof -a -d cwd -F n -p $PID | egrep -v 'p[0-9]+' | awk '{ sub(/^n/, ""); print; }'

To finish setting all up, you should give both shell scripts execution permissions with chmod +x.

Useful links

Advertisements

Open Quicksilver selection in new iTerm window / tab

I’m not very happy with the iTerm plugin for Quicksilver. It does provide an action for opening Quicksilver’s current selection (i.e. an alias to a directory) in iTerm, but it isn’t very fine tuned, actually.

What it does is just open current selection into a new tab in the first opened iTerm window, which is an unwanted behavior in the 99.999999% of the occasions. The most handy behavior would be that the Quicksilver action opened current selection either in a new window (if there are no iTerm windows in your current Space) or in a new tab in the frontmost iTerm window of the current Space (if there are iTerm windows in your current Space).

Writing the scripts

Given that this has bothered me since the very first time I used this Quicksilver action and that I’m surprisingly keen on hacking a bit, I’ve taken courage and started researching AppleScript in the net. After taking a quick look at some introductory material and taking some inspiration, and making some mistakes, I finally came up to this code with help of this “new tab in iTerm” example:

For opening Quicksilver’s selection (must be a directory, not a file) in a new iTerm window in current Space:

-- File: Open in new iTerm window.scpt

tell application "Quicksilver"
	set folder_path to POSIX path of (selection as text)
end tell

tell application "iTerm"
	activate
	set t to (make new terminal)
	tell t -- this creates a new window, unlike tell current terminal
		launch session "Default Session"
		tell last session
			write text "cd '" & folder_path & "'"
			set name to do shell script "basename '" & folder_path & "'"
		end tell
	end tell
end tell

For opening Quicksilver’s selection (must be a directory, not a file) in a new tab in the last iTerm window in current Space:

-- File: Open in new iTerm tab.scpt

tell application "Quicksilver"
	set folder_path to POSIX path of (selection as text)
end tell

tell application "iTerm"
	activate
	tell the current terminal
		activate current session
		launch session "Default Session"
		tell last session
			write text "cd '" & folder_path & "'"
			set name to do shell script "basename '" & folder_path & "'"
		end tell
	end tell
end tell

Adapting the scripts for making Quicksilver actions

The two previous AppleScript’s work perfectly outside of Quicksilver (e.g. when running them within AppleScript Editor). However, if you place these scripts in the Quikcsilver Actions’ directory and try to run them, they won’t work. To make them work, you must make some slight modifications (take a look at Quicksilver’s AppleScript documentation; my inspiration was the “Paste file path” action).

For opening Quicksilver’s selection (must be a directory, not a file) in a new iTerm window in current Space:

-- File: Open in new iTerm window.scpt

using terms from application "Quicksilver"
	on open folder
		set folder_path to POSIX path of folder

		tell application "iTerm"
			activate
			set t to (make new terminal)
			tell t -- this creates a new window, unlike tell current terminal
				launch session "Default Session"
				tell last session
					write text "cd '" & folder_path & "'"
					set name to do shell script "basename '" & folder_path & "'"
				end tell
			end tell
		end tell
	end open
end using terms from

For opening Quicksilver’s selection (must be a directory, not a file) in a new tab in the last iTerm window in current Space:

-- File: Open in new iTerm tab.scpt

using terms from application "Quicksilver"
	on open folder
		set folder_path to POSIX path of folder

		tell application "iTerm"
			activate
			tell the current terminal
				activate current session
				launch session "Default Session"
				tell last session
					write text "cd '" & folder_path & "'"
					set name to do shell script "basename '" & folder_path & "'"
				end tell
			end tell
		end tell
	end open
end using terms from

For Quicksilver to recognize these actions, you must place both AppleScript files into ~/Library/Application Support/Quicksilver/Actions/ and restart Quicksilver. After doing that, you can just fire up Quicksilver, select an alias to a directory in the first tab, and then select the wanted action in the action tab (second tab).

やった! 🙂

Useful links