tmuxinator 3.1.1 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/tmuxinator +3 -1
- data/completion/tmuxinator.bash +1 -2
- data/completion/tmuxinator.fish +0 -2
- data/lib/tmuxinator/assets/template.erb +12 -0
- data/lib/tmuxinator/cli.rb +10 -9
- data/lib/tmuxinator/config.rb +19 -7
- data/lib/tmuxinator/deprecations.rb +2 -0
- data/lib/tmuxinator/doctor.rb +2 -0
- data/lib/tmuxinator/hooks/project.rb +5 -3
- data/lib/tmuxinator/hooks.rb +2 -0
- data/lib/tmuxinator/pane.rb +7 -5
- data/lib/tmuxinator/project.rb +68 -11
- data/lib/tmuxinator/tmux_version.rb +4 -2
- data/lib/tmuxinator/util.rb +2 -0
- data/lib/tmuxinator/version.rb +3 -1
- data/lib/tmuxinator/wemux_support.rb +2 -0
- data/lib/tmuxinator/window.rb +2 -0
- data/lib/tmuxinator.rb +3 -1
- data/spec/factories/projects.rb +2 -0
- data/spec/lib/tmuxinator/cli_spec.rb +16 -14
- data/spec/lib/tmuxinator/config_spec.rb +46 -20
- data/spec/lib/tmuxinator/doctor_spec.rb +2 -0
- data/spec/lib/tmuxinator/hooks/project_spec.rb +2 -0
- data/spec/lib/tmuxinator/hooks_spec.rb +2 -0
- data/spec/lib/tmuxinator/pane_spec.rb +4 -2
- data/spec/lib/tmuxinator/project_spec.rb +75 -1
- data/spec/lib/tmuxinator/util_spec.rb +2 -0
- data/spec/lib/tmuxinator/wemux_support_spec.rb +2 -0
- data/spec/lib/tmuxinator/window_spec.rb +2 -0
- data/spec/matchers/pane_matcher.rb +2 -0
- data/spec/spec_helper.rb +3 -1
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b548f97e14ad874cb4ef91cb7e8380419943e9027786936679d9ab545ab94d47
|
4
|
+
data.tar.gz: 5fc432b4f26221a1f2f08bb7478383dc2f279a84221e0befc2ed41f9fb9de55b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4ca459d020b59ffd5ecd5862b93b8e182526b0b819411989da94b5801d5759ba79cea1145d1a748c597060321072a7e38bd525de77749b62dde9b51fdcf02f4
|
7
|
+
data.tar.gz: 388caf62bd2441710ca97ef1be6be692f72cd52b86c3076ffedfc4ed48b90b6137d33e887ac2742f0288a47bafef12518118413800a022a7c17bd7f7620e9115
|
data/bin/tmuxinator
CHANGED
data/completion/tmuxinator.bash
CHANGED
data/completion/tmuxinator.fish
CHANGED
@@ -20,5 +20,3 @@ complete -f -c $__fish_tmuxinator_program_cmd -n '__fish_tmuxinator_using_comman
|
|
20
20
|
complete -f -c $__fish_tmuxinator_program_cmd -n '__fish_tmuxinator_using_command open' -a "(__fish_tmuxinator_program completions open)"
|
21
21
|
complete -f -c $__fish_tmuxinator_program_cmd -n '__fish_tmuxinator_using_command copy' -a "(__fish_tmuxinator_program completions copy)"
|
22
22
|
complete -f -c $__fish_tmuxinator_program_cmd -n '__fish_tmuxinator_using_command delete' -a "(__fish_tmuxinator_program completions delete)"
|
23
|
-
|
24
|
-
abbr --add mux "tmuxinator"
|
@@ -33,6 +33,18 @@ cd <%= root || "." %>
|
|
33
33
|
<% end %>
|
34
34
|
<% end %>
|
35
35
|
|
36
|
+
<% if enable_pane_titles? %>
|
37
|
+
<% if Tmuxinator::Config.version < 2.6 %>
|
38
|
+
<%= pane_titles_not_supported_warning %>
|
39
|
+
<%- else -%>
|
40
|
+
<% if pane_title_position? && !pane_title_position_valid? %>
|
41
|
+
<%= pane_title_position_not_valid_warning %>
|
42
|
+
<% end %>
|
43
|
+
<%= tmux_set_pane_title_position %>
|
44
|
+
<%= tmux_set_pane_title_format %>
|
45
|
+
<% end %>
|
46
|
+
<% end %>
|
47
|
+
|
36
48
|
# Create other windows.
|
37
49
|
<% windows.drop(1).each do |window| %>
|
38
50
|
<%= window.tmux_new_window_command %>
|
data/lib/tmuxinator/cli.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "open3"
|
2
4
|
|
3
5
|
module Tmuxinator
|
@@ -167,9 +169,8 @@ module Tmuxinator
|
|
167
169
|
end
|
168
170
|
|
169
171
|
def generate_project_file(name, path)
|
170
|
-
|
171
|
-
|
172
|
-
erb = Erubis::Eruby.new(content).result(binding)
|
172
|
+
config = Tmuxinator::Config.default_or_sample
|
173
|
+
erb = Tmuxinator::Project.render_template(config, binding)
|
173
174
|
File.open(path, "w") { |f| f.write(erb) }
|
174
175
|
path
|
175
176
|
end
|
@@ -194,7 +195,7 @@ module Tmuxinator
|
|
194
195
|
|
195
196
|
begin
|
196
197
|
Tmuxinator::Config.validate(options)
|
197
|
-
rescue => e
|
198
|
+
rescue StandardError => e
|
198
199
|
exit! e.message
|
199
200
|
end
|
200
201
|
end
|
@@ -341,12 +342,12 @@ module Tmuxinator
|
|
341
342
|
new_config_path = Tmuxinator::Config.project(new)
|
342
343
|
|
343
344
|
exit!("Project #{existing} doesn't exist!") \
|
344
|
-
unless Tmuxinator::Config.
|
345
|
+
unless Tmuxinator::Config.exist?(name: existing)
|
345
346
|
|
346
|
-
new_exists = Tmuxinator::Config.
|
347
|
+
new_exists = Tmuxinator::Config.exist?(name: new)
|
347
348
|
question = "#{new} already exists, would you like to overwrite it?"
|
348
349
|
if !new_exists || yes?(question, :red)
|
349
|
-
say "Overwriting #{new}" if Tmuxinator::Config.
|
350
|
+
say "Overwriting #{new}" if Tmuxinator::Config.exist?(name: new)
|
350
351
|
FileUtils.copy_file(existing_config_path, new_config_path)
|
351
352
|
end
|
352
353
|
|
@@ -359,7 +360,7 @@ module Tmuxinator
|
|
359
360
|
|
360
361
|
def delete(*projects)
|
361
362
|
projects.each do |project|
|
362
|
-
if Tmuxinator::Config.
|
363
|
+
if Tmuxinator::Config.exist?(name: project)
|
363
364
|
config = Tmuxinator::Config.project(project)
|
364
365
|
|
365
366
|
if yes?("Are you sure you want to delete #{project}?(y/n)", :red)
|
@@ -433,7 +434,7 @@ module Tmuxinator
|
|
433
434
|
if args.empty? && Tmuxinator::Config.local?
|
434
435
|
Tmuxinator::Cli.new.local
|
435
436
|
elsif name && !Tmuxinator::Cli::RESERVED_COMMANDS.include?(name) &&
|
436
|
-
Tmuxinator::Config.
|
437
|
+
Tmuxinator::Config.exist?(name: name)
|
437
438
|
Tmuxinator::Cli.new.start(name, *args.drop(1))
|
438
439
|
else
|
439
440
|
Tmuxinator::Cli.start(args)
|
data/lib/tmuxinator/config.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Tmuxinator
|
2
4
|
class Config
|
3
5
|
LOCAL_DEFAULTS = ["./.tmuxinator.yml", "./.tmuxinator.yaml"].freeze
|
4
|
-
NO_LOCAL_FILE_MSG =
|
5
|
-
|
6
|
-
NO_PROJECT_FOUND_MSG = "Project could not be found.".freeze
|
6
|
+
NO_LOCAL_FILE_MSG = "Project file at ./.tmuxinator.yml doesn't exist."
|
7
|
+
NO_PROJECT_FOUND_MSG = "Project could not be found."
|
7
8
|
TMUX_MASTER_VERSION = Float::INFINITY
|
8
9
|
|
9
10
|
class << self
|
@@ -12,6 +13,7 @@ module Tmuxinator
|
|
12
13
|
return environment if environment?
|
13
14
|
return xdg if xdg?
|
14
15
|
return home if home?
|
16
|
+
|
15
17
|
# No project directory specified or existent, default to XDG:
|
16
18
|
FileUtils::mkdir_p(xdg)
|
17
19
|
xdg
|
@@ -40,6 +42,7 @@ module Tmuxinator
|
|
40
42
|
def environment
|
41
43
|
environment = ENV["TMUXINATOR_CONFIG"]
|
42
44
|
return "" if environment.to_s.empty? # variable is unset (nil) or blank
|
45
|
+
|
43
46
|
FileUtils::mkdir_p(environment) unless File.directory?(environment)
|
44
47
|
environment
|
45
48
|
end
|
@@ -48,6 +51,10 @@ module Tmuxinator
|
|
48
51
|
File.directory?(environment)
|
49
52
|
end
|
50
53
|
|
54
|
+
def default_or_sample
|
55
|
+
default? ? default : sample
|
56
|
+
end
|
57
|
+
|
51
58
|
def sample
|
52
59
|
asset_path "sample.yml"
|
53
60
|
end
|
@@ -57,7 +64,7 @@ module Tmuxinator
|
|
57
64
|
end
|
58
65
|
|
59
66
|
def default?
|
60
|
-
|
67
|
+
exist?(name: "default")
|
61
68
|
end
|
62
69
|
|
63
70
|
def version
|
@@ -76,9 +83,10 @@ module Tmuxinator
|
|
76
83
|
version && version < 1.8 ? "default-path" : "-c"
|
77
84
|
end
|
78
85
|
|
79
|
-
def
|
86
|
+
def exist?(name: nil, path: nil)
|
80
87
|
return File.exist?(path) if path
|
81
88
|
return File.exist?(project(name)) if name
|
89
|
+
|
82
90
|
false
|
83
91
|
end
|
84
92
|
|
@@ -140,21 +148,24 @@ module Tmuxinator
|
|
140
148
|
|
141
149
|
def valid_project_config?(project_config)
|
142
150
|
return false unless project_config
|
143
|
-
unless
|
151
|
+
unless exist?(path: project_config)
|
144
152
|
raise "Project config (#{project_config}) doesn't exist."
|
145
153
|
end
|
154
|
+
|
146
155
|
true
|
147
156
|
end
|
148
157
|
|
149
158
|
def valid_local_project?(name)
|
150
159
|
return false if name
|
151
160
|
raise NO_LOCAL_FILE_MSG unless local?
|
161
|
+
|
152
162
|
true
|
153
163
|
end
|
154
164
|
|
155
165
|
def valid_standard_project?(name)
|
156
166
|
return false unless name
|
157
|
-
raise "Project #{name} doesn't exist." unless
|
167
|
+
raise "Project #{name} doesn't exist." unless exist?(name: name)
|
168
|
+
|
158
169
|
true
|
159
170
|
end
|
160
171
|
|
@@ -193,6 +204,7 @@ module Tmuxinator
|
|
193
204
|
# recursively searching 'directory'
|
194
205
|
def project_in(directory, name)
|
195
206
|
return nil if String(directory).empty?
|
207
|
+
|
196
208
|
projects = Dir.glob("#{directory}/**/*.{yml,yaml}").sort
|
197
209
|
projects.detect { |project| File.basename(project, ".*") == name }
|
198
210
|
end
|
data/lib/tmuxinator/doctor.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Tmuxinator
|
2
4
|
module Hooks
|
3
5
|
module Project
|
@@ -37,6 +39,6 @@ module Tmuxinator
|
|
37
39
|
# this method can only be used from inside Tmuxinator::Project
|
38
40
|
Tmuxinator::Hooks.commands_from self, "on_project_stop"
|
39
41
|
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/tmuxinator/hooks.rb
CHANGED
data/lib/tmuxinator/pane.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Tmuxinator
|
2
4
|
class Pane
|
3
5
|
attr_reader :commands, :project, :index, :tab, :title
|
@@ -7,7 +9,7 @@ module Tmuxinator
|
|
7
9
|
@index = index
|
8
10
|
@project = project
|
9
11
|
@tab = tab
|
10
|
-
@title = title
|
12
|
+
@title = title.to_s.shellescape unless title.nil?
|
11
13
|
end
|
12
14
|
|
13
15
|
def tmux_window_and_pane_target
|
@@ -61,12 +63,12 @@ module Tmuxinator
|
|
61
63
|
|
62
64
|
private
|
63
65
|
|
64
|
-
def _send_target(
|
65
|
-
_send_keys(tmux_window_and_pane_target,
|
66
|
+
def _send_target(keys)
|
67
|
+
_send_keys(tmux_window_and_pane_target, keys)
|
66
68
|
end
|
67
69
|
|
68
|
-
def _send_keys(
|
69
|
-
"#{project.tmux} send-keys -t #{
|
70
|
+
def _send_keys(target, keys)
|
71
|
+
"#{project.tmux} send-keys -t #{target} #{keys} C-m"
|
70
72
|
end
|
71
73
|
|
72
74
|
def _set_title(title)
|
data/lib/tmuxinator/project.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Tmuxinator
|
2
4
|
class Project
|
3
5
|
include Tmuxinator::Util
|
@@ -41,16 +43,14 @@ module Tmuxinator
|
|
41
43
|
|
42
44
|
def self.load(path, options = {})
|
43
45
|
yaml = begin
|
44
|
-
raw_content = File.read(path)
|
45
|
-
|
46
46
|
args = options[:args] || []
|
47
47
|
@settings = parse_settings(args)
|
48
48
|
@args = args
|
49
49
|
|
50
|
-
content =
|
50
|
+
content = render_template(path, binding)
|
51
51
|
YAML.safe_load(content, aliases: true)
|
52
|
-
|
53
|
-
|
52
|
+
rescue SyntaxError, StandardError => error
|
53
|
+
raise "Failed to parse config file: #{error.message}"
|
54
54
|
end
|
55
55
|
|
56
56
|
new(yaml, options)
|
@@ -73,6 +73,7 @@ module Tmuxinator
|
|
73
73
|
unless windows?
|
74
74
|
raise "Your project file didn't specify a 'project_name'" \
|
75
75
|
unless name?
|
76
|
+
|
76
77
|
self
|
77
78
|
end
|
78
79
|
|
@@ -103,7 +104,7 @@ module Tmuxinator
|
|
103
104
|
|
104
105
|
def self.render_template(template, bndg)
|
105
106
|
content = File.read(template)
|
106
|
-
|
107
|
+
bndg.eval(Erubi::Engine.new(content).src)
|
107
108
|
end
|
108
109
|
|
109
110
|
def windows
|
@@ -239,8 +240,8 @@ module Tmuxinator
|
|
239
240
|
!name.nil?
|
240
241
|
end
|
241
242
|
|
242
|
-
def window(
|
243
|
-
"#{name}:#{
|
243
|
+
def window(index)
|
244
|
+
"#{name}:#{index}"
|
244
245
|
end
|
245
246
|
|
246
247
|
def send_pane_command(cmd, window_index, _pane_index)
|
@@ -336,6 +337,42 @@ module Tmuxinator
|
|
336
337
|
"#{tmux} kill-session -t #{name}"
|
337
338
|
end
|
338
339
|
|
340
|
+
def enable_pane_titles?
|
341
|
+
yaml["enable_pane_titles"]
|
342
|
+
end
|
343
|
+
|
344
|
+
def tmux_set_pane_title_position
|
345
|
+
if pane_title_position? && pane_title_position_valid?
|
346
|
+
"#{tmux} set pane-border-status #{yaml['pane_title_position']}"
|
347
|
+
else
|
348
|
+
"#{tmux} set pane-border-status top"
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
def tmux_set_pane_title_format
|
353
|
+
if pane_title_format?
|
354
|
+
"#{tmux} set pane-border-format \"#{yaml['pane_title_format']}\""
|
355
|
+
else
|
356
|
+
"#{tmux} set pane-border-format \"\#{pane_index}: \#{pane_title}\""
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
def pane_title_position_not_valid_warning
|
361
|
+
print_warning(
|
362
|
+
"The specified pane title position " +
|
363
|
+
"\"#{yaml['pane_title_position']}\" is not valid. " +
|
364
|
+
"Please choose one of: top, bottom, or off."
|
365
|
+
)
|
366
|
+
end
|
367
|
+
|
368
|
+
def pane_titles_not_supported_warning
|
369
|
+
print_warning(
|
370
|
+
"You have enabled pane titles in your configuration, " +
|
371
|
+
"but the feature is not supported by your version of tmux.\n" +
|
372
|
+
"Please consider upgrading to a version that supports it (tmux >=2.6)."
|
373
|
+
)
|
374
|
+
end
|
375
|
+
|
339
376
|
private
|
340
377
|
|
341
378
|
def blank?(object)
|
@@ -349,9 +386,10 @@ module Tmuxinator
|
|
349
386
|
def extract_tmux_config
|
350
387
|
options_hash = {}
|
351
388
|
|
352
|
-
|
353
|
-
|
354
|
-
|
389
|
+
`#{show_tmux_options}`.
|
390
|
+
encode("UTF-8", invalid: :replace).
|
391
|
+
split("\n").
|
392
|
+
map do |entry|
|
355
393
|
key, value = entry.split("\s")
|
356
394
|
options_hash[key] = value
|
357
395
|
options_hash
|
@@ -381,5 +419,24 @@ module Tmuxinator
|
|
381
419
|
def wemux?
|
382
420
|
yaml["tmux_command"] == "wemux"
|
383
421
|
end
|
422
|
+
|
423
|
+
def pane_title_position?
|
424
|
+
yaml["pane_title_position"]
|
425
|
+
end
|
426
|
+
|
427
|
+
def pane_title_position_valid?
|
428
|
+
["top", "bottom", "off"].include? yaml["pane_title_position"]
|
429
|
+
end
|
430
|
+
|
431
|
+
def pane_title_format?
|
432
|
+
yaml["pane_title_format"]
|
433
|
+
end
|
434
|
+
|
435
|
+
def print_warning(message)
|
436
|
+
yellow = '\033[1;33m'
|
437
|
+
no_color = '\033[0m'
|
438
|
+
msg = "WARNING: #{message}\n"
|
439
|
+
"printf \"#{yellow}#{msg}#{no_color}\""
|
440
|
+
end
|
384
441
|
end
|
385
442
|
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Tmuxinator
|
2
4
|
module TmuxVersion
|
3
5
|
SUPPORTED_TMUX_VERSIONS = [
|
4
|
-
|
6
|
+
3.4,
|
5
7
|
"3.3a",
|
6
8
|
3.3,
|
7
9
|
"3.2a",
|
@@ -29,7 +31,7 @@ module Tmuxinator
|
|
29
31
|
1.6,
|
30
32
|
1.5,
|
31
33
|
].freeze
|
32
|
-
UNSUPPORTED_VERSION_MSG = <<-MSG
|
34
|
+
UNSUPPORTED_VERSION_MSG = <<-MSG
|
33
35
|
WARNING: You are running tmuxinator with an unsupported version of tmux.
|
34
36
|
Please consider using a supported version:
|
35
37
|
(#{SUPPORTED_TMUX_VERSIONS.join(', ')})
|
data/lib/tmuxinator/util.rb
CHANGED
data/lib/tmuxinator/version.rb
CHANGED
data/lib/tmuxinator/window.rb
CHANGED
data/lib/tmuxinator.rb
CHANGED
data/spec/factories/projects.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "spec_helper"
|
2
4
|
|
3
5
|
describe Tmuxinator::Cli do
|
@@ -15,7 +17,7 @@ describe Tmuxinator::Cli do
|
|
15
17
|
File.new(local_project_path, "w").tap do |f|
|
16
18
|
f.write content
|
17
19
|
end.close
|
18
|
-
expect(File.
|
20
|
+
expect(File.exist?(local_project_path)).to be_truthy
|
19
21
|
expect(File.read(local_project_path)).to eq content
|
20
22
|
end
|
21
23
|
|
@@ -26,7 +28,7 @@ describe Tmuxinator::Cli do
|
|
26
28
|
|
27
29
|
subject(:cli) { described_class }
|
28
30
|
|
29
|
-
let(:fixtures_dir) { File.expand_path("
|
31
|
+
let(:fixtures_dir) { File.expand_path("../../fixtures", __dir__) }
|
30
32
|
let(:project) { FactoryBot.build(:project) }
|
31
33
|
let(:project_config) do
|
32
34
|
File.join(fixtures_dir, "sample_with_project_config.yml")
|
@@ -93,7 +95,7 @@ describe Tmuxinator::Cli do
|
|
93
95
|
context "a tmuxinator project name" do
|
94
96
|
before do
|
95
97
|
expect(Tmuxinator::Config).to \
|
96
|
-
receive(:
|
98
|
+
receive(:exist?).with(name: arg1) { true }
|
97
99
|
end
|
98
100
|
|
99
101
|
it "should call #start" do
|
@@ -127,7 +129,7 @@ describe Tmuxinator::Cli do
|
|
127
129
|
context "something else" do
|
128
130
|
before do
|
129
131
|
expect(Tmuxinator::Config).to \
|
130
|
-
receive(:
|
132
|
+
receive(:exist?).with(name: arg1) { false }
|
131
133
|
end
|
132
134
|
|
133
135
|
it "should call ::start" do
|
@@ -622,7 +624,7 @@ describe Tmuxinator::Cli do
|
|
622
624
|
describe "#copy" do
|
623
625
|
before do
|
624
626
|
ARGV.replace(["copy", "foo", "bar"])
|
625
|
-
allow(Tmuxinator::Config).to receive(:
|
627
|
+
allow(Tmuxinator::Config).to receive(:exist?) { true }
|
626
628
|
end
|
627
629
|
|
628
630
|
context "new project already exists" do
|
@@ -638,7 +640,7 @@ describe Tmuxinator::Cli do
|
|
638
640
|
|
639
641
|
context "existing project doesn't exist" do
|
640
642
|
before do
|
641
|
-
allow(Tmuxinator::Config).to receive(:
|
643
|
+
allow(Tmuxinator::Config).to receive(:exist?) { false }
|
642
644
|
end
|
643
645
|
|
644
646
|
it "exit with error code" do
|
@@ -714,7 +716,7 @@ describe Tmuxinator::Cli do
|
|
714
716
|
|
715
717
|
context "project exists" do
|
716
718
|
before do
|
717
|
-
allow(Tmuxinator::Config).to receive(:
|
719
|
+
allow(Tmuxinator::Config).to receive(:exist?) { true }
|
718
720
|
end
|
719
721
|
|
720
722
|
it "deletes the project" do
|
@@ -725,7 +727,7 @@ describe Tmuxinator::Cli do
|
|
725
727
|
|
726
728
|
context "local project exists" do
|
727
729
|
before do
|
728
|
-
allow(Tmuxinator::Config).to receive(:
|
730
|
+
allow(Tmuxinator::Config).to receive(:exist?) { true }
|
729
731
|
expect(Tmuxinator::Config).to receive(:project) { "local" }
|
730
732
|
end
|
731
733
|
|
@@ -737,7 +739,7 @@ describe Tmuxinator::Cli do
|
|
737
739
|
|
738
740
|
context "project doesn't exist" do
|
739
741
|
before do
|
740
|
-
allow(Tmuxinator::Config).to receive(:
|
742
|
+
allow(Tmuxinator::Config).to receive(:exist?) { false }
|
741
743
|
end
|
742
744
|
|
743
745
|
it "outputs an error message" do
|
@@ -754,7 +756,7 @@ describe Tmuxinator::Cli do
|
|
754
756
|
|
755
757
|
context "all projects exist" do
|
756
758
|
before do
|
757
|
-
allow(Tmuxinator::Config).to receive(:
|
759
|
+
allow(Tmuxinator::Config).to receive(:exist?).and_return(true)
|
758
760
|
end
|
759
761
|
|
760
762
|
it "deletes the projects" do
|
@@ -765,10 +767,10 @@ describe Tmuxinator::Cli do
|
|
765
767
|
|
766
768
|
context "only one project exists" do
|
767
769
|
before do
|
768
|
-
allow(Tmuxinator::Config).to receive(:
|
770
|
+
allow(Tmuxinator::Config).to receive(:exist?).with(name: "foo") {
|
769
771
|
true
|
770
772
|
}
|
771
|
-
allow(Tmuxinator::Config).to receive(:
|
773
|
+
allow(Tmuxinator::Config).to receive(:exist?).with(name: "bar") {
|
772
774
|
false
|
773
775
|
}
|
774
776
|
end
|
@@ -785,7 +787,7 @@ describe Tmuxinator::Cli do
|
|
785
787
|
|
786
788
|
context "all projects do not exist" do
|
787
789
|
before do
|
788
|
-
allow(Tmuxinator::Config).to receive(:
|
790
|
+
allow(Tmuxinator::Config).to receive(:exist?).and_return(false)
|
789
791
|
end
|
790
792
|
|
791
793
|
it "outputs multiple error messages" do
|
@@ -952,7 +954,7 @@ describe Tmuxinator::Cli do
|
|
952
954
|
let(:name) { "sample" }
|
953
955
|
let(:custom_name) { nil }
|
954
956
|
let(:cli_options) { {} }
|
955
|
-
let(:path) { File.expand_path("
|
957
|
+
let(:path) { File.expand_path("../../fixtures", __dir__) }
|
956
958
|
|
957
959
|
shared_examples_for :a_proper_project do
|
958
960
|
it "should create a valid project" do
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "spec_helper"
|
2
4
|
|
3
5
|
describe Tmuxinator::Config do
|
4
|
-
let(:fixtures_dir) { File.expand_path("
|
6
|
+
let(:fixtures_dir) { File.expand_path("../../fixtures", __dir__) }
|
5
7
|
let(:xdg_config_dir) { "#{fixtures_dir}/xdg-tmuxinator" }
|
6
8
|
let(:home_config_dir) { "#{fixtures_dir}/dot-tmuxinator" }
|
7
9
|
|
@@ -150,6 +152,30 @@ describe Tmuxinator::Config do
|
|
150
152
|
end
|
151
153
|
end
|
152
154
|
|
155
|
+
describe "#default_or_sample" do
|
156
|
+
context "with default? true" do
|
157
|
+
before do
|
158
|
+
allow(described_class).to receive(:default?).and_return true
|
159
|
+
allow(described_class).to receive(:default).and_return("default_path")
|
160
|
+
end
|
161
|
+
|
162
|
+
it "gets the default config when it exists" do
|
163
|
+
expect(described_class.default_or_sample).to eq "default_path"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
context "with default? false" do
|
168
|
+
before do
|
169
|
+
allow(described_class).to receive(:default?)
|
170
|
+
allow(described_class).to receive(:sample).and_return("sample_path")
|
171
|
+
end
|
172
|
+
|
173
|
+
it "falls back to the sample config when the default is missing" do
|
174
|
+
expect(described_class.default_or_sample).to eq "sample_path"
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
153
179
|
describe "#version" do
|
154
180
|
subject { described_class.version }
|
155
181
|
|
@@ -160,25 +186,25 @@ describe Tmuxinator::Config do
|
|
160
186
|
end
|
161
187
|
|
162
188
|
version_mapping = {
|
163
|
-
"0.8"
|
164
|
-
"1.0"
|
165
|
-
"1.9"
|
166
|
-
"1.9a"
|
167
|
-
"2.4"
|
168
|
-
"2.9a"
|
169
|
-
"3.0-rc5"
|
189
|
+
"0.8" => 0.8,
|
190
|
+
"1.0" => 1.0,
|
191
|
+
"1.9" => 1.9,
|
192
|
+
"1.9a" => 1.9,
|
193
|
+
"2.4" => 2.4,
|
194
|
+
"2.9a" => 2.9,
|
195
|
+
"3.0-rc5" => 3.0,
|
170
196
|
"next-3.1" => 3.1,
|
171
|
-
"master"
|
197
|
+
"master" => Float::INFINITY,
|
172
198
|
# Failsafes
|
173
|
-
"foobar"
|
174
|
-
"-123-"
|
175
|
-
"5935"
|
176
|
-
""
|
177
|
-
"!@#^%"
|
178
|
-
"2.9ä"
|
179
|
-
"v3.5"
|
180
|
-
"v3.12.0"
|
181
|
-
"v3.12.5"
|
199
|
+
"foobar" => 0.0,
|
200
|
+
"-123-" => 123.0,
|
201
|
+
"5935" => 5935.0,
|
202
|
+
"" => 0.0,
|
203
|
+
"!@#^%" => 0.0,
|
204
|
+
"2.9ä" => 2.9,
|
205
|
+
"v3.5" => 3.5,
|
206
|
+
"v3.12.0" => 3.12,
|
207
|
+
"v3.12.5" => 3.12
|
182
208
|
}.freeze
|
183
209
|
|
184
210
|
version_mapping.each do |string_version, parsed_numeric_version|
|
@@ -262,14 +288,14 @@ describe Tmuxinator::Config do
|
|
262
288
|
end
|
263
289
|
end
|
264
290
|
|
265
|
-
describe "#
|
291
|
+
describe "#exist?" do
|
266
292
|
before do
|
267
293
|
allow(File).to receive_messages(exist?: true)
|
268
294
|
allow(described_class).to receive_messages(project: "")
|
269
295
|
end
|
270
296
|
|
271
297
|
it "checks if the given project exists" do
|
272
|
-
expect(described_class.
|
298
|
+
expect(described_class.exist?(name: "test")).to be_truthy
|
273
299
|
end
|
274
300
|
end
|
275
301
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "spec_helper"
|
2
4
|
|
3
5
|
describe Tmuxinator::Pane do
|
@@ -10,7 +12,7 @@ describe Tmuxinator::Pane do
|
|
10
12
|
let(:project) { double }
|
11
13
|
let(:window) { double }
|
12
14
|
let(:commands) { ["vim", "bash"] }
|
13
|
-
let(:title) { "test" }
|
15
|
+
let(:title) { "test (a test)" }
|
14
16
|
|
15
17
|
before do
|
16
18
|
allow(project).to receive(:name).and_return "foo"
|
@@ -39,7 +41,7 @@ describe Tmuxinator::Pane do
|
|
39
41
|
|
40
42
|
it "sets pane title" do
|
41
43
|
expect(subject.tmux_set_title).to eql(
|
42
|
-
"tmux select-pane -t foo:0.1 -T test"
|
44
|
+
"tmux select-pane -t foo:0.1 -T test\\ \\(a\\ test\\)"
|
43
45
|
)
|
44
46
|
end
|
45
47
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "spec_helper"
|
2
4
|
|
3
5
|
describe Tmuxinator::Project do
|
@@ -589,7 +591,7 @@ describe Tmuxinator::Project do
|
|
589
591
|
end
|
590
592
|
|
591
593
|
describe "::load" do
|
592
|
-
let(:path) { File.expand_path("
|
594
|
+
let(:path) { File.expand_path("../../fixtures/sample.yml", __dir__) }
|
593
595
|
let(:options) { {} }
|
594
596
|
|
595
597
|
it "should raise if the project file doesn't parse" do
|
@@ -635,4 +637,76 @@ describe Tmuxinator::Project do
|
|
635
637
|
end.to raise_error RuntimeError, %r{didn't.specify.a.'project_name'}
|
636
638
|
end
|
637
639
|
end
|
640
|
+
|
641
|
+
describe "#pane_titles" do
|
642
|
+
before do
|
643
|
+
allow(project).to receive(:tmux).and_return "tmux"
|
644
|
+
end
|
645
|
+
|
646
|
+
context "pane_titles not enabled" do
|
647
|
+
before { project.yaml["enable_pane_titles"] = false }
|
648
|
+
|
649
|
+
it "returns false" do
|
650
|
+
expect(project.enable_pane_titles?).to be false
|
651
|
+
end
|
652
|
+
end
|
653
|
+
|
654
|
+
context "pane_titles enabled" do
|
655
|
+
before { project.yaml["enable_pane_titles"] = true }
|
656
|
+
|
657
|
+
it "returns true" do
|
658
|
+
expect(project.enable_pane_titles?).to be true
|
659
|
+
end
|
660
|
+
end
|
661
|
+
|
662
|
+
context "pane_title_position not configured" do
|
663
|
+
before { project.yaml["pane_title_position"] = nil }
|
664
|
+
|
665
|
+
it "configures a default position of top" do
|
666
|
+
expect(project.tmux_set_pane_title_position).to eq(
|
667
|
+
"tmux set pane-border-status top"
|
668
|
+
)
|
669
|
+
end
|
670
|
+
end
|
671
|
+
|
672
|
+
context "pane_title_position configured" do
|
673
|
+
before { project.yaml["pane_title_position"] = "bottom" }
|
674
|
+
|
675
|
+
it "configures a position of bottom" do
|
676
|
+
expect(project.tmux_set_pane_title_position).to eq(
|
677
|
+
"tmux set pane-border-status bottom"
|
678
|
+
)
|
679
|
+
end
|
680
|
+
end
|
681
|
+
|
682
|
+
context "pane_title_position invalid" do
|
683
|
+
before { project.yaml["pane_title_position"] = "other" }
|
684
|
+
|
685
|
+
it "configures the default position" do
|
686
|
+
expect(project.tmux_set_pane_title_position).to eq(
|
687
|
+
"tmux set pane-border-status top"
|
688
|
+
)
|
689
|
+
end
|
690
|
+
end
|
691
|
+
|
692
|
+
context "pane_title_format not configured" do
|
693
|
+
before { project.yaml["pane_title_format"] = nil }
|
694
|
+
|
695
|
+
it "configures a default format" do
|
696
|
+
expect(project.tmux_set_pane_title_format).to eq(
|
697
|
+
"tmux set pane-border-format \"\#{pane_index}: \#{pane_title}\""
|
698
|
+
)
|
699
|
+
end
|
700
|
+
end
|
701
|
+
|
702
|
+
context "pane_title_format configured" do
|
703
|
+
before { project.yaml["pane_title_format"] = " [ #T ] " }
|
704
|
+
|
705
|
+
it "configures the provided format" do
|
706
|
+
expect(project.tmux_set_pane_title_format).to eq(
|
707
|
+
'tmux set pane-border-format " [ #T ] "'
|
708
|
+
)
|
709
|
+
end
|
710
|
+
end
|
711
|
+
end
|
638
712
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "coveralls"
|
2
4
|
require "pry"
|
3
5
|
require "simplecov"
|
@@ -39,7 +41,7 @@ def capture_io
|
|
39
41
|
|
40
42
|
yield
|
41
43
|
|
42
|
-
|
44
|
+
[captured_stdout.string, captured_stderr.string]
|
43
45
|
ensure
|
44
46
|
$stdout = orig_stdout
|
45
47
|
$stderr = orig_stderr
|
metadata
CHANGED
@@ -1,30 +1,30 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tmuxinator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Allen Bargi
|
8
8
|
- Christopher Chow
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2024-
|
12
|
+
date: 2024-04-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
15
|
+
name: erubi
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
18
|
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
20
|
+
version: '1.7'
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: '
|
27
|
+
version: '1.7'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: thor
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -177,14 +177,14 @@ dependencies:
|
|
177
177
|
requirements:
|
178
178
|
- - "~>"
|
179
179
|
- !ruby/object:Gem::Version
|
180
|
-
version: 0.
|
180
|
+
version: 0.61.1
|
181
181
|
type: :development
|
182
182
|
prerelease: false
|
183
183
|
version_requirements: !ruby/object:Gem::Requirement
|
184
184
|
requirements:
|
185
185
|
- - "~>"
|
186
186
|
- !ruby/object:Gem::Version
|
187
|
-
version: 0.
|
187
|
+
version: 0.61.1
|
188
188
|
- !ruby/object:Gem::Dependency
|
189
189
|
name: simplecov
|
190
190
|
requirement: !ruby/object:Gem::Requirement
|
@@ -302,8 +302,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
302
302
|
- !ruby/object:Gem::Version
|
303
303
|
version: 1.8.23
|
304
304
|
requirements: []
|
305
|
-
rubygems_version: 3.
|
306
|
-
signing_key:
|
305
|
+
rubygems_version: 3.3.26
|
306
|
+
signing_key:
|
307
307
|
specification_version: 4
|
308
308
|
summary: Create and manage complex tmux sessions easily.
|
309
309
|
test_files:
|