color tab support
This commit is contained in:
parent
f206847274
commit
81a8462103
|
@ -11,4 +11,6 @@ Gem::Specification.new do |s|
|
||||||
s.has_rdoc = true
|
s.has_rdoc = true
|
||||||
|
|
||||||
s.add_development_dependency 'rspec', '~> 2.6.0'
|
s.add_development_dependency 'rspec', '~> 2.6.0'
|
||||||
|
s.add_development_dependency 'fakefs'
|
||||||
|
s.add_development_dependency 'mocha'
|
||||||
end
|
end
|
||||||
|
|
|
@ -67,15 +67,18 @@
|
||||||
# first_tab.select # brings first tab back to focus
|
# first_tab.select # brings first tab back to focus
|
||||||
# end
|
# end
|
||||||
|
|
||||||
|
require 'tempfile'
|
||||||
|
|
||||||
# The ItermWindow class models an iTerm terminal window and allows for full control via Ruby commands.
|
# The ItermWindow class models an iTerm terminal window and allows for full control via Ruby commands.
|
||||||
class ItermWindow
|
class ItermWindow
|
||||||
|
attr_reader :tab_color_files
|
||||||
|
|
||||||
# While you can directly use ItermWindow.new, using either ItermWindow.open or
|
# While you can directly use ItermWindow.new, using either ItermWindow.open or
|
||||||
# ItermWindow.current is the preferred method.
|
# ItermWindow.current is the preferred method.
|
||||||
def initialize
|
def initialize
|
||||||
@buffer = []
|
@buffer = []
|
||||||
@tabs = {}
|
@tabs = {}
|
||||||
|
@tab_color_files = []
|
||||||
end
|
end
|
||||||
|
|
||||||
# Creates a new terminal window, runs the block on it
|
# Creates a new terminal window, runs the block on it
|
||||||
|
@ -105,16 +108,18 @@ class ItermWindow
|
||||||
|
|
||||||
# Outputs a single line of Applescript code
|
# Outputs a single line of Applescript code
|
||||||
def output(command)
|
def output(command)
|
||||||
@buffer << command.gsub(/'/, '"')
|
@buffer << command.gsub("'", '"').gsub('\\', '\\\\\\')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def concatenated_buffer
|
||||||
|
@buffer.join("\n")
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# Outputs @buffer to the command line as an osascript function
|
# Outputs @buffer to the command line as an osascript function
|
||||||
def send_output
|
def send_output
|
||||||
buffer_str = @buffer.map {|line| "-e '#{line}'"}.join(' ')
|
shell_out
|
||||||
shell_out "osascript #{buffer_str}"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Initializes the terminal window
|
# Initializes the terminal window
|
||||||
|
@ -137,16 +142,18 @@ class ItermWindow
|
||||||
create_tab_convenience_method(name)
|
create_tab_convenience_method(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def create_tab_convenience_method(name)
|
def create_tab_convenience_method(name)
|
||||||
(class << self; self; end).send(:define_method, name) do
|
(class << self; self; end).send(:define_method, name) do
|
||||||
@tabs[name]
|
@tabs[name]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def shell_out(str)
|
def shell_out
|
||||||
%x{str}
|
Tempfile.open('iterm') do |f|
|
||||||
|
f.print concatenated_buffer
|
||||||
|
f.close
|
||||||
|
system %{osascript #{f.path}}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -194,6 +201,15 @@ class ItermWindow
|
||||||
end
|
end
|
||||||
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
|
# Runs a block on this tab with proper opening and closing statements
|
||||||
def execute_block(&block)
|
def execute_block(&block)
|
||||||
@currently_executing_block = true
|
@currently_executing_block = true
|
||||||
|
@ -203,13 +219,34 @@ class ItermWindow
|
||||||
@currently_executing_block = false
|
@currently_executing_block = false
|
||||||
end
|
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
|
private
|
||||||
|
|
||||||
def output(command)
|
def output(command)
|
||||||
@window.output command
|
@window.output command
|
||||||
end
|
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
|
end
|
|
@ -4,12 +4,13 @@ require 'iterm_window'
|
||||||
describe ItermWindow do
|
describe ItermWindow do
|
||||||
before(:each) do
|
before(:each) do
|
||||||
@window = ItermWindow.new
|
@window = ItermWindow.new
|
||||||
|
Kernel.stubs(:system)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe ".current" do
|
describe ".current" do
|
||||||
it "should instantiate the current window and run the block" do
|
it "should instantiate the current window and run the block" do
|
||||||
ItermWindow.should_receive(:new).and_return(@window)
|
ItermWindow.expects(:new).returns(@window)
|
||||||
@window.should_receive(:run).with(:current)
|
@window.expects(:run).with(:current)
|
||||||
ItermWindow.current do
|
ItermWindow.current do
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -18,8 +19,8 @@ describe ItermWindow do
|
||||||
|
|
||||||
describe ".open" do
|
describe ".open" do
|
||||||
it "should instantiate a new window and run the block" do
|
it "should instantiate a new window and run the block" do
|
||||||
ItermWindow.should_receive(:new).and_return(@window)
|
ItermWindow.expects(:new).returns(@window)
|
||||||
@window.should_receive(:run).with(:new)
|
@window.expects(:run).with(:new)
|
||||||
ItermWindow.open do
|
ItermWindow.open do
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -28,12 +29,25 @@ describe ItermWindow do
|
||||||
|
|
||||||
describe "opening a tab (example 1)" do
|
describe "opening a tab (example 1)" do
|
||||||
before(:each) do
|
before(:each) do
|
||||||
ItermWindow.should_receive(:new).and_return(@window)
|
ItermWindow.expects(:new).returns(@window)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should generate and run the right Applescript" do
|
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'"
|
desired = (<<-CMD).strip
|
||||||
@window.should_receive(:shell_out).with(desired)
|
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
|
ItermWindow.open do
|
||||||
open_tab :my_tab do
|
open_tab :my_tab do
|
||||||
|
@ -41,17 +55,47 @@ describe ItermWindow do
|
||||||
write "mate ./"
|
write "mate ./"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@window.concatenated_buffer.should == desired
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "open multiple tabs (example 2)" do
|
describe "open multiple tabs (example 2)" do
|
||||||
before(:each) do
|
before(:each) do
|
||||||
ItermWindow.should_receive(:new).and_return(@window)
|
ItermWindow.expects(:new).returns(@window)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should generate and run the right Applescript" do
|
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'"
|
desired = (<<-CMD).strip
|
||||||
@window.should_receive(:shell_out).with(desired)
|
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
|
ItermWindow.current do
|
||||||
open_tab :project_dir do
|
open_tab :project_dir do
|
||||||
|
@ -72,17 +116,37 @@ describe ItermWindow do
|
||||||
set_title "MyProject Console"
|
set_title "MyProject Console"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@window.concatenated_buffer.should == desired
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "open tabs using bookmarks (example 3)" do
|
describe "open tabs using bookmarks (example 3)" do
|
||||||
before(:each) do
|
before(:each) do
|
||||||
ItermWindow.should_receive(:new).and_return(@window)
|
ItermWindow.expects(:new).returns(@window)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should generate and run the correct Applescript" do
|
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'"
|
desired = (<<-CMD).strip
|
||||||
@window.should_receive(:shell_out).with(desired)
|
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
|
ItermWindow.current do
|
||||||
open_tab :project_dir do
|
open_tab :project_dir do
|
||||||
|
@ -95,17 +159,38 @@ describe ItermWindow do
|
||||||
|
|
||||||
project_dir.select
|
project_dir.select
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@window.concatenated_buffer.should == desired
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "switching between tabs (example 4)" do
|
describe "switching between tabs (example 4)" do
|
||||||
before(:each) do
|
before(:each) do
|
||||||
ItermWindow.should_receive(:new).and_return(@window)
|
ItermWindow.expects(:new).returns(@window)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should generate and run the correct Applescript" do
|
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'"
|
desired = (<<-CMD).strip
|
||||||
@window.should_receive(:shell_out).with(desired)
|
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
|
ItermWindow.open do
|
||||||
open_tab :first_tab
|
open_tab :first_tab
|
||||||
|
@ -117,6 +202,61 @@ describe ItermWindow do
|
||||||
second_tab.write "echo 'hello there!'"
|
second_tab.write "echo 'hello there!'"
|
||||||
first_tab.select
|
first_tab.select
|
||||||
end
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
RSpec.configure do |c|
|
||||||
|
c.mock_with :mocha
|
||||||
|
end
|
||||||
|
|
Loading…
Reference in New Issue