teamocil 1.0.5 → 1.0.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cd9c25b9a34c7f2b8efa0b353640523a9c6ad8f4
4
- data.tar.gz: 4e4db6b9d019b46b0820d8d7a8d583afdb1250e9
3
+ metadata.gz: a3243fbfc89942819b6f281a12b5618ef90bb408
4
+ data.tar.gz: 598b276ff2b771918704058021d5264e5864348a
5
5
  SHA512:
6
- metadata.gz: 30df185031fc3ef4f5c530bc29b10f525312ca12f34d6590732f315ddf6b62cca9214b8ae5639cfb7d815bc4446181789f7f07a57ecf1fb73fa5969118cd5d13
7
- data.tar.gz: 70d528fc0064ae4ec5f2409737fe21ff0b2aac5dfd2f4cfbf26b6bbf1406594c09d5b9677d30573222f681d14ff3d24f7dc6a2ac4e7f15df7c50d3382a19fa37
6
+ metadata.gz: c6506fa11e9cbb7a1a0de10ac307caac52b1844132e005fd8a6763a39b780edb2c0c7c5c4d92e3234494f80d4c2723b0b11b586aad09f601d4d64be1535bb93a
7
+ data.tar.gz: 91a84c4b94ce363dc0736da6a9908cd30060af64debc49dd72af0d90d222a4e698582ee6b7d232541c5e538aba6d8a2c132d5160f5efdbe7d1a95713086b1941
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
@@ -1,2 +1,7 @@
1
- rvm: 2.1.2
2
- script: bundle exec phare
1
+ rvm:
2
+ - 2.0.0
3
+ - 2.1.2
4
+
5
+ script:
6
+ - 'echo "Checking code style" && bundle exec phare'
7
+ - 'echo "Running specs" && bundle exec rspec'
data/README.md CHANGED
@@ -68,6 +68,13 @@ Feel free to fork the repository and add back as many features as you want :)
68
68
 
69
69
  ## Configuration
70
70
 
71
+ ### Session
72
+
73
+ | Key | Description
74
+ |-----------|----------------------------
75
+ | `name` | The tmux session name
76
+ | `windows` | An `Array` of windows
77
+
71
78
  ### Windows
72
79
 
73
80
  | Key | Description
@@ -183,6 +190,9 @@ To get autocompletion when typing `teamocil <Tab>` in a zsh session, add this li
183
190
  compctl -g '~/.teamocil/*(:t:r)' teamocil
184
191
  ```
185
192
 
193
+ [zsh-completions](https://github.com/zsh-users/zsh-completions) also provides
194
+ additional completion definitions for Teamocil.
195
+
186
196
  ### Bash autocompletion
187
197
 
188
198
  To get autocompletion when typing `teamocil <Tab>` in a bash session, add this line to your `~/.bashrc` file:
@@ -12,7 +12,13 @@ require 'teamocil/utils/option_parser'
12
12
  require 'teamocil/layout'
13
13
  require 'teamocil/cli'
14
14
 
15
+ # Errors
16
+ require 'teamocil/error/layout_not_found'
17
+ require 'teamocil/error/invalid_yaml_layout'
18
+
15
19
  # Command classes
20
+ require 'teamocil/command/list_panes'
21
+ require 'teamocil/command/list_windows'
16
22
  require 'teamocil/command/new_window'
17
23
  require 'teamocil/command/rename_session'
18
24
  require 'teamocil/command/rename_window'
@@ -21,13 +27,15 @@ require 'teamocil/command/select_pane'
21
27
  require 'teamocil/command/select_window'
22
28
  require 'teamocil/command/send_keys'
23
29
  require 'teamocil/command/send_keys_to_pane'
30
+ require 'teamocil/command/show_options'
31
+ require 'teamocil/command/show_window_options'
24
32
  require 'teamocil/command/split_window'
25
33
 
26
34
  # Tmux classes
35
+ require 'teamocil/tmux'
27
36
  require 'teamocil/tmux/session'
28
37
  require 'teamocil/tmux/window'
29
38
  require 'teamocil/tmux/pane'
30
- require 'teamocil/tmux/options'
31
39
 
32
40
  module Teamocil
33
41
  class << self
@@ -49,7 +57,7 @@ module Teamocil
49
57
  end
50
58
 
51
59
  def self.query_system(command)
52
- `#{command}`
60
+ `tmux #{command.to_s}`
53
61
  end
