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
data/bin/mux CHANGED
@@ -1,6 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
- $:.unshift(File.dirname(__FILE__) + '/../lib') unless $:.include?(File.dirname(__FILE__) + '/../lib')
2
+ $: << File.expand_path("../../lib/", __FILE__)
3
3
 
4
- require 'tmuxinator'
4
+ require "thor"
5
+ require "tmuxinator"
5
6
 
6
- Tmuxinator::Cli.run(*ARGV)
7
+ if ARGV.length == 1 && (ARGV & Tmuxinator::Cli.new.command_list).empty?
8
+ Tmuxinator::Cli.new.start(ARGV[0])
9
+ else
10
+ Tmuxinator::Cli.start
11
+ end
data/bin/tmuxinator CHANGED
@@ -1,6 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
- $:.unshift(File.dirname(__FILE__) + '/../lib') unless $:.include?(File.dirname(__FILE__) + '/../lib')
2
+ $: << File.expand_path("../../lib/", __FILE__)
3
3
 
4
- require 'tmuxinator'
4
+ require "thor"
5
+ require "tmuxinator"
5
6
 
6
- Tmuxinator::Cli.run(*ARGV)
7
+ if ARGV.length == 1 && (ARGV & Tmuxinator::Cli.new.command_list).empty?
8
+ Tmuxinator::Cli.new.start(ARGV[0])
9
+ else
10
+ Tmuxinator::Cli.start
11
+ end
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env bash
2
+
3
+ _tmuxinator() {
4
+ COMPREPLY=()
5
+ local word="${COMP_WORDS[COMP_CWORD]}"
6
+
7
+ if [ "$COMP_CWORD" -eq 1 ]; then
8
+ COMPREPLY=( $(compgen -W "$(tmuxinator commands)" -- "$word") )
9
+ else
10
+ local words=("${COMP_WORDS[@]}")
11
+ unset words[0]
12
+ unset words[$COMP_CWORD]
13
+ local completions=$(tmuxinator completions "${words[@]}")
14
+ COMPREPLY=( $(compgen -W "$completions" -- "$word") )
15
+ fi
16
+ }
17
+
18
+ complete -F _tmuxinator -o tmuxinator mux
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env zsh
2
+
3
+ if [[ ! -o interactive ]]; then
4
+ return
5
+ fi
6
+
7
+ compctl -K _tmuxinator tmuxinator mux
8
+
9
+ _tmuxinator() {
10
+ local words completions
11
+ read -cA words
12
+
13
+ if [ "${#words}" -eq 2 ]; then
14
+ completions="$(tmuxinator commands)"
15
+ else
16
+ completions="$(tmuxinator completions ${words[2,-2]})"
17
+ fi
18
+
19
+ reply=("${(ps:\n:)completions}")
20
+ }
data/lib/tmuxinator.rb CHANGED
@@ -1,11 +1,17 @@
1
- require 'yaml'
2
- require 'ostruct'
3
- require 'erb'
4
- require 'tmuxinator/helper'
5
- require 'tmuxinator/cli'
6
- require 'tmuxinator/config_writer'
1
+ require "yaml"
2
+ require "erubis"
3
+ require "shellwords"
4
+ require "thor"
5
+ require "active_support/all"
7
6
 
8
- TMUX_TEMPLATE = "#{File.dirname(__FILE__)}/tmuxinator/assets/tmux_config.tmux"
7
+ require "tmuxinator/util"
8
+ require "tmuxinator/deprecations"
9
+ require "tmuxinator/cli"
10
+ require "tmuxinator/config"
11
+ require "tmuxinator/pane"
12
+ require "tmuxinator/project"
13
+ require "tmuxinator/window"
14
+ require "tmuxinator/version"
9
15
 
10
16
  module Tmuxinator
11
17
  end
@@ -1,22 +1,35 @@
1
1
  # ~/.tmuxinator/<%= @name %>.yml
2
2
  # you can make as many tabs as you wish...
3
3
 
4
- project_name: Tmuxinator
5
- project_root: ~/code/rails_project
6
- socket_name: foo # Not needed. Remove to use default socket
7
- rvm: 1.9.2@rails_project
8
- pre: sudo /etc/rc.d/mysqld start
9
- tabs:
4
+ name: sample
5
+ root: ~/test
6
+ socket_name: foo # Remove to use default socket
7
+ pre: sudo /etc/rc.d/mysqld start # Runs before everything
8
+ pre_window: rbenv shell 2.0.0-p247 # Runs in each tab and pane
9
+ tmux_options: -v -2 # Pass arguments to tmux
10
+ windows:
10
11
  - editor:
