tmuxinator 0.6.11 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,11 +4,75 @@ module Tmuxinator
4
4
  include Tmuxinator::Deprecations
5
5
  include Tmuxinator::WemuxSupport
6
6
 
7
- attr_reader :yaml, :custom_name
7
+ RBENVRVM_DEP_MSG = <<-M
8
+ DEPRECATION: rbenv/rvm-specific options have been replaced by the
9
+ pre_tab option and will not be supported in 0.8.0.
10
+ M
11
+ TABS_DEP_MSG = <<-M
12
+ DEPRECATION: The tabs option has been replaced by the windows option
13
+ and will not be supported in 0.8.0.
14
+ M
15
+ CLIARGS_DEP_MSG = <<-M
16
+ DEPRECATION: The cli_args option has been replaced by the tmux_options
17
+ option and will not be supported in 0.8.0.
18
+ M
19
+
20
+ attr_reader :yaml
21
+ attr_reader :force_attach
22
+ attr_reader :force_detach
23
+ attr_reader :custom_name
24
+
25
+ def self.load(path, options = {})
26
+ yaml = begin
27
+ raw_content = File.read(path)
28
+
29
+ args = options[:args] || []
30
+ @settings = parse_settings(args)
31
+ @args = args
32
+
33
+ content = Erubis::Eruby.new(raw_content).result(binding)
34
+ YAML.load(content)
35
+ rescue SyntaxError, StandardError
36
+ raise "Failed to parse config file. Please check your formatting."
37
+ end
38
+
39
+ new(yaml, options)
40
+ end
41
+
42
+ def self.parse_settings(args)
43
+ settings = args.select { |x| x.match(/.*=.*/) }
44
+ args.reject! { |x| x.match(/.*=.*/) }
45
+
46
+ settings.map! do |setting|
47
+ parts = setting.split("=")
48
+ [parts[0], parts[1]]
49
+ end
50
+
51
+ Hash[settings]
52
+ end
53
+
54
+ def validate!
55
+ raise "Your project file should include some windows." \
56
+ unless self.windows?
57
+ raise "Your project file didn't specify a 'project_name'" \
58
+ unless self.name?
59
+ self
60
+ end
61
+
62
+ def initialize(yaml, options = {})
63
+ options[:force_attach] = false if options[:force_attach].nil?
64
+ options[:force_detach] = false if options[:force_detach].nil?
8
65
 
9
- def initialize(yaml, custom_name = nil)
10
66
  @yaml = yaml
11
- @custom_name = custom_name
67
+
68
+ @custom_name = options[:custom_name]
69
+
70
+ @force_attach = options[:force_attach]
71
+ @force_detach = options[:force_detach]
72
+
73
+ raise "Cannot force_attach and force_detach at the same time" \
74
+ if @force_attach && @force_detach
75
+
12
76
  load_wemux_overrides if wemux?
13
77
  end
14
78
 
@@ -20,7 +84,7 @@ module Tmuxinator
20
84
  def windows
21
85
  windows_yml = yaml["tabs"] || yaml["windows"]
22
86
 
23
- @windows ||= windows_yml.map.with_index do |window_yml, index|
87
+ @windows ||= (windows_yml || {}).map.with_index do |window_yml, index|
24
88
  Tmuxinator::Window.new(window_yml, index, self)
25
89
  end
26
90
  end
@@ -32,7 +96,7 @@ module Tmuxinator
32
96
 
33
97
  def name
34
98
  name = custom_name || yaml["project_name"] || yaml["name"]
35
- name.blank? ? nil : name.shellescape
99
+ name.blank? ? nil : name.to_s.shellescape
36
100
  end
37
101
 
38
102
  def pre
@@ -44,11 +108,21 @@ module Tmuxinator
44
108
  end
45
109
  end
46
110
 
111
+ def attach?
112
+ if yaml["attach"].nil?
113
+ yaml_attach = true
114
+ else
115
+ yaml_attach = yaml["attach"]
116
+ end
117
+ attach = force_attach || !force_detach && yaml_attach
118
+ attach
119
+ end
120
+
47
121
  def pre_window
48
122
  if rbenv?
49
- "rbenv shell #{yaml["rbenv"]}"
123
+ "rbenv shell #{yaml['rbenv']}"
50
124
  elsif rvm?
51
- "rvm use #{yaml["rvm"]}"
125
+ "rvm use #{yaml['rvm']}"
52
126
  elsif pre_tab?
53
127
  yaml["pre_tab"]
54
128
  else
@@ -56,14 +130,6 @@ module Tmuxinator
56
130
  end
