tmuxinator 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +1 -1
  4. data/.travis.yml +5 -0
  5. data/CHANGELOG.md +36 -0
  6. data/CONTRIBUTING.md +29 -0
  7. data/Gemfile +4 -7
  8. data/{LICENSE.txt → LICENSE} +1 -1
  9. data/README.md +128 -118
  10. data/Rakefile +1 -72
  11. data/bin/mux +8 -3
  12. data/bin/tmuxinator +8 -3
  13. data/completion/tmuxinator.bash +18 -0
  14. data/completion/tmuxinator.zsh +20 -0
  15. data/lib/tmuxinator.rb +13 -7
  16. data/lib/tmuxinator/assets/sample.yml +24 -11
  17. data/lib/tmuxinator/assets/template.erb +47 -0
  18. data/lib/tmuxinator/cli.rb +121 -145
  19. data/lib/tmuxinator/config.rb +92 -0
  20. data/lib/tmuxinator/deprecations.rb +19 -0
  21. data/lib/tmuxinator/pane.rb +36 -0
  22. data/lib/tmuxinator/project.rb +142 -0
  23. data/lib/tmuxinator/util.rb +14 -0
  24. data/lib/tmuxinator/version.rb +3 -0
  25. data/lib/tmuxinator/window.rb +76 -0
  26. data/spec/factories/projects.rb +17 -0
  27. data/spec/fixtures/sample.deprecations.yml +35 -0
  28. data/spec/fixtures/sample.yml +35 -0
  29. data/spec/lib/tmuxinator/cli_spec.rb +230 -0
  30. data/spec/lib/tmuxinator/config_spec.rb +121 -0
  31. data/spec/lib/tmuxinator/pane_spec.rb +7 -0
  32. data/spec/lib/tmuxinator/project_spec.rb +209 -0
  33. data/spec/lib/tmuxinator/util_spec.rb +4 -0
  34. data/spec/lib/tmuxinator/window_spec.rb +62 -0
  35. data/spec/spec_helper.rb +28 -8
  36. data/tmuxinator.gemspec +47 -65
  37. metadata +186 -62
  38. data/.document +0 -5
  39. data/Gemfile.lock +0 -28
  40. data/TODO +0 -4
  41. data/VERSION +0 -1
  42. data/bin/tmuxinator_completion +0 -29
  43. data/lib/tmuxinator/assets/tmux_config.tmux +0 -37
  44. data/lib/tmuxinator/config_writer.rb +0 -104
  45. data/lib/tmuxinator/helper.rb +0 -19
  46. data/spec/tmuxinator_spec.rb +0 -54