54
62
 
55
63
  def self.parse_options!(arguments: nil)
@@ -0,0 +1,15 @@
1
+ module Teamocil
2
+ module Command
3
+ class ListPanes < ClosedStruct.new(:index)
4
+ def to_s
5
+ "list-panes #{options.join(' ')}"
6
+ end
7
+
8
+ def options
9
+ [].tap do |options|
10
+ options << "-t '#{index}'" if index
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ module Teamocil
2
+ module Command
3
+ class ListWindows < ClosedStruct.new(:foo)
4
+ def to_s
5
+ 'list-windows'
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Teamocil
2
+ module Command
3
+ class ShowOptions < ClosedStruct.new(:name)
4
+ def to_s
5
+ "show-options -gv #{name}"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Teamocil
2
+ module Command
3
+ class ShowWindowOptions < ClosedStruct.new(:name)
4
+ def to_s
5
+ "show-window-options -gv #{name}"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ module Teamocil
2
+ module Error
3
+ class InvalidYAMLLayout < StandardError
4
+ def initialize(path)
5
+ @path = path
6
+ end
7
+
8
+ def to_s
9
+ "There was a YAML error when parsing `#{@path}`"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Teamocil
2
+ module Error
3
+ class LayoutNotFound < StandardError
4
+ def initialize(path)
5
+ @path = path
6
+ end
7
+
8
+ def to_s
9
+ "Cannot find a layout at `#{@path}`"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,5 +1,5 @@
1
1
  module Teamocil
2
- class Layout < ClosedStruct.new(:path, :options)
2
+ class Layout < ClosedStruct.new(:path)
3
3
  def execute!
4
4
  if Teamocil.options[:debug]
5
5
  Teamocil.puts(shell_commands.join("\n"))
@@ -34,33 +34,23 @@ module Teamocil
34
34
  private
35
35
 
36
36
  def shell_commands
37
- commands = parsed_layout.as_tmux
38
- commands.flatten.map { |command| "tmux #{command}" }
37
+ session.as_tmux.map { |command| "tmux #{command}" }
39
38
  end
40
39
 
41
- def parsed_layout
42
- begin
43
- yaml_content = YAML.load(raw_content)
44
- rescue
45
- Teamocil.bail("There was a YAML error when parsing `#{path}`")
46
- end
47
-
48
- if valid?
49
- Teamocil::Tmux::Session.new(yaml_content)
50
- else
51
- Teamocil.bail("The layout at `#{path}` is not valid.")
52
- end
40
+ def session
41
+ Teamocil::Tmux::Session.new(parsed_content)
53
42
  end
54
43
 
55
- def valid?
56
- # TODO: Actually validate if the layout is valid
57
- true
44
+ def parsed_content
45
+ YAML.load(raw_content)
46
+ rescue Psych::SyntaxError
47
+ raise Teamocil::Error::InvalidYAMLLayout, path
58
48
  end
59
49
 
60
50
  def raw_content
61
51
  File.read(path)
62
- rescue
63
- Teamocil.bail("Cannot find a layout at `#{path}`")
52
+ rescue Errno::ENOENT
53
+ raise Teamocil::Error::LayoutNotFound, path
64
54
  end
65
55
  end
66
56
  end
@@ -0,0 +1,25 @@
1
+ module Teamocil
2
+ module Tmux
3
+ def self.option(option, default: nil)
4
+ command = Teamocil::Command::ShowOptions.new(name: option)
5
+ value = Teamocil.query_system(command).chomp
6
+ value.empty? ? default : value.to_i
7
+ end
8
+
9
+ def self.window_option(option, default: nil)
10
+ command = Teamocil::Command::ShowWindowOptions.new(name: option)
11
+ value = Teamocil.query_system(command).chomp
12
+ value.empty? ? default : value.to_i
13
+ end
14
+
15
+ def self.window_count
16
+ command = Teamocil::Command::ListWindows.new
17
+ Teamocil.query_system(command).chomp.split("\n").size
18
+ end
19
+
20
+ def self.pane_count(index: nil)
21
+ command = Teamocil::Command::ListPanes.new(index: index)
22
+ Teamocil.query_system(command).chomp.split("\n").size
23
+ end
24
+ end
25
+ end
@@ -1,13 +1,27 @@
1
1
  module Teamocil
