color tab support

This commit is contained in:
John Bintz 2011-07-02 16:57:31 -04:00
parent f206847274
commit 81a8462103
4 changed files with 210 additions and 27 deletions

View File

@ -11,4 +11,6 @@ Gem::Specification.new do |s|
s.has_rdoc = true
s.add_development_dependency 'rspec', '~> 2.6.0'
s.add_development_dependency 'fakefs'
s.add_development_dependency 'mocha'
end

View File

@ -67,15 +67,18 @@
# first_tab.select # brings first tab back to focus
# end
require 'tempfile'
# The ItermWindow class models an iTerm terminal window and allows for full control via Ruby commands.
class ItermWindow
attr_reader :tab_color_files
# While you can directly use ItermWindow.new, using either ItermWindow.open or
# ItermWindow.current is the preferred method.
def initialize
@buffer = []
@tabs = {}
@tab_color_files = []
end
# Creates a new terminal window, runs the block on it
@ -105,16 +108,18 @@ class ItermWindow
# Outputs a single line of Applescript code
def output(command)
@buffer << command.gsub(/'/, '"')
@buffer << command.gsub("'", '"').gsub('\\', '\\\\\\')
end
def concatenated_buffer
@buffer.join("\n")
end
private
# Outputs @buffer to the command line as an osascript function
def send_output
buffer_str = @buffer.map {|line| "-e '#{line}'"}.join(' ')
shell_out "osascript #{buffer_str}"
shell_out
end
# Initializes the terminal window
@ -137,16 +142,18 @@ class ItermWindow
create_tab_convenience_method(name)
end
private
def create_tab_convenience_method(name)
(class << self; self; end).send(:define_method, name) do
@tabs[name]
end
end
def shell_out(str)
%x{str}
def shell_out
Tempfile.open('iterm') do |f|
f.print concatenated_buffer
f.close
system %{osascript #{f.path}}
end
end
@ -194,6 +201,15 @@ class ItermWindow
end
end
# Sets the title of the tab (ie the text on the iTerm tab itself)
def tab_color(color)
if @currently_executing_block
output "write text 'cat #{file = create_tab_color_file(color)} && rm #{file}'"
else
execute_block { tab_color(color) }
end
end
# Runs a block on this tab with proper opening and closing statements
def execute_block(&block)
@currently_executing_block = true
@ -203,13 +219,34 @@ class ItermWindow
@currently_executing_block = false
end
def self.create_tab_color(color)
raise ArgumentError.new("bad hex color: #{color}") if color.downcase[%r{[^a-f0-9]}] || !([ 3, 6 ].include?(color.length))
%w{red green blue}.zip(color.scan(
(case color.length
when 3
/./
when 6
/../
end)
).collect { |part|
part += part if part.length == 1
part.hex
}).collect do |color, brightness|
"\033]6;1;bg;#{color};brightness;#{brightness}\a"
end.join
end
private
def output(command)
@window.output command
end
def create_tab_color_file(color)
file = Tempfile.open('iterm').path + '.tc'
File.open(file, 'wb') { |f| f.puts self.class.create_tab_color(color) }
@window.tab_color_files << file
file
end
end
end
end

View File

@ -4,12 +4,13 @@ require 'iterm_window'
describe ItermWindow do
before(:each) do
@window = ItermWindow.new
Kernel.stubs(:system)
end
describe ".current" do
it "should instantiate the current window and run the block" do
ItermWindow.should_receive(:new).and_return(@window)
@window.should_receive(:run).with(:current)
ItermWindow.expects(:new).returns(@window)
@window.expects(:run).with(:current)
ItermWindow.current do
end
@ -18,8 +19,8 @@ describe ItermWindow do
describe ".open" do
it "should instantiate a new window and run the block" do
ItermWindow.should_receive(:new).and_return(@window)
@window.should_receive(:run).with(:new)
ItermWindow.expects(:new).returns(@window)
@window.expects(:run).with(:new)
ItermWindow.open do
end
@ -28,12 +29,25 @@ describe ItermWindow do
describe "opening a tab (example 1)" do
before(:each) do
ItermWindow.should_receive(:new).and_return(@window)
ItermWindow.expects(:new).returns(@window)
end
it "should generate and run the right Applescript" do
desired = "osascript -e 'tell application \"iTerm\"' -e 'activate' -e 'set myterm to (make new terminal)' -e 'tell myterm' -e 'launch session \"Default Session\"' -e 'set my_tab_tty to the tty of the last session' -e 'tell session id my_tab_tty' -e 'write text \"cd ~/projects/my_project/trunk\"' -e 'write text \"mate ./\"' -e 'end tell' -e 'end tell' -e 'end tell'"
@window.should_receive(:shell_out).with(desired)
desired = (<<-CMD).strip
tell application "iTerm"
activate
set myterm to (make new terminal)
tell myterm
launch session "Default Session"
set my_tab_tty to the tty of the last session
tell session id my_tab_tty
write text \"cd ~/projects/my_project/trunk\"
write text \"mate ./\"
end tell
end tell
end tell
CMD
@window.expects(:shell_out)
ItermWindow.open do
open_tab :my_tab do
@ -41,17 +55,47 @@ describe ItermWindow do
write "mate ./"
end
end
@window.concatenated_buffer.should == desired
end
end
describe "open multiple tabs (example 2)" do
before(:each) do
ItermWindow.should_receive(:new).and_return(@window)
ItermWindow.expects(:new).returns(@window)
end
it "should generate and run the right Applescript" do
desired = "osascript -e 'tell application \"iTerm\"' -e 'activate' -e 'set myterm to first terminal' -e 'tell myterm' -e 'launch session \"Default Session\"' -e 'set project_dir_tty to the tty of the last session' -e 'tell session id project_dir_tty' -e 'write text \"cd ~/projects/my_project/trunk\"' -e 'write text \"mate ./\"' -e 'set name to \"MyProject Dir\"' -e 'end tell' -e 'launch session \"Default Session\"' -e 'set server_tty to the tty of the last session' -e 'tell session id server_tty' -e 'write text \"cd ~/projects/my_project/trunk\"' -e 'write text \"script/server -p 3005\"' -e 'set name to \"MyProject Server\"' -e 'end tell' -e 'launch session \"Default Session\"' -e 'set console_tty to the tty of the last session' -e 'tell session id console_tty' -e 'write text \"cd ~/projects/my_project/trunk\"' -e 'write text \"script/console\"' -e 'set name to \"MyProject Console\"' -e 'end tell' -e 'end tell' -e 'end tell'"
@window.should_receive(:shell_out).with(desired)
desired = (<<-CMD).strip
tell application "iTerm"
activate
set myterm to first terminal
tell myterm
launch session "Default Session"
set project_dir_tty to the tty of the last session
tell session id project_dir_tty
write text "cd ~/projects/my_project/trunk"
write text "mate ./"
set name to "MyProject Dir"
end tell
launch session "Default Session"
set server_tty to the tty of the last session
tell session id server_tty
write text "cd ~/projects/my_project/trunk"
write text "script/server -p 3005"
set name to "MyProject Server"
end tell
launch session "Default Session"
set console_tty to the tty of the last session
tell session id console_tty
write text "cd ~/projects/my_project/trunk"
write text "script/console"
set name to "MyProject Console"
end tell
end tell
end tell
CMD
@window.expects(:shell_out)
ItermWindow.current do
open_tab :project_dir do
@ -72,17 +116,37 @@ describe ItermWindow do
set_title "MyProject Console"
end
end
@window.concatenated_buffer.should == desired
end
end
describe "open tabs using bookmarks (example 3)" do
before(:each) do
ItermWindow.should_receive(:new).and_return(@window)
ItermWindow.expects(:new).returns(@window)
end
it "should generate and run the correct Applescript" do
desired = "osascript -e 'tell application \"iTerm\"' -e 'activate' -e 'set myterm to first terminal' -e 'tell myterm' -e 'launch session \"Default Session\"' -e 'set project_dir_tty to the tty of the last session' -e 'tell session id project_dir_tty' -e 'write text \"cd ~/projects/my_project/trunk\"' -e 'write text \"mate ./\"' -e 'end tell' -e 'launch session \"MyProject Server\"' -e 'set server_tty to the tty of the last session' -e 'launch session \"MyProject Console\"' -e 'set console_tty to the tty of the last session' -e 'select session id project_dir_tty' -e 'end tell' -e 'end tell'"
@window.should_receive(:shell_out).with(desired)
desired = (<<-CMD).strip
tell application "iTerm"
activate
set myterm to first terminal
tell myterm
launch session "Default Session"
set project_dir_tty to the tty of the last session
tell session id project_dir_tty
write text "cd ~/projects/my_project/trunk"
write text "mate ./"
end tell
launch session "MyProject Server"
set server_tty to the tty of the last session
launch session "MyProject Console"
set console_tty to the tty of the last session
select session id project_dir_tty
end tell
end tell
CMD
@window.stubs(:shell_out)
ItermWindow.current do
open_tab :project_dir do
@ -95,17 +159,38 @@ describe ItermWindow do
project_dir.select
end
@window.concatenated_buffer.should == desired
end
end
describe "switching between tabs (example 4)" do
before(:each) do
ItermWindow.should_receive(:new).and_return(@window)
ItermWindow.expects(:new).returns(@window)
end
it "should generate and run the correct Applescript" do
desired = "osascript -e 'tell application \"iTerm\"' -e 'activate' -e 'set myterm to (make new terminal)' -e 'tell myterm' -e 'launch session \"Default Session\"' -e 'set first_tab_tty to the tty of the last session' -e 'launch session \"Default Session\"' -e 'set second_tab_tty to the tty of the last session' -e 'tell session id first_tab_tty' -e 'write text \"cd ~/projects\"' -e 'write text \"ls\"' -e 'end tell' -e 'tell session id second_tab_tty' -e 'write text \"echo \"hello there!\"\"' -e 'end tell' -e 'select session id first_tab_tty' -e 'end tell' -e 'end tell'"
@window.should_receive(:shell_out).with(desired)
desired = (<<-CMD).strip
tell application "iTerm"
activate
set myterm to (make new terminal)
tell myterm
launch session "Default Session"
set first_tab_tty to the tty of the last session
launch session "Default Session"
set second_tab_tty to the tty of the last session
tell session id first_tab_tty
write text "cd ~/projects"
write text "ls"
end tell
tell session id second_tab_tty
write text "echo "hello there!""
end tell
select session id first_tab_tty
end tell
end tell
CMD
@window.expects(:shell_out)
ItermWindow.open do
open_tab :first_tab
@ -117,6 +202,61 @@ describe ItermWindow do
second_tab.write "echo 'hello there!'"
first_tab.select
end
@window.concatenated_buffer.should == desired
end
end
describe 'tab color' do
before(:each) do
ItermWindow.expects(:new).returns(@window)
end
it "should generate and run the correct Applescript" do
@window.expects(:shell_out)
ItermWindow::Tab.any_instance.expects(:create_tab_color_file).with("FF00AA")
ItermWindow.open do
open_tab :first_tab do
tab_color "FF00AA"
end
end
end
end
describe ".create_tab_color" do
subject { ItermWindow::Tab.create_tab_color(color) }
context 'bad hex color' do
[ "whatever", "F00F" ].each do |bad|
context bad do
let(:color) { bad }
it 'should raise an exception on bad hex color' do
expect { subject }.to raise_error(ArgumentError, /bad hex color/)
end
end
end
end
context 'long hex color' do
let(:color) { "FF00AA" }
it 'should create an escape sequence to execute to change a tab color' do
subject.should match(/red;brightness;255/)
subject.should match(/green;brightness;0/)
subject.should match(/blue;brightness;170/)
end
end
context 'short hex color' do
let(:color) { "F0A" }
it 'should create an escape sequence to execute to change a tab color' do
subject.should match(/red;brightness;255/)
subject.should match(/green;brightness;0/)
subject.should match(/blue;brightness;170/)
end
end
end
end

View File

@ -0,0 +1,4 @@
RSpec.configure do |c|
c.mock_with :mocha
end