57
131
  end
58
132
 
59
- def attach
60
- attach = true
61
- if !yaml["attach"].nil?
62
- attach = yaml["attach"]
63
- end
64
- attach
65
- end
66
-
67
133
  def post
68
134
  post_config = yaml["post"]
69
135
  if post_config.is_a?(Array)
@@ -86,8 +152,6 @@ module Tmuxinator
86
152
  " -S #{socket_path}"
87
153
  elsif socket_name
88
154
  " -L #{socket_name}"
89
- else
90
- nil
91
155
  end
92
156
  end
93
157
 
@@ -101,9 +165,9 @@ module Tmuxinator
101
165
 
102
166
  def tmux_options
103
167
  if cli_args?
104
- " #{yaml["cli_args"].to_s.strip}"
168
+ " #{yaml['cli_args'].to_s.strip}"
105
169
  elsif tmux_options?
106
- " #{yaml["tmux_options"].to_s.strip}"
170
+ " #{yaml['tmux_options'].to_s.strip}"
107
171
  else
108
172
  ""
109
173
  end
@@ -133,15 +197,11 @@ module Tmuxinator
133
197
  !name.nil?
134
198
  end
135
199
 
136
- def attach?
137
- !!attach
138
- end
139
-
140
200
  def window(i)
141
201
  "#{name}:#{i}"
142
202
  end
143
203
 
144
- def send_pane_command(cmd, window_index, pane_index)
204
+ def send_pane_command(cmd, window_index, _pane_index)
145
205
  if cmd.empty?
146
206
  ""
147
207
  else
@@ -151,7 +211,7 @@ module Tmuxinator
151
211
 
152
212
  def send_keys(cmd, window_index)
153
213
  if cmd.empty?
154
- ""
214
+ ""
155
215
  else
156
216
  "#{tmux} send-keys -t #{window(window_index)} #{cmd.shellescape} C-m"
157
217
  end
@@ -159,9 +219,9 @@ module Tmuxinator
159
219
 
160
220
  def deprecations
161
221
  deprecations = []
162
- deprecations << "DEPRECATION: rbenv/rvm specific options have been replaced by the pre_tab option and will not be supported in 0.8.0." if yaml["rbenv"] || yaml["rvm"]
163
- deprecations << "DEPRECATION: The tabs option has been replaced by the windows option and will not be supported in 0.8.0." if yaml["tabs"]
164
- deprecations << "DEPRECATION: The cli_args option has been replaced by the tmux_options option and will not be supported in 0.8.0." if yaml["cli_args"]
222
+ deprecations << RBENVRVM_DEP_MSG if yaml["rbenv"] || yaml["rvm"]
223
+ deprecations << TABS_DEP_MSG if yaml["tabs"]
224
+ deprecations << CLIARGS_DEP_MSG if yaml["cli_args"]
165
225
  deprecations
166
226
  end
167
227
 
@@ -177,6 +237,11 @@ module Tmuxinator
177
237
  "#{tmux} start-server\\; show-option -g"
178
238
  end
179
239
 
240
+ def tmux_new_session_command
241
+ window = windows.first.tmux_window_name_option
242
+ "#{tmux} new-session -d -s #{name} #{window}"
243
+ end
244
+
180
245
  private
181
246
 
182
247
  def tmux_config
@@ -187,7 +252,7 @@ module Tmuxinator
187
252
  options_hash = {}
188
253
 
189
254
  options_string = `#{show_tmux_options}`
190
- options_string.encode!("UTF-8", :invalid => :replace)
255
+ options_string.encode!("UTF-8", invalid: :replace)
191
256
  options_string.split("\n").map do |entry|
192
257
  key, value = entry.split("\s")
193
258
  options_hash[key] = value
@@ -1,3 +1,3 @@
1
1
  module Tmuxinator
2
- VERSION = "0.6.11"
2
+ VERSION = "0.7.0"
3
3
  end
@@ -5,17 +5,17 @@ module Tmuxinator
5
5
  end
6
6
 
7
7
  def load_wemux_overrides
8
- self.instance_eval do
9
- def render
8
+ class_eval do
9
+ define_method :render do
10
10
  template = File.read(Tmuxinator::Config.wemux_template)
11
11
  Erubis::Eruby.new(template).result(binding)
12
12
  end
13
13
 
14
- def name
14
+ define_method :name do
15
15
  "wemux"
16
16
  end
17
17
 
18
- def tmux
18
+ define_method :tmux do
19
19
  "wemux"
20
20
  end
21
21
  end