12
+ pre:
13
+ - echo "I get run in each pane, before each pane command!"
14
+ -
11
15
  layout: main-vertical
12
16
  panes:
13
17
  - vim
14
18
  - #empty, will just run plain bash
15
19
  - top
16
20
  - shell: git pull
17
- - database: rails db
18
- - server: rails s
19
- - logs: tail -f logs/development.log
20
- - console: rails c
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
21
34
  - capistrano:
22
- - server: ssh me@myhost
35
+ - server: ssh user@example.com
@@ -0,0 +1,47 @@
1
+ #!<%= ENV["SHELL"] || "/bin/bash" %>
2
+ <%= tmux %> start-server\; has-session -t <%= name %> 2>/dev/null
3
+
4
+ if [ "$?" -eq 1 ]; then
5
+ cd <%= root || "." %>
6
+
7
+ # Run pre command.
8
+ <%= pre %>
9
+
10
+ # Create the session and the first window.
11
+ <%= tmux %> new-session -d -s <%= name %> -n <%= windows.first.name %>
12
+
13
+ # Set the default path.
14
+ <%= tmux %> set-option -t <%= name %> default-path <%= root -%> 1>/dev/null
15
+
16
+ # Create other windows.
17
+ <%- windows.drop(1).each do |window| -%>
18
+ <%= window.tmux_new_window_command %>
19
+ <%- end -%>
20
+
21
+ <%- windows.each do |window| -%>
22
+
23
+ # Window "<%= window.name %>"
24
+ <%- unless window.panes? -%>
25
+ <%= window.tmux_pre_window_command %>
26
+ <%= window.tmux_main_command %>
27
+ <%- else -%>
28
+ <%- window.panes.each do |pane| -%>
29
+ <%= pane.tmux_pre_window_command %>
30
+ <%= pane.tmux_pre_command %>
31
+ <%= pane.tmux_main_command %>
32
+
33
+ <%- unless pane.last? -%>
34
+ <%= pane.tmux_split_command %>
35
+ <%- end -%>
36
+ <%- end -%>
37
+
38
+
39
+ <%= window.tmux_layout_command %>
40
+ <%= window.tmux_select_first_pane %>
41
+ <%- end -%>
42
+ <%- end -%>
43
+
44
+ <%= tmux %> select-window -t <%= base_index %>
45
+ fi
46
+
47
+ <%= tmux %> -u attach-session -t <%= name %>
@@ -1,175 +1,151 @@
1
- require 'fileutils'
2
-
3
1
  module Tmuxinator
4
- class Cli
2
+ class Cli < Thor
3
+ include Tmuxinator::Util
5
4
 
6
- class << self
7
- include Tmuxinator::Helper
5
+ attr_reader :command_list
8
6
 
9
- def run *args
10
- if args.empty?
11
- self.usage
12
- else
13
- self.send(args.shift, *args)
14
- end
15
- end
7
+ def initialize(*args)
8
+ super
9
+ @command_list = %w(commands copy debug delete doctor help implode list start version)
10
+ end
11
+
12
+ package_name "tmuxinator"
13
+
14
+ desc "commands", "Lists commands available in tmuxinator"
16
15
 
17
- # print the usage string, this is a fall through method.
18
- def usage
19
- puts %{
20
- Usage: tmuxinator ACTION [Arg]
21
- or
22
- tmuxinator [project_name]
23
-
24
- ACTIONS:
25
- start [project_name]
26
- start a tmux session using project's tmuxinator config
27
- open [project_name]
28
- create a new project file and open it in your editor
29
- copy [source_project] [new_project]
30
- copy source_project project file to a new project called new_project
31
- delete [project_name]
32
- deletes the project called project_name
33
- implode
34
- deletes all existing projects!
35
- list [-v]
36
- list all existing projects
37
- doctor
38
- look for problems in your configuration
39
- help
40
- shows this help document
41
- version
42
- shows tmuxinator version number
43
- }
16
+ def commands
17
+ puts command_list.join("\n")
18
+ end
19
+
20
+ desc "completions [arg1 arg2]", "Used for shell completion"
21
+
22
+ def completions(arg)
23
+ if %w(start open copy delete).include?(arg)
24
+ configs = Tmuxinator::Config.configs
25
+ puts configs
44
26
  end