2
2
  module Tmux
3
- class Pane < ClosedStruct.new(:index, :root, :commands, :focus, :first)
3
+ class Pane < ClosedStruct.new(:index, :root, :commands, :focus)
4
4
  def as_tmux
5
5
  [].tap do |tmux|
6
- tmux << Teamocil::Command::SplitWindow.new(root: root) unless first
7
- tmux << Teamocil::Command::SendKeysToPane.new(index: index, keys: commands.join('; '))
8
- tmux << Teamocil::Command::SendKeysToPane.new(index: index, keys: 'Enter')
6
+ tmux << Teamocil::Command::SplitWindow.new(root: root) unless first?
7
+ tmux << Teamocil::Command::SendKeysToPane.new(index: internal_index, keys: commands.join('; ')) if commands
8
+ tmux << Teamocil::Command::SendKeysToPane.new(index: internal_index, keys: 'Enter')
9
9
  end
10
10
  end
11
+
12
+ def internal_index
13
+ index + self.class.pane_base_index
14
+ end
15
+
16
+ def self.pane_base_index
17
+ @pane_base_index ||= Teamocil::Tmux.window_option('pane-base-index', default: 0)
18
+ end
19
+
20
+ private
21
+
22
+ def first?
23
+ index.zero?
24
+ end
11
25
  end
12
26
  end
13
27
  end
@@ -9,8 +9,7 @@ module Teamocil
9
9
 
10
10
  self.windows = windows.each_with_index.map do |window, index|
11
11
  # Windows need to know their position
12
- window.merge! index: index + window_base_index
13
- window.merge! first: index.zero?
12
+ window.merge! index: index
14
13
 
15
14
  Teamocil::Tmux::Window.new(window)
16
15
  end
@@ -23,12 +22,8 @@ module Teamocil
23
22
 
24
23
  # Set the focus on the right window or do nothing
25
24
  focused_window = windows.find(&:focus)
26
- tmux << Teamocil::Command::SelectWindow.new(index: focused_window.index) if focused_window
27
- end
28
- end
29
-
30
- def window_base_index
31
- @window_base_index ||= Teamocil::Tmux::Options.fetch_option('base-index', default: 0)
25
+ tmux << Teamocil::Command::SelectWindow.new(index: focused_window.internal_index) if focused_window
26
+ end.flatten
32
27
  end
33
28
  end
34
29
  end
@@ -1,20 +1,19 @@
1
1
  module Teamocil
2
2
  module Tmux
3
- class Window < ClosedStruct.new(:index, :root, :focus, :layout, :name, :panes, :first)
3
+ class Window < ClosedStruct.new(:index, :root, :focus, :layout, :name, :panes)
4
4
  def initialize(object)
5
5
  super
6
6
 
7
7
  # Make sure paths like `~/foo/bar` work
8
8
  self.root = File.expand_path(root) if root
9
9
 
10
- self.panes ||= splits
10
+ self.panes ||= []
11
11
  self.panes = panes.each_with_index.map do |pane, index|
12
12
  # Support single command instead of `commands` key in Hash
13
13
  pane = { commands: [pane] } if pane.is_a?(String)
14
14
 
15
15
  # Panes need to know their position
16
- pane.merge! index: index + pane_base_index
17
- pane.merge! first: index.zero?
16
+ pane.merge! index: index
18
17
 
19
18
  # Panes need know the window root directory
20
19
  pane.merge! root: root
@@ -26,27 +25,51 @@ module Teamocil
26
25
  def as_tmux
27
26
  [].tap do |tmux|
28
27
  # Rename the current window or create a new one