@@ -5,7 +5,9 @@ module Tmuxinator
5
5
  attr_reader :name, :root, :panes, :layout, :commands, :index, :project
6
6
 
7
7
  def initialize(window_yaml, index, project)
8
- @name = !window_yaml.keys.first.nil? ? window_yaml.keys.first.shellescape : nil
8
+ @name = if !window_yaml.keys.first.nil?
9
+ window_yaml.keys.first.shellescape
10
+ end
9
11
  @root = nil
10
12
  @panes = []
11
13
  @layout = nil
@@ -18,7 +20,11 @@ module Tmuxinator
18
20
  if value.is_a?(Hash)
19
21
  @layout = value["layout"] ? value["layout"].shellescape : nil
20
22
  @pre = value["pre"] if value["pre"]
21
- @root = value["root"] ? File.expand_path(value["root"]).shellescape : project.root? ? project.root : nil
23
+ @root = if value["root"]
24
+ File.expand_path(value["root"]).shellescape
25
+ elsif project.root?
26
+ project.root
27
+ end
22
28
 
23
29
  @panes = build_panes(value["panes"])
24
30
  else
@@ -29,7 +35,7 @@ module Tmuxinator
29
35
  def build_panes(panes_yml)
30
36
  Array(panes_yml).map.with_index do |pane_yml, index|
31
37
  if pane_yml.is_a?(Hash)
32
- pane_yml.map do |name, commands|
38
+ pane_yml.map do |_name, commands|
33
39
  Tmuxinator::Pane.new(index, project, self, *commands)
34
40
  end
35
41
  else
@@ -38,7 +44,7 @@ module Tmuxinator
38
44
  end.flatten
39
45
  end
40
46
 
41
- def build_commands(prefix, command_yml)
47
+ def build_commands(_prefix, command_yml)
42
48
  if command_yml.is_a?(Array)
43
49
  command_yml.map do |command|
44
50
  "#{tmux_window_command_prefix} #{command.shellescape} C-m" if command
@@ -80,9 +86,13 @@ module Tmuxinator
80
86
  "#{project.tmux} send-keys -t #{project.name}:#{index + project.base_index}"
81
87
  end
82
88
 
89
+ def tmux_window_name_option
90
+ name ? "-n #{name}" : ""
91
+ end
92
+
83
93
  def tmux_new_window_command
84
94
  path = root? ? "#{Tmuxinator::Config.default_path_option} #{root}" : nil
85
- "#{project.tmux} new-window #{path} -t #{tmux_window_target} -n #{name}"
95
+ "#{project.tmux} new-window #{path} -t #{tmux_window_target} #{tmux_window_name_option}"
86
96
  end
87
97
 
88
98
  def tmux_layout_command
@@ -1,39 +1,81 @@
1
+ def yaml_load(file)
2
+ YAML.load(File.read(File.expand_path(file)))
3
+ end
1
4
  FactoryGirl.define do
2
- factory :project, :class => Tmuxinator::Project do
5
+ factory :project, class: Tmuxinator::Project do
6
+ transient do
7
+ file { yaml_load("spec/fixtures/sample.yml") }
8
+ end
9
+
10
+ initialize_with { Tmuxinator::Project.new(file) }
11
+ end
12
+
13
+ factory :project_with_force_attach, class: Tmuxinator::Project do
14
+ transient do
15
+ file { yaml_load("spec/fixtures/detach.yml") }
16
+ end
17
+
18
+ initialize_with { Tmuxinator::Project.new(file, force_attach: true) }
19
+ end
20
+
21
+ factory :project_with_force_detach, class: Tmuxinator::Project do
22
+ transient do
23
+ file { yaml_load("spec/fixtures/detach.yml") }
24
+ end
25
+ initialize_with { Tmuxinator::Project.new(file, force_detach: true) }
26
+ end
27
+
28
+ factory :project_with_custom_name, class: Tmuxinator::Project do
29
+ transient do
30
+ file { yaml_load("spec/fixtures/sample.yml") }
31
+ end
32
+
33
+ initialize_with { Tmuxinator::Project.new(file, custom_name: "custom") }
34
+ end
35
+
36
+ factory :project_with_number_as_name, class: Tmuxinator::Project do
3
37
  transient do
4
- file { YAML.load(File.read("#{File.expand_path("spec/fixtures/sample.yml")}")) }
38
+ file { yaml_load("spec/fixtures/sample_number_as_name.yml") }
5
39
  end
6
40
 
7
41
  initialize_with { Tmuxinator::Project.new(file) }
8
42
  end
