tmuxinator 0.7.2 → 0.8.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 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