@@ -0,0 +1,92 @@
1
+ require "pry"
2
+ module Tmuxinator
3
+ class Config
4
+ class << self
5
+ def root
6
+ Dir.mkdir("#{ENV["HOME"]}/.tmuxinator") unless File.directory?(File.expand_path("~/.tmuxinator"))
7
+ "#{ENV["HOME"]}/.tmuxinator"
8
+ end
9
+
10
+ def sample
11
+ "#{File.dirname(__FILE__)}/assets/sample.yml"
12
+ end
13
+
14
+ def default
15
+ "#{ENV["HOME"]}/.tmuxinator/default.yml"
16
+ end
17
+
18
+ def default?
19
+ exists?(default)
20
+ end
21
+
22
+ def installed?
23
+ Kernel.system("which tmux > /dev/null")
24
+ end
25
+
26
+ def editor?
27
+ !ENV["EDITOR"].nil? && !ENV["EDITOR"].empty?
28
+ end
29
+
30
+ def shell?
31
+ !ENV["SHELL"].nil? && !ENV["SHELL"].empty?
32
+ end
33
+
34
+ def exists?(name)
35
+ unless project(name).nil?
36
+ File.exists?(project(name))
37
+ else
38
+ false
39
+ end
40
+ end
41
+
42
+ def project(name)
43
+ projects = Dir.glob("#{root}/**/*.yml")
44
+ projects.select { |project| project =~ /#{name}.yml/ }.first
45
+ end
46
+
47
+ def template
48
+ "#{File.dirname(__FILE__)}/assets/template.erb"
49
+ end
50
+
51
+ def configs
52
+ Dir["#{Tmuxinator::Config.root}/*.yml"].sort.map do |path|
53
+ path.gsub("#{Tmuxinator::Config.root}/", "").gsub(".yml", "")
54
+ end
55
+ end
56
+
57
+ def validate(name)
58
+ unless Tmuxinator::Config.exists?(name)
59
+ puts "Project #{name} doesn't exist."
60
+ exit!
61
+ end
62
+
63
+ config_path = Tmuxinator::Config.project(name)
64
+
65
+ yaml = begin
66
+ YAML.load(File.read(config_path))
67
+ rescue SyntaxError, StandardError
68
+ puts "Failed to parse config file. Please check your formatting."
69
+ exit!
70
+ end
71
+
72
+ project = Tmuxinator::Project.new(yaml)
73
+
74
+ unless project.windows?
75
+ puts "Your project file should include some windows."
76
+ exit!
77
+ end
78
+
79
+ unless project.root?
80
+ puts "Your project file didn't specify a 'project_root'"
81
+ exit!
82
+ end
83
+
84
+ unless project.name?
85
+ puts "Your project file didn't specify a 'project_name'"
86
+ end
87
+
88
+ project
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,19 @@
1
+ module Tmuxinator
2
+ module Deprecations
3
+ def rvm?
4
+ yaml["rvm"].present?
5
+ end
6
+
7
+ def rbenv?
8
+ yaml["rbenv"].present?
9
+ end
10
+
11
+ def pre_tab?
12
+ yaml["pre_tab"].present?
13
+ end
14
+
15
+ def cli_args?
16
+ yaml["cli_args"].present?
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,36 @@
1
+ module Tmuxinator
2
+ class Pane
3
+ attr_reader :command, :project, :index, :project, :tab
4
+
5
+ def initialize(command, index, project, tab)
6
+ @command = command
7
+ @index = index
8
+ @project = project
9
+ @tab = tab
10
+ end
11
+
12
+ def tmux_window_and_pane_target
13
+ "#{project.name}:#{tab.index + project.base_index}.#{index + project.base_index}"
14
+ end
15
+
16
+ def tmux_pre_command
17
+ tab.pre.present? ? "#{project.tmux} send-keys -t #{tmux_window_and_pane_target} #{tab.pre.shellescape} C-m" : ""
18
+ end
19
+
20
+ def tmux_pre_window_command
21
+ project.pre_window.present? ? "#{project.tmux} send-keys -t #{tmux_window_and_pane_target} #{project.pre_window.shellescape} C-m" : ""
22
+ end
23
+
24
+ def tmux_main_command
25
+ command.present? ? "#{project.tmux} send-keys -t #{project.name}:#{tab.index + project.base_index}.#{index + tab.project.base_index} #{command.shellescape} C-m" : ""
26
+ end
27
+
28
+ def tmux_split_command
29
+ "#{project.tmux} splitw -t #{tab.tmux_window_target}"
30
+ end
31
+
32
+ def last?
33
+ index == tab.panes.length - 1
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,142 @@
1
+ module Tmuxinator
2
+ class Project
3
+ include Tmuxinator::Util
4
+ include Tmuxinator::Deprecations
5
+
6
+ attr_reader :yaml
7
+
8
+ def initialize(yaml)
9
+ @yaml = yaml
10
+ end
11
+
12
+ def render
13
+ template = File.read(Tmuxinator::Config.template)
14
+ Erubis::Eruby.new(template).result(binding)
15
+ end
16
+
17
+ def windows
18
+ windows_yml =
19
+ if yaml["tabs"].present?
20
+ yaml["tabs"]
21
+ else
22
+ yaml["windows"]
23
+ end
24
+
25
+ @windows ||= windows_yml.map.with_index do |window_yml, index|
26
+ Tmuxinator::Window.new(window_yml, index, self)
27
+ end
28
+ end
29
+
30
+ def root
31
+ if yaml["project_root"].present?
32
+ yaml["project_root"]
33
+ else
34
+ yaml["root"]
35
+ end
36
+ end
37
+
38
+ def name
39
+ if yaml["project_name"].present?
40
+ yaml["project_name"].shellescape
41
+ else
42
+ yaml["name"].shellescape
43
+ end
44
+ end
45
+
46
+ def pre
47
+ yaml["pre"]
48
+ end
49
+
50
+ def pre_window
51
+ if rbenv?
52
+ "rbenv shell #{yaml["rbenv"]}"
53
+ elsif rvm?
54
+ "rvm use #{yaml["rvm"]}"
55
+ elsif pre_tab?
56
+ yaml["pre_tab"]
57
+ else
58
+ yaml["pre_window"]
59
+ end
60
+ end
61
+
62
+ def tmux
63
+ "tmux#{tmux_options}#{socket}"
64
+ end
65
+
66
+ def socket
67
+ if socket_path.present?
68
+ " -S #{socket_path}"
69
+ elsif socket_name.present?
70
+ " -L #{socket_name}"
71
+ else
72
+ nil
73
+ end
74
+ end
75
+
76
+ def socket_name
77
+ yaml["socket_name"]
78
+ end
79
+
80
+ def socket_path
81
+ yaml["socket_path"]
82
+ end
83
+
84
+ def tmux_options
85
+ if cli_args?
86
+ " #{yaml["cli_args"].strip}"
87
+ elsif tmux_options?
88
+ " #{yaml["tmux_options"].strip}"
89
+ else
90
+ ""
91
+ end
92
+ end
93
+
94
+ def base_index
95
+ `tmux start-server\\\; show-window-options -g | grep pane-base-index`.split(/\s/).last.to_i
96
+ end
97
+
98
+ def tmux_options?
99
+ yaml["tmux_options"].present?
100
+ end
101
+
102
+ def windows?
103
+ windows.any?
104
+ end
105
+
106
+ def root?
107
+ root.present?
108
+ end
109
+
110
+ def name?
111
+ name.present?
112
+ end
113
+
114
+ def window(i)
115
+ "#{name}:#{i}"
116
+ end
117
+
118
+ def send_pane_command(cmd, window_index, pane_index)
119
+ if cmd.blank?
120
+ ""
121
+ else
122
+ "#{tmux} send-keys -t #{window(window_index)} #{cmd.shellescape} C-m"
123
+ end
124
+ end
125
+
126
+ def send_keys(cmd, window_index)
127
+ if cmd.blank?
128
+ ""
129
+ else
130
+ "#{tmux} send-keys -t #{window(window_index)} #{cmd.shellescape} C-m"
131
+ end
132
+ end
133
+
134
+ def deprecations
135
+ deprecations = []
136
+ deprecations << "DEPRECATION: rbenv/rvm specific options have been replaced by the pre_tab option and will not be supported in 0.8.0." if yaml["rbenv"] || yaml["rvm"]
137
+ deprecations << "DEPRECATION: The tabs option has been replaced by the window option and will not be supported in 0.8.0." if yaml["tabs"].present?
138
+ deprecations << "DEPRECATION: The cli_args option has been replaced by the tmux_options option and will not be supported in 0.8.0." if yaml["cli_args"].present?
139
+ deprecations
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,14 @@
1
+ module Tmuxinator
2
+ module Util
3
+ include Thor::Actions
4
+
5
+ def exit!(msg)
6
+ puts msg
7
+ Kernel.exit(1)
8
+ end
9
+
10
+ def yes_no(condition)
11
+ condition ? say("Yes", :green) : say("No", :red)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ module Tmuxinator
2
+ VERSION = "0.6.0"
3
+ end
@@ -0,0 +1,76 @@
1
+ module Tmuxinator
2
+ class Window
3
+ attr_reader :name, :panes, :layout, :command, :index, :project
4
+
5
+ def initialize(window_yaml, index, project)
6
+ @name = window_yaml.keys.first.present? ? window_yaml.keys.first.shellescape : nil
7
+ @panes = []
8
+ @layout = nil
9
+ @pre = nil
10
+ @command = nil
11
+ @project = project
12
+ @index = index
13
+
14
+ value = window_yaml.values.first
15
+
16
+ if value.is_a?(Hash)
17
+ @layout = value["layout"].present? ? value["layout"].shellescape : nil
18
+ @pre = value["pre"] if value["pre"].present?
19
+
20
+ @panes = build_panes(value["panes"])
21
+ else
22
+ @command = value
23
+ end
24
+ end
25
+
26
+ def build_panes(pane_yml)
27
+ if pane_yml.is_a?(Array)
28
+ pane_yml.map.with_index do |pane_cmd, index|
29
+ Tmuxinator::Pane.new(pane_cmd, index, project, self)
30
+ end
31
+ else
32
+ Tmuxinator::Pane.new(pane_yml, index, project, self)
33
+ end
34
+ end
35
+
36
+ def pre
37
+ if @pre.present?
38
+ if @pre.is_a?(Array)
39
+ @pre.join(" && ")
40
+ elsif @pre.is_a?(String)
41
+ @pre
42
+ end
43
+ else
44
+ ""
45
+ end
46
+ end
47
+
48
+ def panes?
49
+ panes.any?
50
+ end
51
+
52
+ def tmux_window_target
53
+ "#{project.name}:#{index + project.base_index}"
54
+ end
55
+
56
+ def tmux_pre_window_command
57
+ project.pre_window.present? ? "#{project.tmux} send-keys -t #{tmux_window_target} #{project.pre_window.shellescape} C-m" : ""
58
+ end
59
+
60
+ def tmux_main_command
61
+ command.present? ? "#{project.tmux} send-keys -t #{project.name}:#{index + project.base_index} #{command.shellescape} C-m" : ""
62
+ end
63
+
64
+ def tmux_new_window_command
65
+ "#{project.tmux} new-window -t #{tmux_window_target} -n #{name}"
66
+ end
67
+
68
+ def tmux_layout_command
69
+ "#{project.tmux} select-layout -t #{tmux_window_target} #{layout}"
70
+ end
71
+
72
+ def tmux_select_first_pane
73
+ "#{project.tmux} select-pane -t #{tmux_window_target}.#{panes.first.index + project.base_index}"
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,17 @@
1
+ FactoryGirl.define do
2
+ factory :project, :class => Tmuxinator::Project do
3
+ ignore do
4
+ file { YAML.load(File.read("#{File.expand_path("spec/fixtures/sample.yml")}")) }
5
+ end
6
+
7
+ initialize_with { Tmuxinator::Project.new(file) }
8
+ end
9
+
10
+ factory :project_with_deprecations, :class => Tmuxinator::Project do
11
+ ignore do
12
+ file { YAML.load(File.read("#{File.expand_path("spec/fixtures/sample.deprecations.yml")}")) }
13
+ end
14
+
15
+ initialize_with { Tmuxinator::Project.new(file) }
16
+ end
17
+ end
@@ -0,0 +1,35 @@
1
+ # ~/.tmuxinator/sample.deprecations.yml
2
+ # you can make as many tabs as you wish...
3
+
4
+ project_name: sample
5
+ project_root: ~/test
6
+ socket_name: foo # Remove to use default socket
7
+ pre: sudo /etc/rc.d/mysqld start # Runs before everything
8
+ rbenv: 2.0.0-p247
9
+ cli_args: -v -2 # Pass arguments to tmux
10
+ tabs:
11
+ - editor:
12
+ pre:
13
+ - echo "I get run in each pane, before each pane command!"
14
+ -
15
+ layout: main-vertical
16
+ panes:
17
+ - vim
18
+ - #empty, will just run plain bash
19
+ - top
20
+ - shell: git pull
21
+ - guard:
22
+ layout: tiled
23
+ pre:
24
+ - echo "I get run in each pane."
25
+ - echo "Before each pane command!"
26
+ panes:
27
+ -
28
+ - #empty, will just run plain bash
29
+ -
30
+ - database: bundle exec rails db
31
+ - server: bundle exec rails s
32
+ - logs: tail -f log/development.log
33
+ - console: bundle exec rails c
34
+ - capistrano:
35
+ - server: ssh user@example.com