9
43
 
10
- factory :project_with_custom_name, :class => Tmuxinator::Project do
44
+ factory :project_with_deprecations, class: Tmuxinator::Project do
11
45
  transient do
12
- file { YAML.load(File.read("#{File.expand_path("spec/fixtures/sample.yml")}")) }
46
+ file { yaml_load("spec/fixtures/sample.deprecations.yml") }
13
47
  end
14
48
 
15
- initialize_with { Tmuxinator::Project.new(file, "custom") }
49
+ initialize_with { Tmuxinator::Project.new(file) }
50
+ end
51
+
52
+ factory :wemux_project, class: Tmuxinator::Project do
53
+ transient do
54
+ file { yaml_load("spec/fixtures/sample_wemux.yml") }
55
+ end
56
+
57
+ initialize_with { Tmuxinator::Project.new(file) }
16
58
  end
17
59
 
18
- factory :project_with_deprecations, :class => Tmuxinator::Project do
60
+ factory :noname_project, class: Tmuxinator::Project do
19
61
  transient do
20
- file { YAML.load(File.read("#{File.expand_path("spec/fixtures/sample.deprecations.yml")}")) }
62
+ file { yaml_load("spec/fixtures/noname.yml") }
21
63
  end
22
64
 
23
65
  initialize_with { Tmuxinator::Project.new(file) }
24
66
  end
25
67
 
26
- factory :wemux_project, :class => Tmuxinator::Project do
68
+ factory :nowindows_project, class: Tmuxinator::Project do
27
69
  transient do
28
- file { YAML.load(File.read("#{File.expand_path("spec/fixtures/sample_wemux.yml")}")) }
70
+ file { yaml_load("spec/fixtures/nowindows.yml") }
29
71
  end
30
72
 
31
73
  initialize_with { Tmuxinator::Project.new(file) }
32
74
  end
33
75
 
34
- factory :noname_project, :class => Tmuxinator::Project do
76
+ factory :nameless_window_project, class: Tmuxinator::Project do
35
77
  transient do
36
- file { YAML.load(File.read("#{File.expand_path("spec/fixtures/noname.yml")}")) }
78
+ file { yaml_load("spec/fixtures/nameless_window.yml") }
37
79
  end
38
80
 
39
81
  initialize_with { Tmuxinator::Project.new(file) }
@@ -0,0 +1,41 @@
1
+ # ~/.tmuxinator/sample.yml
2
+ # you can make as many tabs as you wish...
3
+
4
+ name: sample
5
+ root: ~/test
6
+ socket_name: foo # Remove to use default socket
7
+ pre: sudo /etc/rc.d/mysqld start # Runs before everything
8
+ pre_window: rbenv shell 2.0.0-p247 # Runs in each tab and pane
9
+ tmux_options: -f ~/.tmux.mac.conf # Pass arguments to tmux
10
+ attach: false
11
+ windows:
12
+ - editor:
13
+ pre:
14
+ - echo "I get run in each pane, before each pane command!"
15
+ -
16
+ layout: main-vertical
17
+ panes:
18
+ - vim
19
+ - #empty, will just run plain bash
20
+ - top
21
+ - pane_with_multiple_commands:
22
+ - ssh server
23
+ - echo "Hello"
24
+ - shell:
25
+ - git pull
26
+ - git merge
27
+ - guard:
28
+ layout: tiled
29
+ pre:
30
+ - echo "I get run in each pane."
31
+ - echo "Before each pane command!"
32
+ panes:
33
+ -
34
+ - #empty, will just run plain bash
35
+ -
36
+ - database: bundle exec rails db
37
+ - server: bundle exec rails s
38
+ - logs: tail -f log/development.log
39
+ - console: bundle exec rails c
40
+ - capistrano:
41
+ - server: ssh user@example.com
@@ -0,0 +1,5 @@
1
+ name: nameless_window
2
+ root: ~/
3
+ windows:
4
+ - ~: echo "this is a window with no name"
5
+ - other: echo "this window has a name"
@@ -0,0 +1,3 @@
1
+ name: no_windows
2
+ root: ~/
3
+
@@ -7,6 +7,7 @@ socket_name: foo # Remove to use default socket
7
7
  pre: sudo /etc/rc.d/mysqld start # Runs before everything
8
8
  pre_window: rbenv shell 2.0.0-p247 # Runs in each tab and pane
9
9
  tmux_options: -f ~/.tmux.mac.conf # Pass arguments to tmux
10
+ tmux_detached: false
10
11
  windows:
11
12
  - editor:
12
13
  pre: