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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 079c5def07857f7b54737cd711899a7c529fee96
|
4
|
+
data.tar.gz: 461725febed6618763f593eec2952cbce8866368
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4860c8924f4feb57ae84f2d122a78b9680ff08b83e3e446c70c6464ced07b4e81be1e80e347a20e660d1c386f33d3a393caa585813a1d3eb78648c94c4173ec
|
7
|
+
data.tar.gz: 6b05f2ad6143fd9cd4aa15318dd8e9e9dc816a7e080cb414e468977d7a0bf7d3583f58fd36fd7e981d6ebb103f7c3690b130062980beadbc37bf6728e0bfe946
|
data/bin/mux
CHANGED
@@ -4,16 +4,13 @@ $: << File.expand_path("../../lib/", __FILE__)
|
|
4
4
|
require "thor"
|
5
5
|
require "tmuxinator"
|
6
6
|
|
7
|
-
|
8
|
-
name = ARGV[0]
|
7
|
+
name = ARGV[0] || nil
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
Tmuxinator::Cli.start
|
16
|
-
end
|
9
|
+
if ARGV.length == 0 && Tmuxinator::Config.local?
|
10
|
+
Tmuxinator::Cli.new.local
|
11
|
+
elsif name && !Tmuxinator::Cli::COMMANDS.keys.include?(name.to_sym) &&
|
12
|
+
Tmuxinator::Config.exists?(name)
|
13
|
+
Tmuxinator::Cli.new.start(name, *ARGV.drop(1))
|
17
14
|
else
|
18
15
|
Tmuxinator::Cli.start
|
19
16
|
end
|
data/bin/tmuxinator
CHANGED
@@ -4,16 +4,13 @@ $: << File.expand_path("../../lib/", __FILE__)
|
|
4
4
|
require "thor"
|
5
5
|
require "tmuxinator"
|
6
6
|
|
7
|
-
|
8
|
-
name = ARGV[0]
|
7
|
+
name = ARGV[0] || nil
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
Tmuxinator::Cli.start
|
16
|
-
end
|
9
|
+
if ARGV.length == 0 && Tmuxinator::Config.local?
|
10
|
+
Tmuxinator::Cli.new.local
|
11
|
+
elsif name && !Tmuxinator::Cli::COMMANDS.keys.include?(name.to_sym) &&
|
12
|
+
Tmuxinator::Config.exists?(name)
|
13
|
+
Tmuxinator::Cli.new.start(name, *ARGV.drop(1))
|
17
14
|
else
|
18
15
|
Tmuxinator::Cli.start
|
19
16
|
end
|
@@ -14,7 +14,7 @@ if [ "$?" -eq 1 ]; then
|
|
14
14
|
|
15
15
|
# Create the session and the first window. Manually switch to root
|
16
16
|
# directory if required to support tmux < 1.9
|
17
|
-
TMUX= <%=
|
17
|
+
TMUX= <%= tmux_new_session_command %>
|
18
18
|
<% if windows.first.root? %>
|
19
19
|
<%= windows.first.tmux_window_command_prefix %> <%= "cd #{windows.first.root}".shellescape %> C-m
|
20
20
|
<% end %>
|
@@ -71,11 +71,11 @@ if [ "$?" -eq 1 ]; then
|
|
71
71
|
fi
|
72
72
|
|
73
73
|
<%- if attach? -%>
|
74
|
-
if [ -z "$TMUX" ]; then
|
75
|
-
|
76
|
-
else
|
77
|
-
|
78
|
-
fi
|
74
|
+
if [ -z "$TMUX" ]; then
|
75
|
+
<%= tmux %> -u attach-session -t <%= name %>
|
76
|
+
else
|
77
|
+
<%= tmux %> -u switch-client -t <%= name %>
|
78
|
+
fi
|
79
79
|
<%- end -%>
|
80
80
|
|
81
81
|
<%= post %>
|
data/lib/tmuxinator/cli.rb
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
module Tmuxinator
|
2
2
|
class Cli < Thor
|
3
|
+
# By default, Thor returns exit(0) when an error occurs.
|
4
|
+
# Please see: https://github.com/tmuxinator/tmuxinator/issues/192
|
5
|
+
def self.exit_on_failure?
|
6
|
+
true
|
7
|
+
end
|
8
|
+
|
3
9
|
include Tmuxinator::Util
|
4
10
|
|
5
11
|
COMMANDS = {
|
@@ -7,9 +13,16 @@ module Tmuxinator
|
|
7
13
|
completions: "Used for shell completion",
|
8
14
|
new: "Create a new project file and open it in your editor",
|
9
15
|
open: "Alias of new",
|
10
|
-
start:
|
16
|
+
start: <<-DESC,
|
17
|
+
Start a tmux session using a project's tmuxinator config,
|
18
|
+
with an optional [ALIAS] for project reuse
|
19
|
+
DESC
|
20
|
+
local: "Start a tmux session using ./.tmuxinator.yml",
|
11
21
|
debug: "Output the shell commands that are generated by tmuxinator",
|
12
|
-
copy:
|
22
|
+
copy: <<-DESC,
|
23
|
+
Copy an existing project to a new project and open it in
|
24
|
+
your editor
|
25
|
+
DESC
|
13
26
|
delete: "Deletes given project",
|
14
27
|
implode: "Deletes all tmuxinator projects",
|
15
28
|
version: "Display installed tmuxinator version",
|
@@ -17,18 +30,19 @@ module Tmuxinator
|
|
17
30
|
list: "Lists all tmuxinator projects"
|
18
31
|
}
|
19
32
|
|
20
|
-
package_name "tmuxinator"
|
33
|
+
package_name "tmuxinator" \
|
34
|
+
unless Gem::Version.create(Thor::VERSION) < Gem::Version.create("0.18")
|
21
35
|
|
22
36
|
desc "commands", COMMANDS[:commands]
|
23
37
|
|
24
38
|
def commands(shell = nil)
|
25
39
|
out = if shell == "zsh"
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
40
|
+
COMMANDS.map do |command, desc|
|
41
|
+
"#{command}:#{desc}"
|
42
|
+
end.join("\n")
|
43
|
+
else
|
44
|
+
COMMANDS.keys.join("\n")
|
45
|
+
end
|
32
46
|
|
33
47
|
puts out
|
34
48
|
end
|
@@ -48,39 +62,100 @@ module Tmuxinator
|
|
48
62
|
map "o" => :new
|
49
63
|
map "e" => :new
|
50
64
|
map "n" => :new
|
65
|
+
method_option :local, type: :boolean,
|
66
|
+
aliases: ["-l"],
|
67
|
+
desc: "Create local project file at ./.tmuxinator.yml"
|
51
68
|
|
52
69
|
def new(name)
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
70
|
+
project_file = if options[:local]
|
71
|
+
Tmuxinator::Config::LOCAL_DEFAULT
|
72
|
+
else
|
73
|
+
Tmuxinator::Config.default_project(name)
|
74
|
+
end
|
75
|
+
unless Tmuxinator::Config.exists?(project_file)
|
76
|
+
template = Tmuxinator::Config.default? ? :default : :sample
|
77
|
+
content = File.read(Tmuxinator::Config.send(template.to_sym))
|
78
|
+
erb = Erubis::Eruby.new(content).result(binding)
|
79
|
+
File.open(project_file, "w") { |f| f.write(erb) }
|
59
80
|
end
|
60
81
|
|
61
|
-
Kernel.system("$EDITOR #{
|
82
|
+
Kernel.system("$EDITOR #{project_file}") || doctor
|
62
83
|
end
|
63
84
|
|
64
|
-
|
65
|
-
|
85
|
+
no_commands do
|
86
|
+
def create_project(project_options = {})
|
87
|
+
attach_opt = project_options[:attach]
|
88
|
+
attach = !attach_opt.nil? && attach_opt ? true : false
|
89
|
+
detach = !attach_opt.nil? && !attach_opt ? true : false
|
90
|
+
|
91
|
+
options = {
|
92
|
+
force_attach: attach,
|
93
|
+
force_detach: detach,
|
94
|
+
name: project_options[:name],
|
95
|
+
custom_name: project_options[:custom_name],
|
96
|
+
args: project_options[:args]
|
97
|
+
}
|
98
|
+
|
99
|
+
begin
|
100
|
+
Tmuxinator::Config.validate(options)
|
101
|
+
rescue => e
|
102
|
+
exit! e.message
|
103
|
+
end
|
104
|
+
end
|
66
105
|
|
67
|
-
|
68
|
-
|
106
|
+
def render_project(project)
|
107
|
+
if project.deprecations.any?
|
108
|
+
project.deprecations.each { |deprecation| say deprecation, :red }
|
109
|
+
puts
|
110
|
+
print "Press ENTER to continue."
|
111
|
+
STDIN.getc
|
112
|
+
end
|
69
113
|
|
70
|
-
|
71
|
-
project.deprecations.each { |deprecation| say deprecation, :red }
|
72
|
-
puts
|
73
|
-
print "Press ENTER to continue."
|
74
|
-
STDIN.getc
|
114
|
+
Kernel.exec(project.render)
|
75
115
|
end
|
116
|
+
end
|
76
117
|
|
77
|
-
|
118
|
+
desc "start [PROJECT] [ARGS]", COMMANDS[:start]
|
119
|
+
map "s" => :start
|
120
|
+
method_option :attach, type: :boolean,
|
121
|
+
aliases: "-a",
|
122
|
+
desc: "Attach to tmux session after creation."
|
123
|
+
method_option :name, aliases: "-n",
|
124
|
+
desc: "Give the session a different name"
|
125
|
+
|
126
|
+
def start(name, *args)
|
127
|
+
params = {
|
128
|
+
name: name,
|
129
|
+
custom_name: options[:name],
|
130
|
+
attach: options[:attach],
|
131
|
+
args: args
|
132
|
+
}
|
133
|
+
project = create_project(params)
|
134
|
+
render_project(project)
|
78
135
|
end
|
79
136
|
|
80
|
-
desc "
|
137
|
+
desc "local", COMMANDS[:local]
|
138
|
+
map "." => :local
|
139
|
+
|
140
|
+
def local
|
141
|
+
render_project(create_project(attach: options[:attach]))
|
142
|
+
end
|
81
143
|
|
82
|
-
|
83
|
-
|
144
|
+
method_option :attach, type: :boolean,
|
145
|
+
aliases: "-a",
|
146
|
+
desc: "Attach to tmux session after creation."
|
147
|
+
method_option :name, aliases: "-n",
|
148
|
+
desc: "Give the session a different name"
|
149
|
+
desc "debug [PROJECT] [ARGS]", COMMANDS[:debug]
|
150
|
+
|
151
|
+
def debug(name, *args)
|
152
|
+
params = {
|
153
|
+
name: name,
|
154
|
+
custom_name: options[:name],
|
155
|
+
attach: options[:attach],
|
156
|
+
args: args
|
157
|
+
}
|
158
|
+
project = create_project(params)
|
84
159
|
puts project.render
|
85
160
|
end
|
86
161
|
|
@@ -92,9 +167,12 @@ module Tmuxinator
|
|
92
167
|
existing_config_path = Tmuxinator::Config.project(existing)
|
93
168
|
new_config_path = Tmuxinator::Config.project(new)
|
94
169
|
|
95
|
-
exit!("Project #{existing} doesn't exist!")
|
170
|
+
exit!("Project #{existing} doesn't exist!") \
|
171
|
+
unless Tmuxinator::Config.exists?(existing)
|
96
172
|
|
97
|
-
|
173
|
+
new_exists = Tmuxinator::Config.exists?(new)
|
174
|
+
question = "#{new} already exists, would you like to overwrite it?"
|
175
|
+
if !new_exists || yes?(question, :red)
|
98
176
|
say "Overwriting #{new}" if Tmuxinator::Config.exists?(new)
|
99
177
|
FileUtils.copy_file(existing_config_path, new_config_path)
|
100
178
|
end
|
@@ -108,7 +186,7 @@ module Tmuxinator
|
|
108
186
|
|
109
187
|
def delete(project)
|
110
188
|
if Tmuxinator::Config.exists?(project)
|
111
|
-
config =
|
189
|
+
config = "#{Tmuxinator::Config.root}/#{project}.yml"
|
112
190
|
|
113
191
|
if yes?("Are you sure you want to delete #{project}?(y/n)", :red)
|
114
192
|
FileUtils.rm(config)
|
@@ -156,7 +234,7 @@ module Tmuxinator
|
|
156
234
|
yes_no Tmuxinator::Config.editor?
|
157
235
|
|
158
236
|
say "Checking if $SHELL is set ==> "
|
159
|
-
yes_no
|
237
|
+
yes_no Tmuxinator::Config.shell?
|
160
238
|
end
|
161
239
|
end
|
162
240
|
end
|
data/lib/tmuxinator/config.rb
CHANGED
@@ -1,17 +1,21 @@
|
|
1
1
|
module Tmuxinator
|
2
2
|
class Config
|
3
|
+
LOCAL_DEFAULT = "./.tmuxinator.yml".freeze
|
4
|
+
NO_LOCAL_FILE_MSG = "Project file at ./.tmuxinator.yml doesn't exist."
|
5
|
+
|
3
6
|
class << self
|
4
7
|
def root
|
5
|
-
|
6
|
-
"#{ENV[
|
8
|
+
root_dir = File.expand_path("~/.tmuxinator")
|
9
|
+
Dir.mkdir("#{ENV['HOME']}/.tmuxinator") unless File.directory?(root_dir)
|
10
|
+
"#{ENV['HOME']}/.tmuxinator"
|
7
11
|
end
|
8
12
|
|
9
13
|
def sample
|
10
|
-
"
|
14
|
+
asset_path "sample.yml"
|
11
15
|
end
|
12
16
|
|
13
17
|
def default
|
14
|
-
"#{ENV[
|
18
|
+
"#{ENV['HOME']}/.tmuxinator/default.yml"
|
15
19
|
end
|
16
20
|
|
17
21
|
def default?
|
@@ -42,18 +46,33 @@ module Tmuxinator
|
|
42
46
|
File.exists?(project(name))
|
43
47
|
end
|
44
48
|
|
45
|
-
def
|
49
|
+
def project_in_root(name)
|
46
50
|
projects = Dir.glob("#{root}/**/*.yml")
|
47
|
-
|
48
|
-
|
51
|
+
projects.detect { |project| File.basename(project, ".yml") == name }
|
52
|
+
end
|
53
|
+
|
54
|
+
def local?
|
55
|
+
project_in_local
|
56
|
+
end
|
57
|
+
|
58
|
+
def project_in_local
|
59
|
+
[LOCAL_DEFAULT].detect { |f| File.exists?(f) }
|
60
|
+
end
|
61
|
+
|
62
|
+
def default_project(name)
|
63
|
+
"#{root}/#{name}.yml"
|
64
|
+
end
|
65
|
+
|
66
|
+
def project(name)
|
67
|
+
project_in_root(name) || project_in_local || default_project(name)
|
49
68
|
end
|
50
69
|
|
51
70
|
def template
|
52
|
-
"
|
71
|
+
asset_path "template.erb"
|
53
72
|
end
|
54
73
|
|
55
74
|
def wemux_template
|
56
|
-
"
|
75
|
+
asset_path "wemux_template.erb"
|
57
76
|
end
|
58
77
|
|
59
78
|
def configs
|
@@ -62,34 +81,27 @@ module Tmuxinator
|
|
62
81
|
end
|
63
82
|
end
|
64
83
|
|
65
|
-
def validate(
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
unless project.windows?
|
83
|
-
puts "Your project file should include some windows."
|
84
|
-
exit!
|
85
|
-
end
|
84
|
+
def validate(options = {})
|
85
|
+
name = options[:name]
|
86
|
+
options[:force_attach] ||= false
|
87
|
+
options[:force_detach] ||= false
|
88
|
+
|
89
|
+
project_file = if name.nil?
|
90
|
+
raise NO_LOCAL_FILE_MSG \
|
91
|
+
unless Tmuxinator::Config.local?
|
92
|
+
project_in_local
|
93
|
+
else
|
94
|
+
raise "Project #{name} doesn't exist." \
|
95
|
+
unless Tmuxinator::Config.exists?(name)
|
96
|
+
Tmuxinator::Config.project(name)
|
97
|
+
end
|
98
|
+
Tmuxinator::Project.load(project_file, options).validate!
|
99
|
+
end
|
86
100
|
|
87
|
-
|
88
|
-
puts "Your project file didn't specify a 'project_name'"
|
89
|
-
exit!
|
90
|
-
end
|
101
|
+
private
|
91
102
|
|
92
|
-
|
103
|
+
def asset_path(asset)
|
104
|
+
"#{File.dirname(__FILE__)}/assets/#{asset}"
|
93
105
|
end
|
94
106
|
end
|
95
107
|
end
|
data/lib/tmuxinator/pane.rb
CHANGED
@@ -10,27 +10,43 @@ module Tmuxinator
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def tmux_window_and_pane_target
|
13
|
-
|
13
|
+
x = tab.index + project.base_index
|
14
|
+
y = index + project.base_index
|
15
|
+
"#{project.name}:#{x}.#{y}"
|
14
16
|
end
|
15
17
|
|
16
18
|
def tmux_pre_command
|
17
19
|
return unless tab.pre
|
18
20
|
|
19
|
-
|
21
|
+
t = tmux_window_and_pane_target
|
22
|
+
e = tab.pre.shellescape
|
23
|
+
"#{project.tmux} send-keys -t #{t} #{e} C-m"
|
20
24
|
end
|
21
25
|
|
22
26
|
def tmux_pre_window_command
|
23
27
|
return unless project.pre_window
|
24
28
|
|
25
|
-
|
29
|
+
t = tmux_window_and_pane_target
|
30
|
+
e = project.pre_window.shellescape
|
31
|
+
"#{project.tmux} send-keys -t #{t} #{e} C-m"
|
26
32
|
end
|
27
33
|
|
28
34
|
def tmux_main_command(command)
|
29
|
-
|
35
|
+
if command
|
36
|
+
x = tab.index + project.base_index
|
37
|
+
y = index + tab.project.base_index
|
38
|
+
e = command.shellescape
|
39
|
+
n = project.name
|
40
|
+
"#{project.tmux} send-keys -t #{n}:#{x}.#{y} #{e} C-m"
|
41
|
+
else
|
42
|
+
""
|
43
|
+
end
|
30
44
|
end
|
31
45
|
|
32
46
|
def tmux_split_command
|
33
|
-
path = tab.root?
|
47
|
+
path = if tab.root?
|
48
|
+
"#{Tmuxinator::Config.default_path_option} #{tab.root}"
|
49
|
+
end
|
34
50
|
"#{project.tmux} splitw #{path} -t #{tab.tmux_window_target}"
|
35
51
|
end
|
36
52
|
|