tmuxinator 0.6.11 → 0.7.0
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 +4 -4
- data/bin/mux +6 -9
- data/bin/tmuxinator +6 -9
- data/lib/tmuxinator/assets/template.erb +6 -6
- data/lib/tmuxinator/assets/wemux_template.erb +1 -1
- data/lib/tmuxinator/cli.rb +111 -33
- data/lib/tmuxinator/config.rb +47 -35
- data/lib/tmuxinator/pane.rb +21 -5
- data/lib/tmuxinator/project.rb +94 -29
- data/lib/tmuxinator/version.rb +1 -1
- data/lib/tmuxinator/wemux_support.rb +4 -4
- data/lib/tmuxinator/window.rb +15 -5
- data/spec/factories/projects.rb +53 -11
- data/spec/fixtures/detach.yml +41 -0
- data/spec/fixtures/nameless_window.yml +5 -0
- data/spec/fixtures/nowindows.yml +3 -0
- data/spec/fixtures/sample.yml +1 -0
- data/spec/fixtures/sample_number_as_name.yml +5 -0
- data/spec/lib/tmuxinator/cli_spec.rb +191 -30
- data/spec/lib/tmuxinator/config_spec.rb +105 -8
- data/spec/lib/tmuxinator/project_spec.rb +172 -28
- data/spec/lib/tmuxinator/util_spec.rb +0 -1
- data/spec/lib/tmuxinator/wemux_support_spec.rb +47 -0
- data/spec/lib/tmuxinator/window_spec.rb +82 -21
- data/spec/spec_helper.rb +16 -15
- metadata +13 -3
data/lib/tmuxinator/project.rb
CHANGED
@@ -4,11 +4,75 @@ module Tmuxinator
|
|
4
4
|
include Tmuxinator::Deprecations
|
5
5
|
include Tmuxinator::WemuxSupport
|
6
6
|
|
7
|
-
|
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
|
-
|
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[
|
123
|
+
"rbenv shell #{yaml['rbenv']}"
|
50
124
|
elsif rvm?
|
51
|
-
"rvm use #{yaml[
|
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[
|
168
|
+
" #{yaml['cli_args'].to_s.strip}"
|
105
169
|
elsif tmux_options?
|
106
|
-
" #{yaml[
|
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,
|
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 <<
|
163
|
-
deprecations <<
|
164
|
-
deprecations <<
|
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", :
|
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
|
data/lib/tmuxinator/version.rb
CHANGED
@@ -5,17 +5,17 @@ module Tmuxinator
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def load_wemux_overrides
|
8
|
-
|
9
|
-
|
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
|
-
|
14
|
+
define_method :name do
|
15
15
|
"wemux"
|
16
16
|
end
|
17
17
|
|
18
|
-
|
18
|
+
define_method :tmux do
|
19
19
|
"wemux"
|
20
20
|
end
|
21
21
|
end
|
data/lib/tmuxinator/window.rb
CHANGED
@@ -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?
|
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 =
|
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 |
|
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(
|
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}
|
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
|
data/spec/factories/projects.rb
CHANGED
@@ -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, :
|
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 {
|
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 :
|
44
|
+
factory :project_with_deprecations, class: Tmuxinator::Project do
|
11
45
|
transient do
|
12
|
-
file {
|
46
|
+
file { yaml_load("spec/fixtures/sample.deprecations.yml") }
|
13
47
|
end
|
14
48
|
|
15
|
-
initialize_with { Tmuxinator::Project.new(file
|
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 :
|
60
|
+
factory :noname_project, class: Tmuxinator::Project do
|
19
61
|
transient do
|
20
|
-
file {
|
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 :
|
68
|
+
factory :nowindows_project, class: Tmuxinator::Project do
|
27
69
|
transient do
|
28
|
-
file {
|
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 :
|
76
|
+
factory :nameless_window_project, class: Tmuxinator::Project do
|
35
77
|
transient do
|
36
|
-
file {
|
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
|
data/spec/fixtures/sample.yml
CHANGED
@@ -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:
|