29
- if Teamocil.options[:here] && first
28
+ if Teamocil.options[:here] && first?
29
+ if root
30
+ first_pane_index = panes.first.internal_index
31
+ tmux << Teamocil::Command::SendKeysToPane.new(index: first_pane_index, keys: %(cd "#{root}"))
32
+ tmux << Teamocil::Command::SendKeysToPane.new(index: first_pane_index, keys: 'Enter')
33
+ end
34
+
30
35
  tmux << Teamocil::Command::RenameWindow.new(name: name)
31
36
  else
32
37
  tmux << Teamocil::Command::NewWindow.new(name: name, root: root)
33
38
  end
34
39
 
35
40
  # Execute all panes commands
36
- tmux << panes.map(&:as_tmux)
41
+ tmux << panes.map(&:as_tmux).flatten
37
42
 
38
43
  # Select the window layout
39
44
  tmux << Teamocil::Command::SelectLayout.new(layout: layout) if layout
40
45
 
41
46
  # Set the focus on the right pane or the first one
42
47
  focused_pane = panes.find(&:focus)
43
- focused_index = focused_pane ? focused_pane.index : pane_base_index
48
+ focused_index = focused_pane ? focused_pane.internal_index : Teamocil::Tmux::Pane.pane_base_index
44
49
  tmux << Teamocil::Command::SelectPane.new(index: focused_index)
50
+ end.flatten
51
+ end
52
+
53
+ def internal_index
54
+ index + self.class.window_base_index
55
+ end
56
+
57
+ def self.window_base_index
58
+ @window_base_index ||= begin
59
+ base_index = Teamocil::Tmux.option('base-index', default: 0)
60
+ current_window_count = Teamocil::Tmux.window_count
61
+
62
+ # If `--here` is specified, treat the current window as a new one
63
+ current_window_count -= 1 if Teamocil.options[:here]
64
+
65
+ base_index + current_window_count
45
66
  end
46
67
  end
47
68
 
48
- def pane_base_index
49
- @pane_base_index ||= Teamocil::Tmux::Options.fetch_window_option('pane-base-index', default: 0)
69
+ protected
70
+
71
+ def first?
72
+ index.zero?
50
73
  end
51
74
  end
52
75
  end
@@ -5,7 +5,7 @@ module Teamocil
5
5
 
6
6
  args.first.each_pair do |key, value|
7
7
  # Make sure we only set values to defined arguments
8
- if members.map { |x| x.intern }.include?(key.to_sym)
8
+ if members.map(&:intern).include?(key.to_sym)
9
9
  send "#{key}=", value
10
10
  else
11
11
  raise ArgumentError, "#{self.class.name} doesn’t support the `#{key}` keyword, only #{members.join(', ')}"
@@ -1,3 +1,3 @@
1
1
  module Teamocil
2
- VERSION = '1.0.5'
2
+ VERSION = '1.0.6'
3
3
  end
