teamocil 0.3.7 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +8 -3
- data/examples/simple-four-splits.yml +1 -0
- data/lib/teamocil.rb +2 -1
- data/lib/teamocil/cli.rb +6 -1
- data/lib/teamocil/error.rb +6 -0
- data/lib/teamocil/layout/session.rb +2 -3
- data/lib/teamocil/layout/split.rb +4 -2
- data/lib/teamocil/layout/window.rb +7 -3
- data/spec/fixtures/layouts.yml +8 -0
- data/spec/layout_spec.rb +43 -1
- metadata +5 -4
data/README.md
CHANGED
@@ -51,6 +51,7 @@ If you are not using a top-level `session` key, then the first key of your layou
|
|
51
51
|
* `name` (the name that will appear in `tmux` statusbar)
|
52
52
|
* `root` (the directory in which every split will be created)
|
53
53
|
* `filters` (a hash of `before` and `after` commands to run for each split)
|
54
|
+
* `clear` (whether or not to prepend a `clear` command before the `before` filters list)
|
54
55
|
* `splits` (an array of split items)
|
55
56
|
* `options` (a hash of tmux options, see `man tmux` for a list)
|
56
57
|
|
@@ -59,6 +60,7 @@ If you are not using a top-level `session` key, then the first key of your layou
|
|
59
60
|
```yaml
|
60
61
|
windows:
|
61
62
|
- name: "my-first-window"
|
63
|
+
clear: true
|
62
64
|
options:
|
63
65
|
synchronize-panes: true
|
64
66
|
root: "~/Projects/foo-www"
|
@@ -87,7 +89,8 @@ Every window must define an array of splits that will be created within it. A ve
|
|
87
89
|
* `cmd` (the commands to initially execute in the split)
|
88
90
|
* `width` (the split width, in percentage)
|
89
91
|
* `height` (the split width, in percentage)
|
90
|
-
* `target` (the split to set focus on
|
92
|
+
* `target` (the split to set focus on before creating the current one)
|
93
|
+
* `focus` (the split to set focus on after initializing all the splits for a window)
|
91
94
|
|
92
95
|
#### Example
|
93
96
|
|
@@ -101,6 +104,7 @@ windows:
|
|
101
104
|
splits:
|
102
105
|
- cmd: "git status"
|
103
106
|
- cmd: "bundle exec rails server --port 4000"
|
107
|
+
focus: true
|
104
108
|
width: 50
|
105
109
|
- cmd:
|
106
110
|
- "sudo service memcached start"
|
@@ -185,9 +189,9 @@ To get autocompletion when typing `teamocil <Tab>` in a zsh session, add this li
|
|
185
189
|
compctl -g '~/.teamocil/*(:t:r)' teamocil
|
186
190
|
```
|
187
191
|
|
188
|
-
### ERB
|
192
|
+
### ERB support
|
189
193
|
|
190
|
-
You can use ERB in your
|
194
|
+
You can use ERB in your layouts. For example, you can use an environment variable in a layout like so:
|
191
195
|
|
192
196
|
```yaml
|
193
197
|
windows:
|
@@ -208,6 +212,7 @@ Feel free to contribute and submit issues/pull requests [on GitHub](https://gith
|
|
208
212
|
|
209
213
|
* Samuel Garneau ([garno](https://github.com/garno))
|
210
214
|
* Jimmy Bourassa ([jbourassa](https://github.com/jbourassa))
|
215
|
+
* Brandon Dimcheff ([bdimcheff](https://github.com/bdimcheff))
|
211
216
|
|
212
217
|
Take a look at the `spec` folder before you do, and make sure `bundle exec rake spec` passes after your modifications :)
|
213
218
|
|
data/lib/teamocil.rb
CHANGED
data/lib/teamocil/cli.rb
CHANGED
@@ -36,7 +36,12 @@ module Teamocil
|
|
36
36
|
yaml = ERB.new(File.read(file)).result
|
37
37
|
|
38
38
|
@layout = Teamocil::Layout.new(YAML.load(yaml), @options)
|
39
|
-
|
39
|
+
|
40
|
+
begin
|
41
|
+
@layout.compile!
|
42
|
+
rescue Teamocil::Error::LayoutError => e
|
43
|
+
bail e.message
|
44
|
+
end
|
40
45
|
@layout.execute_commands(@layout.generate_commands)
|
41
46
|
end
|
42
47
|
end # }}}
|
@@ -10,7 +10,8 @@ module Teamocil
|
|
10
10
|
# @param options [Hash] the options, mostly passed by the CLI
|
11
11
|
# @param attrs [Hash] the session data from the layout file
|
12
12
|
def initialize(options, attrs={}) # {{{
|
13
|
-
|
13
|
+
raise Teamocil::Error::LayoutError.new("You must specify a `windows` or `session` key for your layout.") unless attrs["windows"]
|
14
|
+
@name = attrs["name"] || "teamocil-session"
|
14
15
|
@windows = attrs["windows"].each_with_index.map { |window, window_index| Window.new(self, window_index, window) }
|
15
16
|
@options = options
|
16
17
|
end # }}}
|
@@ -22,8 +23,6 @@ module Teamocil
|
|
22
23
|
commands = []
|
23
24
|
commands << "tmux rename-session \"#{@name}\"" unless @name.nil?
|
24
25
|
commands << @windows.map(&:generate_commands)
|
25
|
-
commands << "tmux select-pane -t 0"
|
26
|
-
commands
|
27
26
|
end # }}}
|
28
27
|
|
29
28
|
end
|
@@ -3,7 +3,7 @@ module Teamocil
|
|
3
3
|
|
4
4
|
# This class represents a split within a tmux window
|
5
5
|
class Split
|
6
|
-
attr_reader :width, :height, :cmd, :index, :target
|
6
|
+
attr_reader :width, :height, :cmd, :index, :target, :focus
|
7
7
|
|
8
8
|
# Initialize a new tmux split
|
9
9
|
#
|
@@ -11,10 +11,12 @@ module Teamocil
|
|
11
11
|
# @param index [Fixnnum] the split index
|
12
12
|
# @param attrs [Hash] the split data from the layout file
|
13
13
|
def initialize(window, index, attrs={}) # {{{
|
14
|
+
raise Teamocil::Error::LayoutError.new("You cannot have empty splits") if attrs.nil?
|
14
15
|
@height = attrs["height"]
|
15
16
|
@width = attrs["width"]
|
16
17
|
@cmd = attrs["cmd"]
|
17
18
|
@target = attrs["target"]
|
19
|
+
@focus = attrs["focus"] || false
|
18
20
|
|
19
21
|
@window = window
|
20
22
|
@index = index
|
@@ -41,7 +43,7 @@ module Teamocil
|
|
41
43
|
end
|
42
44
|
|
43
45
|
# Wrap all commands around filters
|
44
|
-
@cmd = [@window.filters["before"]] + [@cmd] + [@window.filters["after"]]
|
46
|
+
@cmd = [@window.filters["before"]] + [@window.clear] + [@cmd] + [@window.filters["after"]]
|
45
47
|
|
46
48
|
# If a `root` key exist, start each split in this directory
|
47
49
|
@cmd.unshift "cd \"#{@window.root}\"" unless @window.root.nil?
|
@@ -3,7 +3,7 @@ module Teamocil
|
|
3
3
|
|
4
4
|
# This class represents a window within tmux
|
5
5
|
class Window
|
6
|
-
attr_reader :filters, :root, :splits, :options, :index, :name
|
6
|
+
attr_reader :filters, :root, :splits, :options, :index, :name, :clear
|
7
7
|
|
8
8
|
# Initialize a new tmux window
|
9
9
|
#
|
@@ -11,11 +11,13 @@ module Teamocil
|
|
11
11
|
# @param index [Fixnnum] the window index
|
12
12
|
# @param attrs [Hash] the window data from the layout file
|
13
13
|
def initialize(session, index, attrs={}) # {{{
|
14
|
-
@name = attrs["name"]
|
15
|
-
@root = attrs["root"]
|
14
|
+
@name = attrs["name"] || "teamocil-window-#{index+1}"
|
15
|
+
@root = attrs["root"] || "."
|
16
|
+
@clear = attrs["clear"] == true ? "clear" : nil
|
16
17
|
@options = attrs["options"] || {}
|
17
18
|
|
18
19
|
@splits = attrs["splits"] || []
|
20
|
+
raise Teamocil::Error::LayoutError.new("You must specify a `splits` key for every window.") if @splits.empty?
|
19
21
|
@splits = @splits.each_with_index.map { |split, split_index| Split.new(self, split_index, split) }
|
20
22
|
|
21
23
|
@filters = attrs["filters"] || {}
|
@@ -46,6 +48,8 @@ module Teamocil
|
|
46
48
|
commands << "tmux set-window-option #{option} #{value}"
|
47
49
|
end
|
48
50
|
|
51
|
+
commands << "tmux select-pane -t #{@splits.map(&:focus).index(true) || 0}"
|
52
|
+
|
49
53
|
commands
|
50
54
|
end # }}}
|
51
55
|
|
data/spec/fixtures/layouts.yml
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
two-windows:
|
3
3
|
windows:
|
4
4
|
- name: "foo"
|
5
|
+
clear: true
|
5
6
|
root: "/foo"
|
6
7
|
splits:
|
7
8
|
- cmd: "echo 'foo'"
|
@@ -15,6 +16,7 @@ two-windows:
|
|
15
16
|
- "echo 'bar in an array'"
|
16
17
|
target: bottom-right
|
17
18
|
- cmd: "echo 'bar again'"
|
19
|
+
focus: true
|
18
20
|
width: 50
|
19
21
|
|
20
22
|
# Simple two windows layout with filters
|
@@ -39,5 +41,11 @@ three-windows-within-a-session:
|
|
39
41
|
name: "my awesome session"
|
40
42
|
windows:
|
41
43
|
- name: "first window"
|
44
|
+
splits:
|
45
|
+
- cmd: "echo 'foo'"
|
42
46
|
- name: "second window"
|
47
|
+
splits:
|
48
|
+
- cmd: "echo 'foo'"
|
43
49
|
- name: "third window"
|
50
|
+
splits:
|
51
|
+
- cmd: "echo 'foo'"
|
data/spec/layout_spec.rb
CHANGED
@@ -8,6 +8,23 @@ describe Teamocil::Layout do
|
|
8
8
|
@layout = Teamocil::Layout.new(layouts["two-windows"], {})
|
9
9
|
end # }}}
|
10
10
|
|
11
|
+
describe "handles bad layouts" do # {{{
|
12
|
+
it "does not compile without windows" do # {{{
|
13
|
+
@layout = Teamocil::Layout.new({ "name" => "foo" }, {})
|
14
|
+
lambda { @layout.compile! }.should raise_error Teamocil::Error::LayoutError
|
15
|
+
end # }}}
|
16
|
+
|
17
|
+
it "does not compile without splits" do # {{{
|
18
|
+
@layout = Teamocil::Layout.new({ "windows" => [{ "name" => "foo" }] }, {})
|
19
|
+
lambda { @layout.compile! }.should raise_error Teamocil::Error::LayoutError
|
20
|
+
end # }}}
|
21
|
+
|
22
|
+
it "does not compile with empty splits" do # {{{
|
23
|
+
@layout = Teamocil::Layout.new({ "windows" => [{ "name" => "foo", "splits" => [nil, nil] }] }, {})
|
24
|
+
lambda { @layout.compile! }.should raise_error Teamocil::Error::LayoutError
|
25
|
+
end # }}}
|
26
|
+
end # }}}
|
27
|
+
|
11
28
|
describe "windows" do # {{{
|
12
29
|
it "creates windows" do # {{{
|
13
30
|
session = @layout.compile!
|
@@ -27,6 +44,12 @@ describe Teamocil::Layout do
|
|
27
44
|
session.windows[0].root.should == "/foo"
|
28
45
|
session.windows[1].root.should == "/bar"
|
29
46
|
end # }}}
|
47
|
+
|
48
|
+
it "creates windows with clear option" do # {{{
|
49
|
+
session = @layout.compile!
|
50
|
+
session.windows[0].clear.should == "clear"
|
51
|
+
session.windows[1].clear.should be_nil
|
52
|
+
end # }}}
|
30
53
|
end # }}}
|
31
54
|
|
32
55
|
describe "splits" do # {{{
|
@@ -54,6 +77,12 @@ describe Teamocil::Layout do
|
|
54
77
|
session.windows.last.splits[0].cmd.first.should == "echo 'bar'"
|
55
78
|
session.windows.last.splits[0].cmd.last.should == "echo 'bar in an array'"
|
56
79
|
end # }}}
|
80
|
+
|
81
|
+
it "handles focused splits" do # {{{
|
82
|
+
session = @layout.compile!
|
83
|
+
session.windows.last.splits[1].focus.should be_true
|
84
|
+
session.windows.last.splits[0].focus.should be_false
|
85
|
+
end # }}}
|
57
86
|
end # }}}
|
58
87
|
|
59
88
|
describe "filters" do # {{{
|
@@ -109,12 +138,25 @@ describe Teamocil::Layout do
|
|
109
138
|
@layout = Teamocil::Layout.new(layouts["two-windows"], {})
|
110
139
|
end # }}}
|
111
140
|
|
112
|
-
it "should generate commands" do #{{{
|
141
|
+
it "should generate split commands" do #{{{
|
113
142
|
session = @layout.compile!
|
114
143
|
commands = session.windows.last.splits[0].generate_commands
|
115
144
|
commands.length.should == 2
|
116
145
|
commands.first.should == "tmux send-keys -t 0 \"export TEAMOCIL=1 && cd \"/bar\" && echo 'bar' && echo 'bar in an array'\""
|
117
146
|
commands.last.should == "tmux send-keys -t 0 Enter"
|
147
|
+
|
148
|
+
session = @layout.compile!
|
149
|
+
commands = session.windows.first.splits[0].generate_commands
|
150
|
+
commands.length.should == 2
|
151
|
+
commands.first.should == "tmux send-keys -t 0 \"export TEAMOCIL=1 && cd \"/foo\" && clear && echo 'foo'\""
|
152
|
+
commands.last.should == "tmux send-keys -t 0 Enter"
|
153
|
+
end # }}}
|
154
|
+
|
155
|
+
it "should generate window commands" do #{{{
|
156
|
+
session = @layout.compile!
|
157
|
+
commands = session.windows.last.generate_commands
|
158
|
+
commands.first.should == "tmux new-window -n \"bar\""
|
159
|
+
commands.last.should == "tmux select-pane -t 1"
|
118
160
|
end # }}}
|
119
161
|
end
|
120
162
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: teamocil
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-08-27 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -97,6 +97,7 @@ files:
|
|
97
97
|
- examples/simple-two-vertical-splits.yml
|
98
98
|
- lib/teamocil.rb
|
99
99
|
- lib/teamocil/cli.rb
|
100
|
+
- lib/teamocil/error.rb
|
100
101
|
- lib/teamocil/layout.rb
|
101
102
|
- lib/teamocil/layout/session.rb
|
102
103
|
- lib/teamocil/layout/split.rb
|
@@ -126,7 +127,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
126
127
|
version: '0'
|
127
128
|
segments:
|
128
129
|
- 0
|
129
|
-
hash:
|
130
|
+
hash: -4311130867002785670
|
130
131
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
132
|
none: false
|
132
133
|
requirements:
|
@@ -135,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
135
136
|
version: '0'
|
136
137
|
segments:
|
137
138
|
- 0
|
138
|
-
hash:
|
139
|
+
hash: -4311130867002785670
|
139
140
|
requirements: []
|
140
141
|
rubyforge_project:
|
141
142
|
rubygems_version: 1.8.18
|