tmuxinator 0.7.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 69776676073ac64ed73dd6f12141c6c3d7b3d9bc
4
- data.tar.gz: a8fbc49a81682d255042d28c9c73ccc5303147d7
3
+ metadata.gz: 9f98c0bb5c7a176cd11d7e1720ea199ee655ead7
4
+ data.tar.gz: 590c2abe675cab0d44289fc4409c2b0cce93e0a5
5
5
  SHA512:
6
- metadata.gz: a22f37e133c2bea7f2b3b2b3c62d1291ed364bc7eb1b302fb8814cc86bd29269c132e3eb30bdbb0bc34c7e5b3ef023eb355b20112233dccd6a31d1a8060466b1
7
- data.tar.gz: 1f83b909c1539eb9b8c1d40b78836a1e4a1b9b269130ed8379be287e4e791166f5425ed5ae5fb6b2f2d92631e4a898b80cf487c16a30efa7f43cbe066ac86f59
6
+ metadata.gz: 3c6225eb4aa956911383348621e96977c2558d2bfff0052c0134b690c5e06fafde850586789c23de3f4364f61c20f8cda599de4f577c730a9d11455e5053574f
7
+ data.tar.gz: 64df154916353b5626d67b5452caf2b275add6f0b24023e29523b1a7e2bf8994713afaf22d23661558072994484601acdd8532360a42f72ef0ed658653743324
@@ -8,7 +8,7 @@ _tmuxinator() {
8
8
  if [ "$COMP_CWORD" -eq 1 ]; then
9
9
  local commands="$(compgen -W "$(tmuxinator commands)" -- "$word")"
10
10
  local projects="$(compgen -W "$(tmuxinator completions start)" -- "$word")"
11
-
11
+
12
12
  COMPREPLY=( $commands $projects )
13
13
  elif [ "$COMP_CWORD" -eq 2 ]; then
14
14
  local words
@@ -1,5 +1,3 @@
1
- #compdef tmuxinator mux
2
-
3
1
  _tmuxinator() {
4
2
  local commands projects
5
3
  commands=(${(f)"$(tmuxinator commands zsh)"})
@@ -19,7 +17,7 @@ _tmuxinator() {
19
17
  return
20
18
  }
21
19
 
22
- _tmuxinator
20
+ compdef _tmuxinator tmuxinator mux
23
21
 
24
22
  # Local Variables:
25
23
  # mode: Shell-Script
@@ -4,9 +4,9 @@
4
4
  unset RBENV_VERSION
5
5
  unset RBENV_DIR
6
6
 
7
- <%= tmux %> start-server\; has-session = <%= name %> 2>/dev/null
7
+ <%= tmux %> start-server;
8
8
 
9
- if [ "$?" -eq 1 ]; then
9
+ <%- if !tmux_has_session? name -%>
10
10
  cd <%= root || "." %>
11
11
 
12
12
  # Run pre command.
@@ -69,7 +69,7 @@ if [ "$?" -eq 1 ]; then
69
69
  <% end %>
70
70
 
71
71
  <%= tmux %> select-window -t <%= startup_window %>
72
- fi
72
+ <%- end -%>
73
73
 
74
74
  <%- if attach? -%>
75
75
  if [ -z "$TMUX" ]; then
@@ -17,6 +17,9 @@ module Tmuxinator
17
17
  Start a tmux session using a project's tmuxinator config,
18
18
  with an optional [ALIAS] for project reuse
19
19
  DESC
20
+ stop: <<-DESC,
21
+ Stop a tmux session using a project's tmuxinator config.
22
+ DESC
20
23
  local: "Start a tmux session using ./.tmuxinator.yml",
21
24
  debug: "Output the shell commands that are generated by tmuxinator",
22
25
  copy: <<-DESC,
@@ -44,15 +47,15 @@ module Tmuxinator
44
47
  COMMANDS.keys.join("\n")
45
48
  end
46
49
 
47
- puts out
50
+ say out
48
51
  end
49
52
 
50
53
  desc "completions [arg1 arg2]", COMMANDS[:completions]
51
54
 
52
55
  def completions(arg)
53
- if %w(start open copy delete).include?(arg)
56
+ if %w(start stop open copy delete).include?(arg)
54
57
  configs = Tmuxinator::Config.configs
55
- puts configs
58
+ say configs
56
59
  end
57
60
  end
58
61
 
@@ -116,13 +119,17 @@ module Tmuxinator
116
119
  def render_project(project)
117
120
  if project.deprecations.any?
118
121
  project.deprecations.each { |deprecation| say deprecation, :red }
119
- puts
122
+ say
120
123
  print "Press ENTER to continue."
121
124
  STDIN.getc
122
125
  end
123
126
 
124
127
  Kernel.exec(project.render)
125
128
  end
129
+
130
+ def kill_project(project)
131
+ Kernel.exec(project.tmux_kill_session_command)
132
+ end
126
133
  end
127
134
 
128
135
  desc "start [PROJECT] [ARGS]", COMMANDS[:start]
@@ -144,6 +151,17 @@ module Tmuxinator
144
151
  render_project(project)
145
152
  end
146
153
 
154
+ desc "stop [PROJECT]", COMMANDS[:stop]
155
+ map "st" => :stop
156
+
157
+ def stop(name)
158
+ params = {
159
+ name: name
160
+ }
161
+ project = create_project(params)
162
+ kill_project(project)
163
+ end
164
+
147
165
  desc "local", COMMANDS[:local]
148
166
  map "." => :local
149
167
 
@@ -166,7 +184,7 @@ module Tmuxinator
166
184
  args: args
167
185
  }
168
186
  project = create_project(params)
169
- puts project.render
187
+ say project.render
170
188
  end
171
189
 
172
190
  desc "copy [EXISTING] [NEW]", COMMANDS[:copy]
@@ -190,20 +208,22 @@ module Tmuxinator
190
208
  Kernel.system("$EDITOR #{new_config_path}")
191
209
  end
192
210
 
193
- desc "delete [PROJECT]", COMMANDS[:delete]
211
+ desc "delete [PROJECT1] [PROJECT2] ...", COMMANDS[:delete]
194
212
  map "d" => :delete
195
213
  map "rm" => :delete
196
214
 
197
- def delete(project)
198
- if Tmuxinator::Config.exists?(project)
199
- config = "#{Tmuxinator::Config.root}/#{project}.yml"
215
+ def delete(*projects)
216
+ projects.each do |project|
217
+ if Tmuxinator::Config.exists?(project)
218
+ config = Tmuxinator::Config.project(project)
200
219
 
201
- if yes?("Are you sure you want to delete #{project}?(y/n)", :red)
202
- FileUtils.rm(config)
203
- say "Deleted #{project}"
220
+ if yes?("Are you sure you want to delete #{project}?(y/n)", :red)
221
+ FileUtils.rm(config)
222
+ say "Deleted #{project}"
223
+ end
224
+ else
225
+ say "#{project} does not exist!"
204
226
  end
205
- else
206
- exit!("That file doesn't exist.")
207
227
  end
208
228
  end
209
229
 
@@ -147,6 +147,12 @@ module Tmuxinator
147
147
  yaml["tmux_command"] || "tmux"
148
148
  end
149
149
 
150
+ def tmux_has_session?(name)
151
+ sessions = `#{tmux_command} ls`
152
+
153
+ !!sessions.match("^#{name}:")
154
+ end
155
+
150
156
  def socket
151
157
  if socket_path
152
158
  " -S #{socket_path}"
@@ -242,6 +248,10 @@ module Tmuxinator
242
248
  "#{tmux} new-session -d -s #{name} #{window}"
243
249
  end
244
250
 
251
+ def tmux_kill_session_command
252
+ "#{tmux} kill-session -t #{name}"
253
+ end
254
+
245
255
  private
246
256
 
247
257
  def tmux_config
@@ -1,3 +1,3 @@
1
1
  module Tmuxinator
2
- VERSION = "0.7.2"
2
+ VERSION = "0.8.0"
3
3
  end
@@ -6,7 +6,7 @@ module Tmuxinator
6
6
 
7
7
  def initialize(window_yaml, index, project)
8
8
  @name = if !window_yaml.keys.first.nil?
9
- window_yaml.keys.first.shellescape
9
+ window_yaml.keys.first.to_s.shellescape
10
10
  end
11
11
  @root = nil
12
12
  @panes = []
@@ -41,6 +41,14 @@ FactoryGirl.define do
41
41
  initialize_with { Tmuxinator::Project.new(file) }
42
42
  end
43
43
 
44
+ factory :project_with_literals_as_window_name, class: Tmuxinator::Project do
45
+ transient do
46
+ file { yaml_load("spec/fixtures/sample_literals_as_window_name.yml") }
47
+ end
48
+
49
+ initialize_with { Tmuxinator::Project.new(file) }
50
+ end
51
+
44
52
  factory :project_with_deprecations, class: Tmuxinator::Project do
45
53
  transient do
46
54
  file { yaml_load("spec/fixtures/sample.deprecations.yml") }
@@ -0,0 +1,15 @@
1
+ # ~/.tmuxinator/sample_literals_as_window_name.yml
2
+
3
+ name: sample
4
+ windows:
5
+ - 222: echo Fixnum as window name fixture
6
+ - 222_333: echo Fixnum as window name fixture
7
+ - 111222333444555666777: echo BigNum as window name fixture
8
+ - 222.3: echo Float as window name fixture
9
+ - 4e5: echo Float as window name fixture
10
+ - 4E5: echo Float as window name fixture
11
+ - true: echo TrueClass as window name fixture
12
+ - false: echo FalseClass as window name fixture
13
+ - nil: echo NilClass as window name fixture
14
+ - //: echo RegExp as window name fixture
15
+ - /sample/: echo RegExp as window name fixture
@@ -41,6 +41,7 @@ describe Tmuxinator::Cli do
41
41
  new
42
42
  open
43
43
  start
44
+ stop
44
45
  local
45
46
  debug
46
47
  copy
@@ -98,6 +99,26 @@ describe Tmuxinator::Cli do
98
99
  end
99
100
  end
100
101
 
102
+ describe "#stop" do
103
+ before do
104
+ ARGV.replace(["stop", "foo"])
105
+ allow(Tmuxinator::Config).to receive_messages(validate: project)
106
+ allow(Tmuxinator::Config).to receive_messages(version: 1.9)
107
+ allow(Kernel).to receive(:exec)
108
+ end
109
+
110
+ context "with project name" do
111
+ let(:project) { FactoryGirl.build(:project) }
112
+
113
+ it "stop the project" do
114
+ expect(Kernel).to receive(:exec)
115
+ out, err = capture_io { cli.start }
116
+ expect(err).to eq ""
117
+ expect(out).to eq ""
118
+ end
119
+ end
120
+ end
121
+
101
122
  describe "#local" do
102
123
  shared_examples_for :local_project do
103
124
  before do
@@ -324,30 +345,88 @@ describe Tmuxinator::Cli do
324
345
  end
325
346
 
326
347
  describe "#delete" do
327
- before do
328
- ARGV.replace(["delete", "foo"])
329
- allow(Thor::LineEditor).to receive_messages(readline: "y")
330
- end
331
-
332
- context "project exists" do
348
+ context "with a single argument" do
333
349
  before do
334
- allow(Tmuxinator::Config).to receive(:exists?) { true }
350
+ ARGV.replace(["delete", "foo"])
351
+ allow(Thor::LineEditor).to receive_messages(readline: "y")
335
352
  end
336
353
 
337
- it "deletes the project" do
338
- expect(FileUtils).to receive(:rm)
339
- capture_io { cli.start }
354
+ context "project exists" do
355
+ before do
356
+ allow(Tmuxinator::Config).to receive(:exists?) { true }
357
+ end
358
+
359
+ it "deletes the project" do
360
+ expect(FileUtils).to receive(:rm)
361
+ capture_io { cli.start }
362
+ end
363
+ end
364
+
365
+ context "local project exists" do
366
+ before do
367
+ allow(Tmuxinator::Config).to receive(:exists?) { true }
368
+ expect(Tmuxinator::Config).to receive(:project) { "local" }
369
+ end
370
+
371
+ it "deletes the local project" do
372
+ expect(FileUtils).to receive(:rm).with("local")
373
+ capture_io { cli.start }
374
+ end
375
+ end
376
+
377
+ context "project doesn't exist" do
378
+ before do
379
+ allow(Tmuxinator::Config).to receive(:exists?) { false }
380
+ end
381
+
382
+ it "outputs an error message" do
383
+ expect(capture_io { cli.start }[0]).to match(/foo does not exist!/)
384
+ end
340
385
  end
341
386
  end
342
387
 
343
- context "project doesn't exist" do
388
+ context "with multiple arguments" do
344
389
  before do
345
- allow(Tmuxinator::Config).to receive(:exists?) { false }
390
+ ARGV.replace(["delete", "foo", "bar"])
346
391
  allow(Thor::LineEditor).to receive_messages(readline: "y")
347
392
  end
348
393
 
349
- it "exits with error message" do
350
- expect { capture_io { cli.start } }.to raise_error SystemExit
394
+ context "all projects exist" do
395
+ before do
396
+ allow(Tmuxinator::Config).to receive(:exists?).and_return(true)
397
+ end
398
+
399
+ it "deletes the projects" do
400
+ expect(FileUtils).to receive(:rm).exactly(2).times
401
+ capture_io { cli.start }
402
+ end
403
+ end
404
+
405
+ context "only one project exists" do
406
+ before do
407
+ allow(Tmuxinator::Config).to receive(:exists?).with("foo") { true }
408
+ allow(Tmuxinator::Config).to receive(:exists?).with("bar") { false }
409
+ end
410
+
411
+ it "deletes one project" do
412
+ expect(FileUtils).to receive(:rm)
413
+ capture_io { cli.start }
414
+ end
415
+
416
+ it "outputs an error message" do
417
+ expect(capture_io { cli.start }[0]).to match(/bar does not exist!/)
418
+ end
419
+ end
420
+
421
+ context "all projects do not exist" do
422
+ before do
423
+ allow(Tmuxinator::Config).to receive(:exists?).and_return(false)
424
+ end
425
+
426
+ it "outputs multiple error messages" do
427
+ expect(capture_io { cli.start }[0]).
428
+ to match(/foo does not exist!\nbar does not exist!/)
429
+ end
351
430
  end
352
431
  end
353
432
  end
@@ -8,6 +8,9 @@ describe Tmuxinator::Project do
8
8
  let(:project_with_number_as_name) do
9
9
  FactoryGirl.build(:project_with_number_as_name)
10
10
  end
11
+ let(:project_with_literals_as_window_name) do
12
+ FactoryGirl.build(:project_with_literals_as_window_name)
13
+ end
11
14
  let(:project_with_deprecations) do
12
15
  FactoryGirl.build(:project_with_deprecations)
13
16
  end
@@ -51,13 +54,27 @@ describe Tmuxinator::Project do
51
54
  expect(rendered).to_not include("sample")
52
55
  end
53
56
  end
57
+ end
54
58
 
55
- # Please see: https://github.com/tmuxinator/tmuxinator/issues/347
56
- context "open sessions" do
57
- it "uses 'has-session =' to avoid matching open session name prefixes" do
58
- output = project.render
59
- expect(output).to match %r{has-session =}
60
- end
59
+ describe "#tmux_has_session?" do
60
+ before do
61
+ cmd = "#{project.tmux_command} ls"
62
+ resp = ""\
63
+ "foo: 1 window (created Sun May 25 10:12:00 1986) [50x50] (detached)\n"\
64
+ "bar: 1 window (created Sat Sept 01 00:00:00 1990) [50x50] (detached)"
65
+ call_tmux_ls = receive(:`).with(cmd).at_least(:once).and_return(resp)
66
+
67
+ expect(project).to call_tmux_ls
68
+ end
69
+
70
+ it "should return true only when `tmux ls` has the named session" do
71
+ expect(project.tmux_has_session?("foo")).to be true
72
+ expect(project.tmux_has_session?("bar")).to be true
73
+ expect(project.tmux_has_session?("quux")).to be false
74
+ end
75
+
76
+ it "should return false if a partial (prefix) match is found" do
77
+ expect(project.tmux_has_session?("foobar")).to be false
61
78
  end
62
79
  end
63
80
 
@@ -126,6 +143,15 @@ describe Tmuxinator::Project do
126
143
  expect(rendered.name.to_i).to_not equal 0
127
144
  end
128
145
  end
146
+
147
+ context "window as non-string literal" do
148
+ it "will gracefully handle a window name given as a non-string literal" do
149
+ rendered = project_with_literals_as_window_name
150
+ expect(rendered.windows.map(&:name)).to match_array(
151
+ %w(222 222333 111222333444555666777 222.3 4e5 4E5
152
+ true false nil // /sample/))
153
+ end
154
+ end
129
155
  end
130
156
 
131
157
  describe "#pre_window" do
@@ -456,6 +482,18 @@ describe Tmuxinator::Project do
456
482
  end
457
483
  end
458
484
 
485
+ describe "tmux_kill_session_command" do
486
+ let(:command) { "#{executable} kill-session -t #{session}" }
487
+ let(:executable) { project.tmux }
488
+ let(:session) { project.name }
489
+
490
+ context "when first window has a name" do
491
+ it "returns command to start a new detatched session" do
492
+ expect(project.tmux_kill_session_command).to eq command
493
+ end
494
+ end
495
+ end
496
+
459
497
  describe "::load" do
460
498
  let(:path) { File.expand_path("../../../fixtures/sample.yml", __FILE__) }
461
499
  let(:options) { {} }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tmuxinator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Allen Bargi
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-04-01 00:00:00.000000000 Z
12
+ date: 2016-04-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
@@ -95,6 +95,7 @@ files:
95
95
  - spec/fixtures/nowindows.yml
96
96
  - spec/fixtures/sample.deprecations.yml
97
97
  - spec/fixtures/sample.yml
98
+ - spec/fixtures/sample_literals_as_window_name.yml
98
99
  - spec/fixtures/sample_number_as_name.yml
99
100
  - spec/fixtures/sample_wemux.yml
100
101
  - spec/lib/tmuxinator/cli_spec.rb
@@ -142,6 +143,7 @@ test_files:
142
143
  - spec/fixtures/nowindows.yml
143
144
  - spec/fixtures/sample.deprecations.yml
144
145
  - spec/fixtures/sample.yml
146
+ - spec/fixtures/sample_literals_as_window_name.yml
145
147
  - spec/fixtures/sample_number_as_name.yml
146
148
  - spec/fixtures/sample_wemux.yml
147
149
  - spec/lib/tmuxinator/cli_spec.rb