@@ -0,0 +1,16 @@
1
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2
+
3
+ # Ruby stdlib dependencies
4
+ require 'tmpdir'
5
+ require 'fileutils'
6
+
7
+ # RSpec testing framework
8
+ require 'rspec'
9
+
10
+ # Teamocil
11
+ require 'teamocil'
12
+
13
+ RSpec.configure do |config|
14
+ # Disable `should` syntax
15
+ config.expect_with(:rspec) { |c| c.syntax = :expect }
16
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Teamocil::CLI do
4
+ describe :run! do
5
+ let(:cli) { Teamocil::CLI.new(arguments: arguments, environment: environment) }
6
+ let(:environment) { { 'HOME' => Dir.tmpdir } }
7
+ let(:root) { File.join(environment['HOME'], '.teamocil') }
8
+
9
+ describe 'with --list option' do
10
+ let(:arguments) { ['--list'] }
11
+
12
+ before do
13
+ expect(Teamocil::Layout).to receive(:print_available_layouts).with(directory: root)
14
+ end
15
+
16
+ specify { cli.run! }
17
+ end
18
+
19
+ describe 'with --show option' do
20
+ let(:arguments) { ['--show', 'foo'] }
21
+ let(:layout) { double(Teamocil::Layout) }
22
+ let(:path) { File.join(root, 'foo.yml') }
23
+
24
+ before do
25
+ expect(Teamocil::Layout).to receive(:new).with(path: path).and_return(layout)
26
+ expect(layout).to receive(:show!)
27
+ end
28
+
29
+ specify { cli.run! }
30
+ end
31
+
32
+ describe 'with --edit option' do
33
+ let(:arguments) { ['--edit', 'foo'] }
34
+ let(:layout) { double(Teamocil::Layout) }
35
+ let(:path) { File.join(root, 'foo.yml') }
36
+
37
+ before do
38
+ expect(Teamocil::Layout).to receive(:new).with(path: path).and_return(layout)
39
+ expect(layout).to receive(:edit!)
40
+ end
41
+
42
+ specify { cli.run! }
43
+ end
44
+
45
+ describe 'with implicit execution' do
46
+ context 'with --layout option' do
47
+ let(:arguments) { ['--layout', path] }
48
+ let(:layout) { double(Teamocil::Layout) }
49
+ let(:path) { File.join(root, 'bar.yml') }
50
+
51
+ before do
52
+ expect(Teamocil::Layout).to receive(:new).with(path: path).and_return(layout)
53
+ expect(layout).to receive(:execute!)
54
+ end
55
+
56
+ specify { cli.run! }
57
+ end
58
+
59
+ context 'without --layout option' do
60
+ let(:arguments) { ['foo'] }
61
+ let(:layout) { double(Teamocil::Layout) }
62
+ let(:path) { File.join(root, 'foo.yml') }
63
+
64
+ before do
65
+ expect(Teamocil::Layout).to receive(:new).with(path: path).and_return(layout)
66
+ expect(layout).to receive(:execute!)
67
+ end
68
+
69
+ specify { cli.run! }
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,126 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Teamocil::Layout do
4
+ describe :execute! do
5
+ let(:layout) { Teamocil::Layout.new(path: path) }
6
+ let(:execute!) { layout.execute! }
7
+ let(:path) { double('Path') }
8
+
9
+ let(:options) { {} }
10
+ before { allow(Teamocil).to receive(:options).and_return(options) }
11
+
12
+ context 'without errors' do
13
+ let(:raw_content) { double('Raw content') }
14
+ let(:parsed_content) { double('Parsed content') }
15
+ let(:session) { instance_double(Teamocil::Tmux::Session) }
16
+ let(:commands) { %w(foo bar omg) }
17
+
18
+ before do
19
+ allow(Teamocil::Tmux::Session).to receive(:new).and_return(session)
20
+
21
+ expect(File).to receive(:read).with(path).and_return(raw_content)
22
+ expect(YAML).to receive(:load).with(raw_content).and_return(parsed_content)
23
+
24
+ expect(session).to receive(:as_tmux).and_return(commands)
25
+ end
26
+
27
+ context 'without --debug option' do
28
+ before do
29
+ expect(Teamocil).to receive(:system).with('tmux foo; tmux bar; tmux omg')
30
+ end
31
+
32
+ specify { layout.execute! }
33
+ end
34
+
35
+ context 'with --debug option' do
36
+ let(:options) { { debug: true } }
37
+
38
+ before do
39
+ expect(Teamocil).to receive(:puts).with("tmux foo\ntmux bar\ntmux omg")
40
+ end
41
+
42
+ specify { execute! }
43
+ end
44
+ end
45
+
46
+ context 'with not-found layout' do
47
+ before do
48
+ # Let’s simulate an error from `File.read`
49
+ expect(File).to receive(:read).with(path) { raise Errno::ENOENT }
50
+ end
51
+
52
+ it { expect { execute! }.to raise_error(Teamocil::Error::LayoutNotFound) }
53
+ end
54
+
55
+ context 'with invalid YAML layout' do
56
+ let(:raw_content) { double('Raw content') }
57
+
58
+ before do
59
+ expect(File).to receive(:read).with(path).and_return(raw_content)
60
+
61
+ # Let’s simulate an error from `YAML.load`
62
+ expect(YAML).to receive(:load).with(raw_content) { raise Psych::SyntaxError.new(nil, 0, 0, 0, nil, nil) }
63
+ end
64
+
65
+ it { expect { execute! }.to raise_error(Teamocil::Error::InvalidYAMLLayout) }
66
+ end
67
+ end
68
+
69
+ describe :show! do
70
+ let(:layout) { Teamocil::Layout.new(path: path) }
71
+ let(:show!) { layout.show! }
72
+ let(:path) { double('Path') }
73
+ let(:raw_content) { double('Raw content') }
74
+
75
+ context 'with found layout' do
76
+ before do
77
+ expect(File).to receive(:read).with(path).and_return(raw_content)
78
+ expect(Teamocil).to receive(:puts).with(raw_content)
79
+ end
80
+
81
+ specify { show! }
82
+ end
83
+
84
+ context 'with not-found layout' do
85
+ before do
86
+ # Let’s simulate an error from `File.read`
87
+ expect(File).to receive(:read).with(path) { raise Errno::ENOENT }
88
+ end
89
+
90
+ it { expect { show! }.to raise_error(Teamocil::Error::LayoutNotFound) }
91
+ end
92
+ end
93
+
94
+ describe :edit! do
95
+ let(:layout) { Teamocil::Layout.new(path: path) }
96
+ let(:edit!) { layout.edit! }
97
+ let(:path) { double('Path') }
98
+
99
+ before do
100
+ expect(Teamocil).to receive(:system).with("$EDITOR #{path}")
101
+ end
102
+
103
+ specify { edit! }
104
+ end
105
+
106
+ describe :ClassMethods do
107
+ describe :print_available_layouts do
108
+ let(:tmpdir) { Dir.mktmpdir }
109
+ let(:directory) { File.join(tmpdir, '.teamocil') }
110
+ after { FileUtils.remove_entry(tmpdir) }
111
+
112
+ before do
113
+ FileUtils.mkdir_p(directory)
114
+ FileUtils.touch(File.join(directory, 'foo.yml'))
115
+ FileUtils.touch(File.join(directory, 'bar.yml'))
116
+ FileUtils.touch(File.join(directory, 'omg.txt'))
117
+
118
+ expect(Teamocil).to receive(:puts).with(%w(bar foo))
119
+ end
120
+
121
+ specify do
122
+ Teamocil::Layout.print_available_layouts(directory: directory)
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Teamocil::Tmux::Pane do
4
+ describe :as_tmux do
5
+ let(:pane) { Teamocil::Tmux::Pane.new(commands: commands, root: root, index: index, focus: focus) }
6
+ let(:as_tmux) { pane.as_tmux }
7
+ let(:pane_base_index) { Random.rand(0..100) }
8
+
9
+ before do
10
+ allow(Teamocil::Tmux::Pane).to receive(:pane_base_index).and_return(pane_base_index)
11
+ end
12
+
13
+ # Pane attributes
14
+ let(:commands) { %w(foo bar) }
15
+ let(:root) { '/tmp' }
16
+ let(:focus) { true }
17
+
18
+ context 'for first pane' do
19
+ let(:index) { 0 }
20
+
21
+ it do
22
+ expect(as_tmux).to eql [
23
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index, keys: 'foo; bar'),
24
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index, keys: 'Enter')
25
+ ]
26
+ end
27
+ end
28
+
29
+ context 'for not-first pane' do
30
+ let(:index) { 1 }
31
+
32
+ it do
33
+ expect(as_tmux).to eql [
34
+ Teamocil::Command::SplitWindow.new(root: root),
35
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index + index, keys: 'foo; bar'),
36
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index + index, keys: 'Enter')
37
+ ]
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Teamocil::Tmux::Session do
4
+ pending
5
+ end
@@ -0,0 +1,122 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Teamocil::Tmux::Window do
4
+ let(:window) { Teamocil::Tmux::Window.new(index: index, root: root, layout: layout, name: name, panes: panes) }
5
+ let(:as_tmux) { window.as_tmux }
6
+
7
+ before do
8
+ allow(Teamocil::Tmux::Pane).to receive(:pane_base_index).and_return(pane_base_index)
9
+ allow(Teamocil::Tmux::Window).to receive(:window_base_index).and_return(window_base_index)
10
+ allow(Teamocil).to receive(:options).and_return(options)
11
+ end
12
+
13
+ # Tmux options
14
+ let(:pane_base_index) { Random.rand(0..100) }
15
+ let(:window_base_index) { Random.rand(0..100) }
16
+
17
+ # Window attributes
18
+ let(:options) { {} }
19
+ let(:index) { 0 }
20
+ let(:name) { 'foo' }
21
+ let(:layout) { nil }
22
+ let(:root) { nil }
23
+ let(:panes) do
24
+ [
25
+ { commands: %w(foo omg) },
26
+ { commands: %w(bar), focus: true }
27
+ ]
28
+ end
29
+
30
+ it do
31
+ expect(as_tmux).to eql [
32
+ Teamocil::Command::NewWindow.new(name: name),
33
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index, keys: 'foo; omg'),
34
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index, keys: 'Enter'),
35
+ Teamocil::Command::SplitWindow.new,
36
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index + 1, keys: 'bar'),
37
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index + 1, keys: 'Enter'),
38
+ Teamocil::Command::SelectPane.new(index: pane_base_index + 1)
39
+ ]
40
+ end
41
+
42
+ context 'with root attribute' do
43
+ let(:root) { '/tmp' }
44
+
45
+ it do
46
+ expect(as_tmux).to eql [
47
+ Teamocil::Command::NewWindow.new(name: name, root: root),
48
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index, keys: 'foo; omg'),
49
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index, keys: 'Enter'),
50
+ Teamocil::Command::SplitWindow.new(root: root),
51
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index + 1, keys: 'bar'),
52
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index + 1, keys: 'Enter'),
53
+ Teamocil::Command::SelectPane.new(index: pane_base_index + 1)
54
+ ]
55
+ end
56
+ end
57
+
58
+ context 'without panes' do
59
+ let(:panes) { nil }
60
+
61
+ it do
62
+ expect(as_tmux).to eql [
63
+ Teamocil::Command::NewWindow.new(name: name, root: root),
64
+ Teamocil::Command::SelectPane.new(index: pane_base_index)
65
+ ]
66
+ end
67
+ end
68
+
69
+ context 'with layout attribute' do
70
+ let(:layout) { 'tiled' }
71
+
72
+ it do
73
+ expect(as_tmux).to eql [
74
+ Teamocil::Command::NewWindow.new(name: name),
75
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index, keys: 'foo; omg'),
76
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index, keys: 'Enter'),
77
+ Teamocil::Command::SplitWindow.new,
78
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index + 1, keys: 'bar'),
79
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index + 1, keys: 'Enter'),
80
+ Teamocil::Command::SelectLayout.new(layout: layout),
81
+ Teamocil::Command::SelectPane.new(index: pane_base_index + 1)
82
+ ]
83
+ end
84
+ end
85
+
86
+ context 'with --here option' do
87
+ context 'without root' do
88
+ let(:options) { { here: true } }
89
+
90
+ it do
91
+ expect(as_tmux).to eql [
92
+ Teamocil::Command::RenameWindow.new(name: name),
93
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index, keys: 'foo; omg'),
94
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index, keys: 'Enter'),
95
+ Teamocil::Command::SplitWindow.new,
96
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index + 1, keys: 'bar'),
97
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index + 1, keys: 'Enter'),
98
+ Teamocil::Command::SelectPane.new(index: pane_base_index + 1)
99
+ ]
100
+ end
101
+ end
102
+
103
+ context 'with root' do
104
+ let(:root) { '/tmp' }
105
+ let(:options) { { here: true } }
106
+
107
+ it do
108
+ expect(as_tmux).to eql [
109
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index, keys: 'cd "/tmp"'),
110
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index, keys: 'Enter'),
111
+ Teamocil::Command::RenameWindow.new(name: name),
112
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index, keys: 'foo; omg'),
113
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index, keys: 'Enter'),
114
+ Teamocil::Command::SplitWindow.new(root: root),
115
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index + 1, keys: 'bar'),
116
+ Teamocil::Command::SendKeysToPane.new(index: pane_base_index + 1, keys: 'Enter'),
117
+ Teamocil::Command::SelectPane.new(index: pane_base_index + 1)
118
+ ]
119
+ end
120
+ end
121
+ end
122
+ end
@@ -24,5 +24,6 @@ Gem::Specification.new do |s|
24
24
  # Dependencies