45
- alias :help :usage
46
- alias :h :usage
47
-
48
- # Open a config file, it's created if it doesn't exist already.
49
- def open *args
50
- exit!("You must specify a name for the new project") unless args.size > 0
51
- puts "warning: passing multiple arguments to open will be ignored" if args.size > 1
52
- @name = args.shift
53
- config_path = "#{root_dir}#{@name}.yml"
54
- unless File.exists?(config_path)
55
- template = File.exists?(user_config) ? user_config : sample_config
56
- erb = ERB.new(File.read(template)).result(binding)
57
- tmp = File.open(config_path, 'w') {|f| f.write(erb) }
58
- end
59
- system("$EDITOR #{config_path}")
27
+ end
28
+
29
+ desc "new [PROJECT]", "Create a new project file and open it in your editor"
30
+ map "open" => :new
31
+ map "o" => :new
32
+ map "n" => :new
33
+
34
+ def new(name)
35
+ config = Tmuxinator::Config.project(name)
36
+
37
+ unless Tmuxinator::Config.exists?(name)
38
+ template = Tmuxinator::Config.default? ? Tmuxinator::Config.default : Tmuxinator::Config.sample
39
+ erb = ERB.new(File.read(template)).result(binding)
40
+ File.open(config, "w") { |f| f.write(erb) }
60
41
  end
61
- alias :o :open
62
- alias :new :open
63
- alias :n :open
64
42
 
65
- def copy *args
66
- @copy = args.shift
67
- @name = args.shift
68
- @config_to_copy = "#{root_dir}#{@copy}.yml"
43
+ Kernel.system("$EDITOR #{config}")
44
+ end
69
45
 
70
- exit!("Project #{@copy} doesn't exist!") unless File.exists?(@config_to_copy)
71
- exit!("You must specify a name for the new project") unless @name
46
+ desc "start [PROJECT]", "Start a tmux session using a project's tmuxinator config"
47
+ map "s" => :start
72
48
 
73
- file_path = "#{root_dir}#{@name}.yml"
49
+ def start(name)
50
+ project = Tmuxinator::Config.validate(name)
74
51
 
75
- if File.exists?(file_path)
76
- confirm!("#{@name} already exists, would you like to overwrite it? (type yes or no):") do
77
- FileUtils.rm(file_path)
78
- puts "Overwriting #{@name}"
79
- end
80
- end
81
- open @name
82
- end
83
- alias :c :copy
84
-
85
- def delete *args
86
- puts "warning: passing multiple arguments to delete will be ignored" if args.size > 1
87
- filename = args.shift
88
- file_path = "#{root_dir}#{filename}.yml"
89
-
90
- if File.exists?(file_path)
91
- confirm!("Are you sure you want to delete #{filename}? (type yes or no):") do
92
- FileUtils.rm(file_path)
93
- puts "Deleted #{filename}"
94
- end
95
- else
96
- exit! "That file doesn't exist."
97
- end
52
+ if project.deprecations.any?
53
+ project.deprecations.each { |deprecation| say deprecation, :red }
54
+ puts
55
+ print "Press any key to continue."
56
+ STDIN.getc
98
57
  end
99
- alias :d :delete
100
58
 
101
- def implode *args
102
- exit!("delete_all doesn't accapt any arguments!") unless args.empty?
103
- confirm!("Are you sure you want to delete all tmuxinator configs? (type yes or no):") do
104
- FileUtils.remove_dir(root_dir)
105
- puts "Deleted #{root_dir}"
59
+ Kernel.exec(project.render)
60
+ end
61
+
62
+ desc "debug [PROJECT]", "Output the shell commands that are generated by tmuxinator"
63
+
64
+ def debug(name)
65
+ project = Tmuxinator::Config.validate(name)
66
+ puts project.render
67
+ end
68
+
69
+ desc "copy [EXISTING] [NEW]", "Copy an existing project to a new project and open it in your editor"
70
+ map "c" => :copy
71
+ map "cp" => :copy
72
+
73
+ def copy(existing, new)
74
+ existing_config_path = Tmuxinator::Config.project(existing)
75
+ new_config_path = Tmuxinator::Config.project(new)
76
+
77
+ exit!("Project #{existing} doesn't exist!") unless Tmuxinator::Config.exists?(existing)
78
+
79
+ if Tmuxinator::Config.exists?(new)
80
+ if yes?("#{new} already exists, would you like to overwrite it?", :red)
81
+ FileUtils.rm(new_config_path)
82
+ say "Overwriting #{new}"
106
83
  end
107
84
  end
