tmuxinator 0.6.11 → 0.7.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: 38f09af10a658caa15c32d1abe77373cc9e2d960
4
- data.tar.gz: 8a17b9b5cf0de202edb22ead61cd148462e4a8fd
3
+ metadata.gz: 079c5def07857f7b54737cd711899a7c529fee96
4
+ data.tar.gz: 461725febed6618763f593eec2952cbce8866368
5
5
  SHA512:
6
- metadata.gz: 7fba40c695a6406361c67fc0275a2706577bce38b86e1b37d4a6311fac8957d9212aba70ca93c3b52150e7ec77a45cf52b2da030781f82fe2fa8c57dec694440
7
- data.tar.gz: 6e39fbf6bcb98e0e7deac36693b931c1f1ff0fc024e7a6f0425bdb0c5345e2b59965511923ed8b37a0b2530604803dfc76a690d0da8463ed26e1201dc26b5db5
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
- if ARGV.length == 1
8
- name = ARGV[0]
7
+ name = ARGV[0] || nil
9
8
 
10
- if Tmuxinator::Cli::COMMANDS.keys.include?(name.to_sym)
11
- Tmuxinator::Cli.start
12
- elsif Tmuxinator::Config.exists?(name)
13
- Tmuxinator::Cli.new.start(name)
14
- else
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
@@ -4,16 +4,13 @@ $: << File.expand_path("../../lib/", __FILE__)
4
4
  require "thor"
5
5
  require "tmuxinator"
6
6
 
7
- if ARGV.length == 1
8
- name = ARGV[0]
7
+ name = ARGV[0] || nil
9
8
 
10
- if Tmuxinator::Cli::COMMANDS.keys.include?(name.to_sym)
11
- Tmuxinator::Cli.start
12
- elsif Tmuxinator::Config.exists?(name)
13
- Tmuxinator::Cli.new.start(name)
14
- else
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= <%= tmux %> new-session -d -s <%= name %> -n <%= windows.first.name %>
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
- <%= tmux %> -u attach-session -t <%= name %>
76
- else
77
- <%= tmux %> -u switch-client -t <%= name %>
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 %>
@@ -8,7 +8,7 @@ if [ "$?" -eq 127 ]; then
8
8
  <%= pre %>
9
9
 
10
10
  # Create the session and the first window.
11
- TMUX= <%= tmux %> new-session -d -s <%= name %> -n <%= windows.first.name %>
11
+ TMUX= <%= tmux_new_session_command %>
12
12
 
13
13
  # Set the default path.
14
14
  <%- if root? -%>
@@ -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: "Start a tmux session using a project's tmuxinator config, with an optional [ALIAS] for project reuse",
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: "Copy an existing project to a new project and open it in your editor",
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" unless Gem::Version.create(Thor::VERSION) < Gem::Version.create("0.18")
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
- COMMANDS.map do |command, desc|
27
- "#{command}:#{desc}"
28
- end.join("\n")
29
- else
30
- COMMANDS.keys.join("\n")
31
- end
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
- config = Tmuxinator::Config.project(name)
54
-
55
- unless Tmuxinator::Config.exists?(name)
56
- template = Tmuxinator::Config.default? ? Tmuxinator::Config.default : Tmuxinator::Config.sample
57
- erb = Erubis::Eruby.new(File.read(template)).result(binding)
58
- File.open(config, "w") { |f| f.write(erb) }
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 #{config}") || doctor
82
+ Kernel.system("$EDITOR #{project_file}") || doctor
62
83
  end
63
84
 
64
- desc "start [PROJECT] [SESSION_NAME]", COMMANDS[:start]
65
- map "s" => :start
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
- def start(name, custom_name = nil)
68
- project = Tmuxinator::Config.validate(name, custom_name )
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
- if project.deprecations.any?
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
- Kernel.exec(project.render)
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 "debug [PROJECT]", COMMANDS[:debug]
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
- def debug(name, custom_name = nil)
83
- project = Tmuxinator::Config.validate(name, custom_name )
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!") unless Tmuxinator::Config.exists?(existing)
170
+ exit!("Project #{existing} doesn't exist!") \
171
+ unless Tmuxinator::Config.exists?(existing)
96
172
 
97
- if !Tmuxinator::Config.exists?(new) or yes?("#{new} already exists, would you like to overwrite it?", :red)
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 = "#{Tmuxinator::Config.root}/#{project}.yml"
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 Tmuxinator::Config.shell?
237
+ yes_no Tmuxinator::Config.shell?
160
238
  end
161
239
  end
162
240
  end
@@ -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
- Dir.mkdir("#{ENV["HOME"]}/.tmuxinator") unless File.directory?(File.expand_path("~/.tmuxinator"))
6
- "#{ENV["HOME"]}/.tmuxinator"
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
- "#{File.dirname(__FILE__)}/assets/sample.yml"
14
+ asset_path "sample.yml"
11
15
  end
12
16
 
13
17
  def default
14
- "#{ENV["HOME"]}/.tmuxinator/default.yml"
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 project(name)
49
+ def project_in_root(name)
46
50
  projects = Dir.glob("#{root}/**/*.yml")
47
- project_file = projects.detect { |project| File.basename(project, ".yml") == name }
48
- project_file || "#{root}/#{name}.yml"
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
- "#{File.dirname(__FILE__)}/assets/template.erb"
71
+ asset_path "template.erb"
53
72
  end
54
73
 
55
74
  def wemux_template
56
- "#{File.dirname(__FILE__)}/assets/wemux_template.erb"
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(name, custom_name = nil)
66
- unless Tmuxinator::Config.exists?(name)
67
- puts "Project #{name} doesn't exist."
68
- exit!
69
- end
70
-
71
- config_path = Tmuxinator::Config.project(name)
72
-
73
- yaml = begin
74
- YAML.load(Erubis::Eruby.new(File.read(config_path)).result(binding))
75
- rescue SyntaxError, StandardError
76
- puts "Failed to parse config file. Please check your formatting."
77
- exit!
78
- end
79
-
80
- project = Tmuxinator::Project.new(yaml, custom_name)
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
- unless project.name?
88
- puts "Your project file didn't specify a 'project_name'"
89
- exit!
90
- end
101
+ private
91
102
 
92
- project
103
+ def asset_path(asset)
104
+ "#{File.dirname(__FILE__)}/assets/#{asset}"
93
105
  end
94
106
  end
95
107
  end
@@ -10,27 +10,43 @@ module Tmuxinator
10
10
  end
11
11
 
12
12
  def tmux_window_and_pane_target
13
- "#{project.name}:#{tab.index + project.base_index}.#{index + project.base_index}"
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
- "#{project.tmux} send-keys -t #{tmux_window_and_pane_target} #{tab.pre.shellescape} C-m"
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
- "#{project.tmux} send-keys -t #{tmux_window_and_pane_target} #{project.pre_window.shellescape} C-m"
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
- command ? "#{project.tmux} send-keys -t #{project.name}:#{tab.index + project.base_index}.#{index + tab.project.base_index} #{command.shellescape} C-m" : ""
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? ? "#{Tmuxinator::Config.default_path_option} #{tab.root}" : nil
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