25
25
  s.add_development_dependency 'rake'
26
26
  s.add_development_dependency 'phare', '~> 0.6'
27
- s.add_development_dependency 'rubocop', '~> 0.24'
27
+ s.add_development_dependency 'rubocop', '0.26.1'
28
+ s.add_development_dependency 'rspec', '~> 3.0'
28
29
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: teamocil
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rémi Prévost
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-18 00:00:00.000000000 Z
11
+ date: 2014-09-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -40,18 +40,32 @@ dependencies:
40
40
  version: '0.6'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 0.26.1
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 0.26.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: '0.24'
61
+ version: '3.0'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: '0.24'
68
+ version: '3.0'
55
69
  description: Teamocil helps you set up window and pane layouts for tmux using YAML
56
70
  configuration files.
57
71
  email: remi@exomel.com
@@ -61,6 +75,7 @@ extensions: []
61
75
  extra_rdoc_files: []
62
76
  files:
63
77
  - ".gitignore"
78
+ - ".rspec"
64
79
  - ".rubocop.yml"
65
80
  - ".travis.yml"
66
81
  - Gemfile
@@ -70,6 +85,8 @@ files:
70
85
  - bin/teamocil
71
86
  - lib/teamocil.rb
72
87
  - lib/teamocil/cli.rb