108
- alias :i :implode
109
-
110
- def list *args
111
- verbose = args.include?("-v")
112
- puts "tmuxinator configs:"
113
- Dir["#{root_dir}**"].each do |path|
114
- next unless verbose || File.extname(path) == ".yml"
115
- path = path.gsub(root_dir, '').gsub('.yml','') unless verbose
116
- puts " #{path}"
85
+
86
+ FileUtils.copy_file(existing_config_path, new_config_path)
87
+ Kernel.system("$EDITOR #{new_config_path}")
88
+ end
89
+
90
+ desc "delete [PROJECT]", "Deletes given project"
91
+ map "d" => :delete
92
+ map "rm" => :delete
93
+
94
+ def delete(project)
95
+ config = "#{Tmuxinator::Config.root}#{project}.yml"
96
+
97
+ if Tmuxinator::Config.exists?(config)
98
+ if yes?("Are you sure you want to delete #{project}?", :red)
99
+ FileUtils.rm(config)
100
+ say "Deleted #{project}"
117
101
  end
102
+ else
103
+ exit! "That file doesn't exist."
118
104
  end
119
- alias :l :list
120
- alias :ls :list
105
+ end
121
106
 
122
- def version
123
- system("cat #{File.dirname(__FILE__) + '/../../VERSION'}")
124
- puts
125
- end
126
- alias :v :version
127
-
128
- def doctor
129
- print " checking if tmux is installed ==> "
130
- puts system("which tmux > /dev/null") ? "Yes" : "No"
131
- print " checking if $EDITOR is set ==> "
132
- puts ENV['EDITOR'] ? "Yes" : "No"
133
- print " checking if $SHELL is set ==> "
134
- puts ENV['SHELL'] ? "Yes" : "No"
135
- end
107
+ desc "implode", "Delets all tmuxinator projects"
108
+ map "i" => :implode
136
109
 
137
- # build script and run it
138
- def start *args
139
- exit!("You must specify a name for the new project") unless args.size > 0
140
- puts "warning: passing multiple arguments to open will be ignored" if args.size > 1
141
- project_name = args.shift
142
- config_path = "#{root_dir}#{project_name}.yml"
143
- config = Tmuxinator::ConfigWriter.new(config_path).render
144
- # replace current proccess by running compiled tmux config
145
- exec(config)
110
+ def implode
111
+ if yes?("Are you sure you want to delete all tmuxinator configs?", :red)
112
+ FileUtils.remove_dir(Tmuxinator::Config.root)
113
+ say "Deleted all tmuxinator projects."
146
114
  end
147
- alias :s :start
115
+ end
148
116
 
149
- def method_missing method, *args, &block
150
- start method if File.exists?("#{root_dir}#{method}.yml")
151
- puts "There's no command or project '#{method}' in tmuxinator"
152
- usage
153
- end
117
+ desc "list", "Lists all tmuxinator projects"
118
+ map "l" => :list
119
+ map "ls" => :list
154
120
 
155
- private #==============================
121
+ def list
122
+ say "tmuxinator projects:"
156
123
 
157
- def root_dir
158
- # create ~/.tmuxinator directory if it doesn't exist
159
- Dir.mkdir("#{ENV["HOME"]}/.tmuxinator/") unless File.directory?(File.expand_path("~/.tmuxinator"))
160
- "#{ENV["HOME"]}/.tmuxinator/"
124
+ configs = Dir["#{Tmuxinator::Config.root}/*.yml"].sort.map do |path|
125
+ path.gsub("#{Tmuxinator::Config.root}/", "").gsub(".yml", "")
161
126
  end
162
127
 
163
- def sample_config
164
- "#{File.dirname(__FILE__)}/assets/sample.yml"
165
- end
128
+ print_in_columns configs
129
+ end
166
130
 
167
- def user_config
168
- @config_to_copy || "#{ENV["HOME"]}/.tmuxinator/default.yml"
169
- end
131
+ desc "version", "Display installed tmuxinator version"
132
+ map "-v" => :version
170
133
 
134
+ def version
135
+ say "tmuxinator #{Tmuxinator::VERSION}"
171
136
  end
172
137
 
138
+ desc "doctor", "Look for problems in your configuration"
139
+
140
+ def doctor
141
+ say "Checking if tmux is installed ==> "
142
+ yes_no Tmuxinator::Config.installed?
143
+
144
+ say "Checking if $EDITOR is set ==> "
145
+ yes_no Tmuxinator::Config.editor?
146
+
147
+ say "Checking if $SHELL is set ==> "
148
+ yes_no Tmuxinator::Config.shell?
149
+ end
173
150
  end
174
151
  end
175
-