88
+ - lib/teamocil/command/list_panes.rb
89
+ - lib/teamocil/command/list_windows.rb
73
90
  - lib/teamocil/command/new_window.rb
74
91
  - lib/teamocil/command/rename_session.rb
75
92
  - lib/teamocil/command/rename_window.rb
@@ -78,15 +95,25 @@ files:
78
95
  - lib/teamocil/command/select_window.rb
79
96
  - lib/teamocil/command/send_keys.rb
80
97
  - lib/teamocil/command/send_keys_to_pane.rb
98
+ - lib/teamocil/command/show_options.rb
99
+ - lib/teamocil/command/show_window_options.rb
81
100
  - lib/teamocil/command/split_window.rb
101
+ - lib/teamocil/error/invalid_yaml_layout.rb
102
+ - lib/teamocil/error/layout_not_found.rb
82
103
  - lib/teamocil/layout.rb
83
- - lib/teamocil/tmux/options.rb
104
+ - lib/teamocil/tmux.rb
84
105
  - lib/teamocil/tmux/pane.rb
85
106
  - lib/teamocil/tmux/session.rb
86
107
  - lib/teamocil/tmux/window.rb
87
108
  - lib/teamocil/utils/closed_struct.rb
88
109
  - lib/teamocil/utils/option_parser.rb
89
110
  - lib/teamocil/version.rb
111
+ - spec/spec_helper.rb
112
+ - spec/teamocil/cli_spec.rb
113
+ - spec/teamocil/layout_spec.rb
114
+ - spec/teamocil/tmux/pane_spec.rb
115
+ - spec/teamocil/tmux/session_spec.rb
116
+ - spec/teamocil/tmux/window_spec.rb
90
117
  - teamocil.gemspec
91
118
  homepage: http://remiprev.github.com/teamocil
92
119
  licenses:
@@ -112,4 +139,10 @@ rubygems_version: 2.2.2
112
139
  signing_key:
113
140
  specification_version: 4
114
141
  summary: Easy session, window and pane layouts for tmux
115
- test_files: []
142
+ test_files:
143
+ - spec/spec_helper.rb
144
+ - spec/teamocil/cli_spec.rb
145
+ - spec/teamocil/layout_spec.rb
146
+ - spec/teamocil/tmux/pane_spec.rb
147
+ - spec/teamocil/tmux/session_spec.rb
148
+ - spec/teamocil/tmux/window_spec.rb
@@ -1,15 +0,0 @@
1
- module Teamocil
2
- module Tmux
3
- class Options
4
- def self.fetch_option(option, default: nil)
5
- value = Teamocil.query_system("tmux show-options -gv #{option}").chomp
6
- value.empty? ? default : value.to_i
7
- end
8
-
9
- def self.fetch_window_option(option, default: nil)
10
- value = Teamocil.query_system("tmux show-window-options -gv #{option}").chomp
11
- value.empty? ? default : value.to_i
12
- end
13
- end
14
- end
15
- end