tmuxinator-0.9.0/0000755000175000017500000000000012776077541013606 5ustar uwabamiuwabamitmuxinator-0.9.0/.rspec0000644000175000017500000000003712776077541014723 0ustar uwabamiuwabami--color --format=documentation tmuxinator-0.9.0/code_of_conduct.md0000644000175000017500000000623512776077541017253 0ustar uwabamiuwabami# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at jonarnett90@gmail.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ tmuxinator-0.9.0/completion/0000755000175000017500000000000012776077541015757 5ustar uwabamiuwabamitmuxinator-0.9.0/completion/tmuxinator.zsh0000644000175000017500000000122212776077541020714 0ustar uwabamiuwabami_tmuxinator() { local commands projects commands=(${(f)"$(tmuxinator commands zsh)"}) projects=(${(f)"$(tmuxinator completions start)"}) if (( CURRENT == 2 )); then _describe -t commands "tmuxinator subcommands" commands _describe -t projects "tmuxinator projects" projects elif (( CURRENT == 3)); then case $words[2] in copy|debug|delete|open|start) _arguments '*:projects:($projects)' ;; esac fi return } compdef _tmuxinator tmuxinator mux alias mux="tmuxinator" # Local Variables: # mode: Shell-Script # sh-indentation: 2 # indent-tabs-mode: nil # sh-basic-offset: 2 # End: # vim: ft=zsh sw=2 ts=2 et tmuxinator-0.9.0/completion/mux.fish0000777000175000017500000000000012776077541022525 2tmuxinator.fishustar uwabamiuwabamitmuxinator-0.9.0/completion/tmuxinator.bash0000644000175000017500000000131412776077541021027 0ustar uwabamiuwabami#!/usr/bin/env bash _tmuxinator() { COMPREPLY=() local word word="${COMP_WORDS[COMP_CWORD]}" if [ "$COMP_CWORD" -eq 1 ]; then local commands="$(compgen -W "$(tmuxinator commands)" -- "$word")" local projects="$(compgen -W "$(tmuxinator completions start)" -- "$word")" COMPREPLY=( $commands $projects ) elif [ "$COMP_CWORD" -eq 2 ]; then local words words=("${COMP_WORDS[@]}") unset words[0] unset words[$COMP_CWORD] local completions completions=$(tmuxinator completions "${words[@]}") COMPREPLY=( $(compgen -W "$completions" -- "$word") ) fi } complete -F _tmuxinator tmuxinator mux alias mux="tmuxinator" tmuxinator-0.9.0/completion/tmuxinator.fish0000644000175000017500000000225512776077541021050 0ustar uwabamiuwabamifunction __fish_tmuxinator_using_command set cmd (commandline -opc) if [ (count $cmd) -gt 1 ] if [ $argv[1] = $cmd[2] ] return 0 end end return 1 end set __fish_tmuxinator_program_cmd (commandline -o)[1] function __fish_tmuxinator_program eval "$__fish_tmuxinator_program_cmd $argv" end complete -f -c $__fish_tmuxinator_program_cmd -a '(__fish_tmuxinator_program completions start)' complete -f -c $__fish_tmuxinator_program_cmd -n '__fish_use_subcommand' -x -a "(__fish_tmuxinator_program commands)" complete -f -c $__fish_tmuxinator_program_cmd -n '__fish_tmuxinator_using_command start' -a "(__fish_tmuxinator_program completions start)" complete -f -c $__fish_tmuxinator_program_cmd -n '__fish_tmuxinator_using_command open' -a "(__fish_tmuxinator_program completions open)" complete -f -c $__fish_tmuxinator_program_cmd -n '__fish_tmuxinator_using_command copy' -a "(__fish_tmuxinator_program completions copy)" complete -f -c $__fish_tmuxinator_program_cmd -n '__fish_tmuxinator_using_command delete' -a "(__fish_tmuxinator_program completions delete)" abbr --add mux "tmuxinator" tmuxinator-0.9.0/bin/0000755000175000017500000000000012776077541014356 5ustar uwabamiuwabamitmuxinator-0.9.0/bin/tmuxinator0000755000175000017500000000061512776077541016520 0ustar uwabamiuwabami#!/usr/bin/env ruby $: << File.expand_path("../../lib/", __FILE__) require "thor" require "tmuxinator" name = ARGV[0] || nil if ARGV.length == 0 && Tmuxinator::Config.local? Tmuxinator::Cli.new.local elsif name && !Tmuxinator::Cli::COMMANDS.keys.include?(name.to_sym) && Tmuxinator::Config.exists?(name) Tmuxinator::Cli.new.start(name, *ARGV.drop(1)) else Tmuxinator::Cli.start end tmuxinator-0.9.0/LICENSE0000644000175000017500000000206612776077541014617 0ustar uwabamiuwabamiCopyright (c) 2010-2016 Allen Bargi, Christopher Chow Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. tmuxinator-0.9.0/lib/0000755000175000017500000000000012776077541014354 5ustar uwabamiuwabamitmuxinator-0.9.0/lib/tmuxinator.rb0000644000175000017500000000071012776077541017111 0ustar uwabamiuwabamirequire "yaml" require "erubis" require "shellwords" require "thor" require "thor/version" require "tmuxinator/util" require "tmuxinator/deprecations" require "tmuxinator/wemux_support" require "tmuxinator/cli" require "tmuxinator/config" require "tmuxinator/pane" require "tmuxinator/project" require "tmuxinator/window" require "tmuxinator/version" module Tmuxinator end class Object def blank? respond_to?(:empty?) ? !!empty? : !self end end tmuxinator-0.9.0/lib/tmuxinator/0000755000175000017500000000000012776077541016566 5ustar uwabamiuwabamitmuxinator-0.9.0/lib/tmuxinator/assets/0000755000175000017500000000000012776077541020070 5ustar uwabamiuwabamitmuxinator-0.9.0/lib/tmuxinator/assets/sample.yml0000644000175000017500000000273312776077541022101 0ustar uwabamiuwabami# ~/.tmuxinator/<%= name %>.yml name: <%= name %> root: ~/ # Optional tmux socket # socket_name: foo # Runs before everything. Use it to start daemons etc. # pre: sudo /etc/rc.d/mysqld start # Runs in each window and pane before window/pane specific commands. Useful for setting up interpreter versions. # pre_window: rbenv shell 2.0.0-p247 # Pass command line options to tmux. Useful for specifying a different tmux.conf. # tmux_options: -f ~/.tmux.mac.conf # Change the command to call tmux. This can be used by derivatives/wrappers like byobu. # tmux_command: byobu # Specifies (by name or index) which window will be selected on project startup. If not set, the first window is used. # startup_window: editor # Specitifes (by index) which pane of the specified window will be selected on project startup. If not set, the first pane is used. # startup_pane: 1 # Controls whether the tmux session should be attached to automatically. Defaults to true. # attach: false # Runs after everything. Use it to attach to tmux with custom options etc. # post: tmux -CC attach -t <%= name %> windows: - editor: layout: main-vertical # Synchronize all panes of this window, can be enabled before or after the pane commands run. # 'before' represents legacy functionality and will be deprecated in a future release, in favour of 'after' # synchronize: after panes: - vim - guard - server: bundle exec rails s - logs: tail -f log/development.log tmuxinator-0.9.0/lib/tmuxinator/assets/template.erb0000644000175000017500000000431112776077541022374 0ustar uwabamiuwabami#!<%= ENV["SHELL"] || "/bin/bash" %> # Clear rbenv variables before starting tmux unset RBENV_VERSION unset RBENV_DIR <%= tmux %> start-server; <%- if !tmux_has_session? name -%> cd <%= root || "." %> # Run pre command. <%= pre %> # Create the session and the first window. Manually switch to root # directory if required to support tmux < 1.9 TMUX= <%= tmux_new_session_command %> <% if windows.first.root? %> <%= windows.first.tmux_window_command_prefix %> <%= "cd #{windows.first.root}".shellescape %> C-m <% end %> <% if Tmuxinator::Config.version < 1.7 %> # Set the default path for versions prior to 1.7 <% if root? %> <%= tmux %> set-option -t <%= name %> <%= Tmuxinator::Config.default_path_option %> <%= root -%> 1>/dev/null <% end %> <% end %> # Create other windows. <% windows.drop(1).each do |window| %> <%= window.tmux_new_window_command %> <% end %> <% windows.each do |window| %> # Window "<%= window.name %>" <% if window.synchronize_before? %> <%= window.tmux_synchronize_panes %> <% end %> <% unless window.panes? %> <% if window.project.pre_window %> <%= window.tmux_pre_window_command %> <% end %> <% window.commands.each do |command| %> <%= command %> <% end %> <% else %> <% window.panes.each do |pane| %> <% if pane.project.pre_window %> <%= pane.tmux_pre_window_command %> <% end %> <% if pane.tab.pre %> <%= pane.tmux_pre_command %> <% end %> <% pane.commands.each do |command| %> <%= pane.tmux_main_command(command) %> <% end %> <% unless pane.last? %> <%= pane.tmux_split_command %> <% end %> <%= window.tmux_tiled_layout_command %> <% end %> <%= window.tmux_layout_command %> <%= window.tmux_select_first_pane %> <% end %> <% if window.synchronize_after? %> <%= window.tmux_synchronize_panes %> <% end %> <% end %> <%= tmux %> select-window -t <%= startup_window %> <%= tmux %> select-pane -t <%= startup_pane %> <%- end -%> <%- if attach? -%> if [ -z "$TMUX" ]; then <%= tmux %> -u attach-session -t <%= name %> else <%= tmux %> -u switch-client -t <%= name %> fi <%- end -%> <%= post %> tmuxinator-0.9.0/lib/tmuxinator/assets/wemux_template.erb0000644000175000017500000000273212776077541023626 0ustar uwabamiuwabami#!<%= ENV["SHELL"] || "/bin/bash" %> wemux ls 2>/dev/null if [ "$?" -eq 127 ]; then cd <%= root || "." %> # Run pre command. <%= pre %> # Create the session and the first window. TMUX= <%= tmux_new_session_command %> # Set the default path. <%- if root? -%> <%= tmux %> set-option -t <%= name %> <%= Tmuxinator::Config.default_path_option %> <%= root -%> 1>/dev/null <%- end -%> # Create other windows. <%- windows.drop(1).each do |window| -%> <%= window.tmux_new_window_command %> <%- end -%> <%- windows.each do |window| -%> # Window "<%= window.name %>" <% if window.synchronize_before? %> <%= window.tmux_synchronize_panes %> <% end %> <%- unless window.panes? -%> <%= window.tmux_pre_window_command %> <%- window.commands.each do |command| -%> <%= command %> <%- end -%> <%- else -%> <%- window.panes.each do |pane| -%> <%= pane.tmux_pre_window_command %> <%= pane.tmux_pre_command %> <%- pane.commands.each do |command| -%> <%= pane.tmux_main_command(command) %> <%- end -%> <%- unless pane.last? -%> <%= pane.tmux_split_command %> <%- end -%> <%= window.tmux_layout_command %> <%- end -%> <%= window.tmux_select_first_pane %> <%- end -%> <%- if window.synchronize_after? -%> <%= window.tmux_synchronize_panes %> <%- end %> <%- end -%> <%= tmux %> select-window -t <%= startup_window %> <%= tmux %> select-pane -t <%= startup_pane %> fi wemux attach tmuxinator-0.9.0/lib/tmuxinator/deprecations.rb0000644000175000017500000000034712776077541021577 0ustar uwabamiuwabamimodule Tmuxinator module Deprecations def rvm? yaml["rvm"] end def rbenv? yaml["rbenv"] end def pre_tab? yaml["pre_tab"] end def cli_args? yaml["cli_args"] end end end tmuxinator-0.9.0/lib/tmuxinator/wemux_support.rb0000644000175000017500000000072412776077541022057 0ustar uwabamiuwabamimodule Tmuxinator module WemuxSupport def wemux? yaml["tmux_command"] == "wemux" end def load_wemux_overrides class_eval do define_method :render do template = File.read(Tmuxinator::Config.wemux_template) Erubis::Eruby.new(template).result(binding) end define_method :name do "wemux" end define_method :tmux do "wemux" end end end end end tmuxinator-0.9.0/lib/tmuxinator/pane.rb0000644000175000017500000000252712776077541020044 0ustar uwabamiuwabamimodule Tmuxinator class Pane attr_reader :commands, :project, :index, :tab def initialize(index, project, tab, *commands) @commands = commands @index = index @project = project @tab = tab end def tmux_window_and_pane_target x = tab.index + project.base_index y = index + project.base_index "#{project.name}:#{x}.#{y}" end def tmux_pre_command return unless tab.pre t = tmux_window_and_pane_target e = tab.pre.shellescape "#{project.tmux} send-keys -t #{t} #{e} C-m" end def tmux_pre_window_command return unless project.pre_window t = tmux_window_and_pane_target e = project.pre_window.shellescape "#{project.tmux} send-keys -t #{t} #{e} C-m" end def tmux_main_command(command) if command x = tab.index + project.base_index y = index + tab.project.base_index e = command.shellescape n = project.name "#{project.tmux} send-keys -t #{n}:#{x}.#{y} #{e} C-m" else "" end end def tmux_split_command path = if tab.root? "#{Tmuxinator::Config.default_path_option} #{tab.root}" end "#{project.tmux} splitw #{path} -t #{tab.tmux_window_target}" end def last? index == tab.panes.length - 1 end end end tmuxinator-0.9.0/lib/tmuxinator/config.rb0000644000175000017500000000510312776077541020357 0ustar uwabamiuwabamimodule Tmuxinator class Config LOCAL_DEFAULT = "./.tmuxinator.yml".freeze NO_LOCAL_FILE_MSG = "Project file at ./.tmuxinator.yml doesn't exist." class << self def root root_dir = File.expand_path("#{ENV['HOME']}/.tmuxinator") Dir.mkdir(root_dir) unless File.directory?(root_dir) root_dir end def sample asset_path "sample.yml" end def default "#{ENV['HOME']}/.tmuxinator/default.yml" end def default? exists?("default") end def installed? Kernel.system("type tmux > /dev/null") end def version `tmux -V`.split(" ")[1].to_f if installed? end def default_path_option version && version < 1.8 ? "default-path" : "-c" end def editor? !ENV["EDITOR"].nil? && !ENV["EDITOR"].empty? end def shell? !ENV["SHELL"].nil? && !ENV["SHELL"].empty? end def exists?(name) File.exist?(project(name)) end def project_in_root(name) projects = Dir.glob("#{root}/**/*.yml") projects.detect { |project| File.basename(project, ".yml") == name } end def local? project_in_local end def project_in_local [LOCAL_DEFAULT].detect { |f| File.exist?(f) } end def default_project(name) "#{root}/#{name}.yml" end def project(name) project_in_root(name) || project_in_local || default_project(name) end def template asset_path "template.erb" end def wemux_template asset_path "wemux_template.erb" end def configs Dir["#{Tmuxinator::Config.root}/**/*.yml"].sort.map do |path| path.gsub("#{Tmuxinator::Config.root}/", "").gsub(".yml", "") end end def validate(options = {}) name = options[:name] options[:force_attach] ||= false options[:force_detach] ||= false project_file = if name.nil? raise NO_LOCAL_FILE_MSG \ unless Tmuxinator::Config.local? project_in_local else raise "Project #{name} doesn't exist." \ unless Tmuxinator::Config.exists?(name) Tmuxinator::Config.project(name) end Tmuxinator::Project.load(project_file, options).validate! end private def asset_path(asset) "#{File.dirname(__FILE__)}/assets/#{asset}" end end end end tmuxinator-0.9.0/lib/tmuxinator/util.rb0000644000175000017500000000033612776077541020072 0ustar uwabamiuwabamimodule Tmuxinator module Util include Thor::Actions def exit!(msg) puts msg Kernel.exit(1) end def yes_no(condition) condition ? say("Yes", :green) : say("No", :red) end end end tmuxinator-0.9.0/lib/tmuxinator/version.rb0000644000175000017500000000005212776077541020575 0ustar uwabamiuwabamimodule Tmuxinator VERSION = "0.8.1" end tmuxinator-0.9.0/lib/tmuxinator/window.rb0000644000175000017500000000647312776077541020434 0ustar uwabamiuwabamimodule Tmuxinator class Window include Tmuxinator::Util attr_reader :name, :root, :panes, :layout, :commands, :index, :project, :synchronize def initialize(window_yaml, index, project) @name = if !window_yaml.keys.first.nil? window_yaml.keys.first.to_s.shellescape end @root = nil @panes = [] @synchronize = false @layout = nil @pre = nil @project = project @index = index value = window_yaml.values.first if value.is_a?(Hash) @synchronize = value["synchronize"] || false @layout = value["layout"] ? value["layout"].shellescape : nil @pre = value["pre"] if value["pre"] @root = if value["root"] File.expand_path(value["root"]).shellescape elsif project.root? project.root end @panes = build_panes(value["panes"]) end @commands = build_commands(tmux_window_command_prefix, value) end def build_panes(panes_yml) Array(panes_yml).map.with_index do |pane_yml, index| commands = case pane_yml when Hash pane_yml.values.first when Array pane_yml else pane_yml end Tmuxinator::Pane.new(index, project, self, *commands) end.flatten end def build_commands(_prefix, command_yml) if command_yml.is_a?(Array) command_yml.map do |command| "#{tmux_window_command_prefix} #{command.shellescape} C-m" if command end.compact elsif command_yml.is_a?(String) && !command_yml.empty? ["#{tmux_window_command_prefix} #{command_yml.shellescape} C-m"] else [] end end def pre if @pre.is_a?(Array) @pre.join(" && ") elsif @pre.is_a?(String) @pre end end def root? !root.nil? end def panes? panes.any? end def tmux_window_target "#{project.name}:#{index + project.base_index}" end def tmux_pre_window_command return unless project.pre_window "#{project.tmux} send-keys -t #{tmux_window_target} #{project.pre_window.shellescape} C-m" end def tmux_window_command_prefix "#{project.tmux} send-keys -t #{project.name}:#{index + project.base_index}" end def tmux_window_name_option name ? "-n #{name}" : "" end def tmux_new_window_command path = root? ? "#{Tmuxinator::Config.default_path_option} #{root}" : nil "#{project.tmux} new-window #{path} -t #{tmux_window_target} #{tmux_window_name_option}" end def tmux_tiled_layout_command "#{project.tmux} select-layout -t #{tmux_window_target} tiled" end def tmux_synchronize_panes "#{project.tmux} set-window-option -t #{tmux_window_target} synchronize-panes on" end def tmux_layout_command "#{project.tmux} select-layout -t #{tmux_window_target} #{layout}" end def tmux_select_first_pane "#{project.tmux} select-pane -t #{tmux_window_target}.#{panes.first.index + project.base_index}" end def synchronize_before? synchronize == true || synchronize == "before" end def synchronize_after? synchronize == "after" end end end tmuxinator-0.9.0/lib/tmuxinator/cli.rb0000644000175000017500000001674212776077541017674 0ustar uwabamiuwabamimodule Tmuxinator class Cli < Thor # By default, Thor returns exit(0) when an error occurs. # Please see: https://github.com/tmuxinator/tmuxinator/issues/192 def self.exit_on_failure? true end include Tmuxinator::Util COMMANDS = { commands: "Lists commands available in tmuxinator", completions: "Used for shell completion", new: "Create a new project file and open it in your editor", edit: "Alias of new", open: "Alias of new", start: %w{ Start a tmux session using a project's tmuxinator config, with an optional [ALIAS] for project reuse }.join(" "), stop: "Stop a tmux session using a project's tmuxinator config", local: "Start a tmux session using ./.tmuxinator.yml", debug: "Output the shell commands that are generated by tmuxinator", copy: %w{ Copy an existing project to a new project and open it in your editor }.join(" "), delete: "Deletes given project", implode: "Deletes all tmuxinator projects", version: "Display installed tmuxinator version", doctor: "Look for problems in your configuration", list: "Lists all tmuxinator projects" } package_name "tmuxinator" \ unless Gem::Version.create(Thor::VERSION) < Gem::Version.create("0.18") desc "commands", COMMANDS[:commands] def commands(shell = nil) out = if shell == "zsh" COMMANDS.map do |command, desc| "#{command}:#{desc}" end.join("\n") else COMMANDS.keys.join("\n") end say out end desc "completions [arg1 arg2]", COMMANDS[:completions] def completions(arg) if %w(start stop edit open copy delete).include?(arg) configs = Tmuxinator::Config.configs say configs.join("\n") end end desc "new [PROJECT]", COMMANDS[:new] map "open" => :new map "edit" => :new map "o" => :new map "e" => :new map "n" => :new method_option :local, type: :boolean, aliases: ["-l"], desc: "Create local project file at ./.tmuxinator.yml" def new(name) project_file = find_project_file(name, options[:local]) Kernel.system("$EDITOR #{project_file}") || doctor end no_commands do def find_project_file(name, local = false) path = if local Tmuxinator::Config::LOCAL_DEFAULT else Tmuxinator::Config.default_project(name) end if File.exist?(path) path else generate_project_file(name, path) end end def generate_project_file(name, path) template = Tmuxinator::Config.default? ? :default : :sample content = File.read(Tmuxinator::Config.send(template.to_sym)) erb = Erubis::Eruby.new(content).result(binding) File.open(path, "w") { |f| f.write(erb) } path end def create_project(project_options = {}) attach_opt = project_options[:attach] attach = !attach_opt.nil? && attach_opt ? true : false detach = !attach_opt.nil? && !attach_opt ? true : false options = { force_attach: attach, force_detach: detach, name: project_options[:name], custom_name: project_options[:custom_name], args: project_options[:args] } begin Tmuxinator::Config.validate(options) rescue => e exit! e.message end end def render_project(project) if project.deprecations.any? project.deprecations.each { |deprecation| say deprecation, :red } say print "Press ENTER to continue." STDIN.getc end Kernel.exec(project.render) end def kill_project(project) Kernel.exec(project.tmux_kill_session_command) end end desc "start [PROJECT] [ARGS]", COMMANDS[:start] map "s" => :start method_option :attach, type: :boolean, aliases: "-a", desc: "Attach to tmux session after creation." method_option :name, aliases: "-n", desc: "Give the session a different name" def start(name, *args) params = { name: name, custom_name: options[:name], attach: options[:attach], args: args } project = create_project(params) render_project(project) end desc "stop [PROJECT]", COMMANDS[:stop] map "st" => :stop def stop(name) params = { name: name } project = create_project(params) kill_project(project) end desc "local", COMMANDS[:local] map "." => :local def local render_project(create_project(attach: options[:attach])) end method_option :attach, type: :boolean, aliases: "-a", desc: "Attach to tmux session after creation." method_option :name, aliases: "-n", desc: "Give the session a different name" desc "debug [PROJECT] [ARGS]", COMMANDS[:debug] def debug(name, *args) params = { name: name, custom_name: options[:name], attach: options[:attach], args: args } project = create_project(params) say project.render end desc "copy [EXISTING] [NEW]", COMMANDS[:copy] map "c" => :copy map "cp" => :copy def copy(existing, new) existing_config_path = Tmuxinator::Config.project(existing) new_config_path = Tmuxinator::Config.project(new) exit!("Project #{existing} doesn't exist!") \ unless Tmuxinator::Config.exists?(existing) new_exists = Tmuxinator::Config.exists?(new) question = "#{new} already exists, would you like to overwrite it?" if !new_exists || yes?(question, :red) say "Overwriting #{new}" if Tmuxinator::Config.exists?(new) FileUtils.copy_file(existing_config_path, new_config_path) end Kernel.system("$EDITOR #{new_config_path}") end desc "delete [PROJECT1] [PROJECT2] ...", COMMANDS[:delete] map "d" => :delete map "rm" => :delete def delete(*projects) projects.each do |project| if Tmuxinator::Config.exists?(project) config = Tmuxinator::Config.project(project) if yes?("Are you sure you want to delete #{project}?(y/n)", :red) FileUtils.rm(config) say "Deleted #{project}" end else say "#{project} does not exist!" end end end desc "implode", COMMANDS[:implode] map "i" => :implode def implode if yes?("Are you sure you want to delete all tmuxinator configs?", :red) FileUtils.remove_dir(Tmuxinator::Config.root) say "Deleted all tmuxinator projects." end end desc "list", COMMANDS[:list] map "l" => :list map "ls" => :list def list say "tmuxinator projects:" print_in_columns Tmuxinator::Config.configs end desc "version", COMMANDS[:version] map "-v" => :version def version say "tmuxinator #{Tmuxinator::VERSION}" end desc "doctor", COMMANDS[:doctor] def doctor say "Checking if tmux is installed ==> " yes_no Tmuxinator::Config.installed? say "Checking if $EDITOR is set ==> " yes_no Tmuxinator::Config.editor? say "Checking if $SHELL is set ==> " yes_no Tmuxinator::Config.shell? end end end tmuxinator-0.9.0/lib/tmuxinator/project.rb0000644000175000017500000001634112776077541020566 0ustar uwabamiuwabamimodule Tmuxinator class Project include Tmuxinator::Util include Tmuxinator::Deprecations include Tmuxinator::WemuxSupport RBENVRVM_DEP_MSG = <<-M DEPRECATION: rbenv/rvm-specific options have been replaced by the pre_tab option and will not be supported in 0.8.0. M TABS_DEP_MSG = <<-M DEPRECATION: The tabs option has been replaced by the windows option and will not be supported in 0.8.0. M CLIARGS_DEP_MSG = <<-M DEPRECATION: The cli_args option has been replaced by the tmux_options option and will not be supported in 0.8.0. M SYNC_DEP_MSG = <<-M DEPRECATION: The synchronize option's current default behaviour is to enable pane synchronization before running commands. In a future release, the default syncronization option will be `after`, i.e. synchronization of panes will occur after the commands described in each of the panes have run. At that time, the current behavior will need to be explicitly enabled, using the `synchronize: before` option. To use this behaviour now, use the 'synchronize: after' option. M attr_reader :yaml attr_reader :force_attach attr_reader :force_detach attr_reader :custom_name def self.load(path, options = {}) yaml = begin raw_content = File.read(path) args = options[:args] || [] @settings = parse_settings(args) @args = args content = Erubis::Eruby.new(raw_content).result(binding) YAML.load(content) rescue SyntaxError, StandardError raise "Failed to parse config file. Please check your formatting." end new(yaml, options) end def self.parse_settings(args) settings = args.select { |x| x.match(/.*=.*/) } args.reject! { |x| x.match(/.*=.*/) } settings.map! do |setting| parts = setting.split("=") [parts[0], parts[1]] end Hash[settings] end def validate! raise "Your project file should include some windows." \ unless self.windows? raise "Your project file didn't specify a 'project_name'" \ unless self.name? self end def initialize(yaml, options = {}) options[:force_attach] = false if options[:force_attach].nil? options[:force_detach] = false if options[:force_detach].nil? @yaml = yaml @custom_name = options[:custom_name] @force_attach = options[:force_attach] @force_detach = options[:force_detach] raise "Cannot force_attach and force_detach at the same time" \ if @force_attach && @force_detach load_wemux_overrides if wemux? end def render template = File.read(Tmuxinator::Config.template) Erubis::Eruby.new(template).result(binding) end def windows windows_yml = yaml["tabs"] || yaml["windows"] @windows ||= (windows_yml || {}).map.with_index do |window_yml, index| Tmuxinator::Window.new(window_yml, index, self) end end def root root = yaml["project_root"] || yaml["root"] root.blank? ? nil : File.expand_path(root).shellescape end def name name = custom_name || yaml["project_name"] || yaml["name"] name.blank? ? nil : name.to_s.shellescape end def pre pre_config = yaml["pre"] if pre_config.is_a?(Array) pre_config.join("; ") else pre_config end end def attach? if yaml["attach"].nil? yaml_attach = true else yaml_attach = yaml["attach"] end attach = force_attach || !force_detach && yaml_attach attach end def pre_window if rbenv? "rbenv shell #{yaml['rbenv']}" elsif rvm? "rvm use #{yaml['rvm']}" elsif pre_tab? yaml["pre_tab"] else yaml["pre_window"] end end def post post_config = yaml["post"] if post_config.is_a?(Array) post_config.join("; ") else post_config end end def tmux "#{tmux_command}#{tmux_options}#{socket}" end def tmux_command yaml["tmux_command"] || "tmux" end def tmux_has_session?(name) # Redirect stderr to /dev/null in order to prevent "failed to connect # to server: Connection refused" error message and non-zero exit status # if no tmux sessions exist. # Please see issues #402 and #414. sessions = `#{tmux_command} ls 2> /dev/null` !!sessions.match("^#{name}:") end def socket if socket_path " -S #{socket_path}" elsif socket_name " -L #{socket_name}" end end def socket_name yaml["socket_name"] end def socket_path yaml["socket_path"] end def tmux_options if cli_args? " #{yaml['cli_args'].to_s.strip}" elsif tmux_options? " #{yaml['tmux_options'].to_s.strip}" else "" end end def base_index get_pane_base_index ? get_pane_base_index.to_i : get_base_index.to_i end def pane_base_index get_pane_base_index.to_i end def startup_window yaml["startup_window"] || base_index end def startup_pane yaml["startup_pane"] || pane_base_index end def tmux_options? yaml["tmux_options"] end def windows? windows.any? end def root? !root.nil? end def name? !name.nil? end def window(i) "#{name}:#{i}" end def send_pane_command(cmd, window_index, _pane_index) if cmd.empty? "" else "#{tmux} send-keys -t #{window(window_index)} #{cmd.shellescape} C-m" end end def send_keys(cmd, window_index) if cmd.empty? "" else "#{tmux} send-keys -t #{window(window_index)} #{cmd.shellescape} C-m" end end def deprecations deprecations = [] deprecations << RBENVRVM_DEP_MSG if yaml["rbenv"] || yaml["rvm"] deprecations << TABS_DEP_MSG if yaml["tabs"] deprecations << CLIARGS_DEP_MSG if yaml["cli_args"] deprecations << SYNC_DEP_MSG if legacy_synchronize? deprecations end def get_pane_base_index tmux_config["pane-base-index"] end def get_base_index tmux_config["base-index"] end def show_tmux_options "#{tmux} start-server\\; show-option -g" end def tmux_new_session_command window = windows.first.tmux_window_name_option "#{tmux} new-session -d -s #{name} #{window}" end def tmux_kill_session_command "#{tmux} kill-session -t #{name}" end private def tmux_config @tmux_config ||= extract_tmux_config end def extract_tmux_config options_hash = {} options_string = `#{show_tmux_options}` options_string.encode!("UTF-8", invalid: :replace) options_string.split("\n").map do |entry| key, value = entry.split("\s") options_hash[key] = value options_hash end options_hash end def legacy_synchronize? (synchronize_options & [true, "before"]).any? end def synchronize_options window_options.map do |option| option["synchronize"] if option.is_a?(Hash) end end def window_options yaml["windows"].map(&:values).flatten end end end tmuxinator-0.9.0/.rubocop.yml0000644000175000017500000010750612776077541016071 0ustar uwabamiuwabamiAllCops: Include: - "**/*.podspec" - "**/*.jbuilder" - "**/*.opal" - "**/Vagrantfile" - "**/Berksfile" - "**/Cheffile" - "**/Vagabondfile" Exclude: - "vendor/**/*" - "db/schema.rb" RunRailsCops: false DisplayCopNames: false StyleGuideCopsOnly: false Style/AccessModifierIndentation: Description: Check indentation of private/protected visibility modifiers. StyleGuide: https://github.com/bbatsov/ruby-style-guide#indent-public-private-protected Enabled: true EnforcedStyle: indent SupportedStyles: - outdent - indent Style/AlignHash: Description: Align the elements of a hash literal if they span more than one line. Enabled: true EnforcedHashRocketStyle: key EnforcedColonStyle: key EnforcedLastArgumentHashStyle: always_inspect SupportedLastArgumentHashStyles: - always_inspect - always_ignore - ignore_implicit - ignore_explicit Style/AlignParameters: Description: Align the parameters of a method call if they span more than one line. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-double-indent Enabled: true EnforcedStyle: with_first_parameter SupportedStyles: - with_first_parameter - with_fixed_indentation Style/AndOr: Description: Use &&/|| instead of and/or. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-and-or-or Enabled: true EnforcedStyle: always SupportedStyles: - always - conditionals Style/BarePercentLiterals: Description: Checks if usage of %() or %Q() matches configuration. StyleGuide: https://github.com/bbatsov/ruby-style-guide#percent-q-shorthand Enabled: true EnforcedStyle: bare_percent SupportedStyles: - percent_q - bare_percent Style/BracesAroundHashParameters: Description: Enforce braces style around hash parameters. Enabled: true EnforcedStyle: no_braces SupportedStyles: - braces - no_braces - context_dependent Style/CaseIndentation: Description: Indentation of when in a case/when/[else/]end. StyleGuide: https://github.com/bbatsov/ruby-style-guide#indent-when-to-case Enabled: true IndentWhenRelativeTo: case SupportedStyles: - case - end IndentOneStep: false Style/ClassAndModuleChildren: Description: Checks style of children classes and modules. Enabled: false EnforcedStyle: nested SupportedStyles: - nested - compact Style/ClassCheck: Description: Enforces consistent use of `Object#is_a?` or `Object#kind_of?`. Enabled: true EnforcedStyle: is_a? SupportedStyles: - is_a? - kind_of? Style/CollectionMethods: Description: Preferred collection methods. StyleGuide: https://github.com/bbatsov/ruby-style-guide#map-find-select-reduce-size Enabled: true PreferredMethods: collect: map collect!: map! find: detect find_all: select reduce: inject Style/CommentAnnotation: Description: Checks formatting of special comments (TODO, FIXME, OPTIMIZE, HACK, REVIEW). StyleGuide: https://github.com/bbatsov/ruby-style-guide#annotate-keywords Enabled: false Keywords: - TODO - FIXME - OPTIMIZE - HACK - REVIEW Style/DotPosition: Description: Checks the position of the dot in multi-line method calls. StyleGuide: https://github.com/bbatsov/ruby-style-guide#consistent-multi-line-chains Enabled: true EnforcedStyle: trailing SupportedStyles: - leading - trailing Style/EmptyLineBetweenDefs: Description: Use empty lines between defs. StyleGuide: https://github.com/bbatsov/ruby-style-guide#empty-lines-between-methods Enabled: true AllowAdjacentOneLineDefs: false Style/EmptyLinesAroundBlockBody: Description: Keeps track of empty lines around block bodies. Enabled: true EnforcedStyle: no_empty_lines SupportedStyles: - empty_lines - no_empty_lines Style/EmptyLinesAroundClassBody: Description: Keeps track of empty lines around class bodies. Enabled: true EnforcedStyle: no_empty_lines SupportedStyles: - empty_lines - no_empty_lines Style/EmptyLinesAroundModuleBody: Description: Keeps track of empty lines around module bodies. Enabled: true EnforcedStyle: no_empty_lines SupportedStyles: - empty_lines - no_empty_lines Style/Encoding: Description: Use UTF-8 as the source file encoding. StyleGuide: https://github.com/bbatsov/ruby-style-guide#utf-8 Enabled: false EnforcedStyle: always SupportedStyles: - when_needed - always Style/FileName: Description: Use snake_case for source file names. StyleGuide: https://github.com/bbatsov/ruby-style-guide#snake-case-files Enabled: false Exclude: [] Style/FirstParameterIndentation: Description: Checks the indentation of the first parameter in a method call. Enabled: true EnforcedStyle: special_for_inner_method_call_in_parentheses SupportedStyles: - consistent - special_for_inner_method_call - special_for_inner_method_call_in_parentheses Style/For: Description: Checks use of for or each in multiline loops. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-for-loops Enabled: true EnforcedStyle: each SupportedStyles: - for - each Style/FormatString: Description: Enforce the use of Kernel#sprintf, Kernel#format or String#%. StyleGuide: https://github.com/bbatsov/ruby-style-guide#sprintf Enabled: false EnforcedStyle: format SupportedStyles: - format - sprintf - percent Style/GlobalVars: Description: Do not introduce global variables. StyleGuide: https://github.com/bbatsov/ruby-style-guide#instance-vars Enabled: false AllowedVariables: [] Style/GuardClause: Description: Check for conditionals that can be replaced with guard clauses StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals Enabled: false MinBodyLength: 1 Style/HashSyntax: Description: 'Prefer Ruby 1.9 hash syntax { a: 1, b: 2 } over 1.8 syntax { :a => 1, :b => 2 }.' StyleGuide: https://github.com/bbatsov/ruby-style-guide#hash-literals Enabled: true EnforcedStyle: ruby19 SupportedStyles: - ruby19 - hash_rockets Style/IfUnlessModifier: Description: Favor modifier if/unless usage when you have a single-line body. StyleGuide: https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier Enabled: false MaxLineLength: 80 Style/IndentationWidth: Description: Use 2 spaces for indentation. StyleGuide: https://github.com/bbatsov/ruby-style-guide#spaces-indentation Enabled: true Width: 2 Style/IndentHash: Description: Checks the indentation of the first key in a hash literal. Enabled: true EnforcedStyle: special_inside_parentheses SupportedStyles: - special_inside_parentheses - consistent Style/LambdaCall: Description: Use lambda.call(...) instead of lambda.(...). StyleGuide: https://github.com/bbatsov/ruby-style-guide#proc-call Enabled: false EnforcedStyle: call SupportedStyles: - call - braces Style/Next: Description: Use `next` to skip iteration instead of a condition at the end. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals Enabled: false EnforcedStyle: skip_modifier_ifs MinBodyLength: 3 SupportedStyles: - skip_modifier_ifs - always Style/NonNilCheck: Description: Checks for redundant nil checks. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-non-nil-checks Enabled: true IncludeSemanticChanges: false Style/MethodDefParentheses: Description: Checks if the method definitions have or don't have parentheses. StyleGuide: https://github.com/bbatsov/ruby-style-guide#method-parens Enabled: true EnforcedStyle: require_parentheses SupportedStyles: - require_parentheses - require_no_parentheses Style/MethodName: Description: Use the configured style when naming methods. StyleGuide: https://github.com/bbatsov/ruby-style-guide#snake-case-symbols-methods-vars Enabled: true EnforcedStyle: snake_case SupportedStyles: - snake_case - camelCase Style/MultilineOperationIndentation: Description: Checks indentation of binary operations that span more than one line. Enabled: true EnforcedStyle: aligned SupportedStyles: - aligned - indented Style/NumericLiterals: Description: Add underscores to large numeric literals to improve their readability. StyleGuide: https://github.com/bbatsov/ruby-style-guide#underscores-in-numerics Enabled: false MinDigits: 5 Style/ParenthesesAroundCondition: Description: Don't use parentheses around the condition of an if/unless/while. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-parens-if Enabled: true AllowSafeAssignment: true Style/PercentLiteralDelimiters: Description: Use `%`-literal delimiters consistently StyleGuide: https://github.com/bbatsov/ruby-style-guide#percent-literal-braces Enabled: false PreferredDelimiters: "%": "()" "%i": "()" "%q": "()" "%Q": "()" "%r": "{}" "%s": "()" "%w": "()" "%W": "()" "%x": "()" Style/PercentQLiterals: Description: Checks if uses of %Q/%q match the configured preference. Enabled: true EnforcedStyle: lower_case_q SupportedStyles: - lower_case_q - upper_case_q Style/PredicateName: Description: Check the names of predicate methods. StyleGuide: https://github.com/bbatsov/ruby-style-guide#bool-methods-qmark Enabled: true NamePrefix: - is_ - has_ - have_ NamePrefixBlacklist: - is_ Exclude: - spec/**/* Style/RaiseArgs: Description: Checks the arguments passed to raise/fail. StyleGuide: https://github.com/bbatsov/ruby-style-guide#exception-class-messages Enabled: false EnforcedStyle: exploded SupportedStyles: - compact - exploded Style/RedundantReturn: Description: Don't use return where it's not required. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-explicit-return Enabled: true AllowMultipleReturnValues: false Style/RegexpLiteral: Description: Use %r for regular expressions matching more than `MaxSlashes` '/' characters. Use %r only for regular expressions matching more than `MaxSlashes` '/' character. StyleGuide: https://github.com/bbatsov/ruby-style-guide#percent-r Enabled: false Style/Semicolon: Description: Don't use semicolons to terminate expressions. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-semicolon Enabled: true AllowAsExpressionSeparator: false Style/SignalException: Description: Checks for proper usage of fail and raise. StyleGuide: https://github.com/bbatsov/ruby-style-guide#fail-method Enabled: false EnforcedStyle: semantic SupportedStyles: - only_raise - only_fail - semantic Style/SingleLineBlockParams: Description: Enforces the names of some block params. StyleGuide: https://github.com/bbatsov/ruby-style-guide#reduce-blocks Enabled: false Methods: - reduce: - a - e - inject: - a - e Style/SingleLineMethods: Description: Avoid single-line methods. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-single-line-methods Enabled: false AllowIfMethodIsEmpty: true Style/StringLiterals: Description: Checks if uses of quotes match the configured preference. StyleGuide: https://github.com/bbatsov/ruby-style-guide#consistent-string-literals Enabled: true EnforcedStyle: double_quotes SupportedStyles: - single_quotes - double_quotes Style/StringLiteralsInInterpolation: Description: Checks if uses of quotes inside expressions in interpolated strings match the configured preference. Enabled: true EnforcedStyle: single_quotes SupportedStyles: - single_quotes - double_quotes Style/SpaceAroundBlockParameters: Description: Checks the spacing inside and after block parameters pipes. Enabled: true EnforcedStyleInsidePipes: no_space SupportedStyles: - space - no_space Style/SpaceAroundEqualsInParameterDefault: Description: Checks that the equals signs in parameter default assignments have or don't have surrounding space depending on configuration. StyleGuide: https://github.com/bbatsov/ruby-style-guide#spaces-around-equals Enabled: true EnforcedStyle: space SupportedStyles: - space - no_space Style/SpaceBeforeBlockBraces: Description: Checks that the left block brace has or doesn't have space before it. Enabled: true EnforcedStyle: space SupportedStyles: - space - no_space Style/SpaceInsideBlockBraces: Description: Checks that block braces have or don't have surrounding space. For blocks taking parameters, checks that the left brace has or doesn't have trailing space. Enabled: true EnforcedStyle: space SupportedStyles: - space - no_space EnforcedStyleForEmptyBraces: no_space SpaceBeforeBlockParameters: true Style/SpaceInsideHashLiteralBraces: Description: Use spaces inside hash literal braces - or don't. StyleGuide: https://github.com/bbatsov/ruby-style-guide#spaces-operators Enabled: true EnforcedStyle: space EnforcedStyleForEmptyBraces: no_space SupportedStyles: - space - no_space Style/SymbolProc: Description: Use symbols as procs instead of blocks when possible. Enabled: true IgnoredMethods: - respond_to Style/TrailingBlankLines: Description: Checks trailing blank lines and final newline. StyleGuide: https://github.com/bbatsov/ruby-style-guide#newline-eof Enabled: true EnforcedStyle: final_newline SupportedStyles: - final_newline - final_blank_line Style/TrailingComma: Description: Checks for trailing comma in parameter lists and literals. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas Enabled: false EnforcedStyleForMultiline: no_comma SupportedStyles: - comma - no_comma Style/TrivialAccessors: Description: Prefer attr_* methods to trivial readers/writers. StyleGuide: https://github.com/bbatsov/ruby-style-guide#attr_family Enabled: false ExactNameMatch: false AllowPredicates: false AllowDSLWriters: false Whitelist: - to_ary - to_a - to_c - to_enum - to_h - to_hash - to_i - to_int - to_io - to_open - to_path - to_proc - to_r - to_regexp - to_str - to_s - to_sym Style/VariableName: Description: Use the configured style when naming variables. StyleGuide: https://github.com/bbatsov/ruby-style-guide#snake-case-symbols-methods-vars Enabled: true EnforcedStyle: snake_case SupportedStyles: - snake_case - camelCase Style/WhileUntilModifier: Description: Favor modifier while/until usage when you have a single-line body. StyleGuide: https://github.com/bbatsov/ruby-style-guide#while-as-a-modifier Enabled: false MaxLineLength: 80 Style/WordArray: Description: Use %w or %W for arrays of words. StyleGuide: https://github.com/bbatsov/ruby-style-guide#percent-w Enabled: false MinSize: 0 WordRegex: !ruby/regexp /\A[\p{Word}]+\z/ Metrics/AbcSize: Description: A calculated magnitude based on number of assignments, branches, and conditions. Enabled: false Max: 15 Metrics/BlockNesting: Description: Avoid excessive block nesting StyleGuide: https://github.com/bbatsov/ruby-style-guide#three-is-the-number-thou-shalt-count Enabled: false Max: 3 Metrics/ClassLength: Description: Avoid classes longer than 100 lines of code. Enabled: false CountComments: false Max: 100 Metrics/CyclomaticComplexity: Description: A complexity metric that is strongly correlated to the number of test cases needed to validate a method. Enabled: false Max: 6 Metrics/LineLength: Description: Limit lines to 80 characters. StyleGuide: https://github.com/bbatsov/ruby-style-guide#80-character-limits Enabled: true Max: 80 AllowURI: true URISchemes: - http - https Exclude: - lib/tmuxinator/window.rb - spec/lib/tmuxinator/window_spec.rb Metrics/MethodLength: Description: Avoid methods longer than 10 lines of code. StyleGuide: https://github.com/bbatsov/ruby-style-guide#short-methods Enabled: false CountComments: false Max: 10 Metrics/ParameterLists: Description: Avoid parameter lists longer than three or four parameters. StyleGuide: https://github.com/bbatsov/ruby-style-guide#too-many-params Enabled: false Max: 5 CountKeywordArgs: true Metrics/PerceivedComplexity: Description: A complexity metric geared towards measuring complexity for a human reader. Enabled: false Max: 7 Lint/AssignmentInCondition: Description: Don't use assignment in conditions. StyleGuide: https://github.com/bbatsov/ruby-style-guide#safe-assignment-in-condition Enabled: false AllowSafeAssignment: true Lint/EndAlignment: Description: Align ends correctly. Enabled: true AlignWith: keyword SupportedStyles: - keyword - variable Lint/DefEndAlignment: Description: Align ends corresponding to defs correctly. Enabled: true AlignWith: start_of_line SupportedStyles: - start_of_line - def Rails/ActionFilter: Description: Enforces consistent use of action filter methods. Enabled: false EnforcedStyle: action SupportedStyles: - action - filter Include: - app/controllers/**/*.rb Rails/DefaultScope: Description: Checks if the argument passed to default_scope is a block. Enabled: true Include: - app/models/**/*.rb Rails/HasAndBelongsToMany: Description: Prefer has_many :through to has_and_belongs_to_many. Enabled: true Include: - app/models/**/*.rb Rails/Output: Description: Checks for calls to puts, print, etc. Enabled: true Include: - app/**/*.rb - config/**/*.rb - db/**/*.rb - lib/**/*.rb Rails/ReadWriteAttribute: Description: Checks for read_attribute(:attr) and write_attribute(:attr, val). Enabled: true Include: - app/models/**/*.rb Rails/ScopeArgs: Description: Checks the arguments of ActiveRecord scopes. Enabled: true Include: - app/models/**/*.rb Rails/Validation: Description: Use validates :attribute, hash of validations. Enabled: true Include: - app/models/**/*.rb Style/InlineComment: Description: Avoid inline comments. Enabled: false Style/MethodCalledOnDoEndBlock: Description: Avoid chaining a method call on a do...end block. StyleGuide: https://github.com/bbatsov/ruby-style-guide#single-line-blocks Enabled: false Style/SymbolArray: Description: Use %i or %I for arrays of symbols. StyleGuide: https://github.com/bbatsov/ruby-style-guide#percent-i Enabled: false Style/ExtraSpacing: Description: Do not use unnecessary spacing. Enabled: true Style/AccessorMethodName: Description: Check the naming of accessor methods for get_/set_. Enabled: false Style/Alias: Description: Use alias_method instead of alias. StyleGuide: https://github.com/bbatsov/ruby-style-guide#alias-method Enabled: false Style/AlignArray: Description: Align the elements of an array literal if they span more than one line. StyleGuide: https://github.com/bbatsov/ruby-style-guide#align-multiline-arrays Enabled: true Style/ArrayJoin: Description: Use Array#join instead of Array#*. StyleGuide: https://github.com/bbatsov/ruby-style-guide#array-join Enabled: false Style/AsciiComments: Description: Use only ascii symbols in comments. StyleGuide: https://github.com/bbatsov/ruby-style-guide#english-comments Enabled: false Style/AsciiIdentifiers: Description: Use only ascii symbols in identifiers. StyleGuide: https://github.com/bbatsov/ruby-style-guide#english-identifiers Enabled: false Style/Attr: Description: Checks for uses of Module#attr. StyleGuide: https://github.com/bbatsov/ruby-style-guide#attr Enabled: false Style/BeginBlock: Description: Avoid the use of BEGIN blocks. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-BEGIN-blocks Enabled: true Style/BlockComments: Description: Do not use block comments. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-block-comments Enabled: true Style/BlockEndNewline: Description: Put end statement of multiline block on its own line. Enabled: true # Style/Blocks: # Description: Avoid using {...} for multi-line blocks (multiline chaining is always # ugly). Prefer {...} over do...end for single-line blocks. # StyleGuide: https://github.com/bbatsov/ruby-style-guide#single-line-blocks # Enabled: true Style/CaseEquality: Description: Avoid explicit use of the case equality operator(===). StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-case-equality Enabled: false Style/CharacterLiteral: Description: Checks for uses of character literals. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-character-literals Enabled: false Style/ClassAndModuleCamelCase: Description: Use CamelCase for classes and modules. StyleGuide: https://github.com/bbatsov/ruby-style-guide#camelcase-classes Enabled: true Style/ClassMethods: Description: Use self when defining module/class methods. StyleGuide: https://github.com/bbatsov/ruby-style-guide#def-self-singletons Enabled: true Style/ClassVars: Description: Avoid the use of class variables. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-class-vars Enabled: false Style/ColonMethodCall: Description: 'Do not use :: for method call.' StyleGuide: https://github.com/bbatsov/ruby-style-guide#double-colons Enabled: false Style/CommentIndentation: Description: Indentation of comments. Enabled: true Style/ConstantName: Description: Constants should use SCREAMING_SNAKE_CASE. StyleGuide: https://github.com/bbatsov/ruby-style-guide#screaming-snake-case Enabled: true Style/DefWithParentheses: Description: Use def with parentheses when there are arguments. StyleGuide: https://github.com/bbatsov/ruby-style-guide#method-parens Enabled: true Style/DeprecatedHashMethods: Description: Checks for use of deprecated Hash methods. StyleGuide: https://github.com/bbatsov/ruby-style-guide#hash-key Enabled: false Style/Documentation: Description: Document classes and non-namespace modules. Enabled: false Style/DoubleNegation: Description: Checks for uses of double negation (!!). StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-bang-bang Enabled: false Style/EachWithObject: Description: Prefer `each_with_object` over `inject` or `reduce`. Enabled: false Style/ElseAlignment: Description: Align elses and elsifs correctly. Enabled: true Style/EmptyElse: Description: Avoid empty else-clauses. Enabled: true Style/EmptyLines: Description: Don't use several empty lines in a row. Enabled: true Style/EmptyLinesAroundAccessModifier: Description: Keep blank lines around access modifiers. Enabled: true Style/EmptyLinesAroundMethodBody: Description: Keeps track of empty lines around method bodies. Enabled: true Style/EmptyLiteral: Description: Prefer literals to Array.new/Hash.new/String.new. StyleGuide: https://github.com/bbatsov/ruby-style-guide#literal-array-hash Enabled: false Style/EndBlock: Description: Avoid the use of END blocks. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-END-blocks Enabled: true Style/EndOfLine: Description: Use Unix-style line endings. StyleGuide: https://github.com/bbatsov/ruby-style-guide#crlf Enabled: true Style/EvenOdd: Description: Favor the use of Fixnum#even? && Fixnum#odd? StyleGuide: https://github.com/bbatsov/ruby-style-guide#predicate-methods Enabled: false Style/FlipFlop: Description: Checks for flip flops StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-flip-flops Enabled: false Style/IfWithSemicolon: Description: Do not use if x; .... Use the ternary operator instead. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-semicolon-ifs Enabled: false Style/IndentationConsistency: Description: Keep indentation straight. Enabled: true Style/IndentArray: Description: Checks the indentation of the first element in an array literal. Enabled: true Style/InfiniteLoop: Description: Use Kernel#loop for infinite loops. StyleGuide: https://github.com/bbatsov/ruby-style-guide#infinite-loop Enabled: true Style/Lambda: Description: Use the new lambda literal syntax for single-line blocks. StyleGuide: https://github.com/bbatsov/ruby-style-guide#lambda-multi-line Enabled: false Style/LeadingCommentSpace: Description: Comments should start with a space. StyleGuide: https://github.com/bbatsov/ruby-style-guide#hash-space Enabled: true Style/LineEndConcatenation: Description: Use \ instead of + or << to concatenate two string literals at line end. Enabled: false Style/MethodCallParentheses: Description: Do not use parentheses for method calls with no arguments. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-args-no-parens Enabled: true Style/ModuleFunction: Description: Checks for usage of `extend self` in modules. StyleGuide: https://github.com/bbatsov/ruby-style-guide#module-function Enabled: false Style/MultilineBlockChain: Description: Avoid multi-line chains of blocks. StyleGuide: https://github.com/bbatsov/ruby-style-guide#single-line-blocks Enabled: true Style/MultilineBlockLayout: Description: Ensures newlines after multiline block do statements. Enabled: true Style/MultilineIfThen: Description: Do not use then for multi-line if/unless. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-then Enabled: true Style/MultilineTernaryOperator: Description: 'Avoid multi-line ?: (the ternary operator); use if/unless instead.' StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-multiline-ternary Enabled: true Style/NegatedIf: Description: Favor unless over if for negative conditions (or control flow or). StyleGuide: https://github.com/bbatsov/ruby-style-guide#unless-for-negatives Enabled: false Style/NegatedWhile: Description: Favor until over while for negative conditions. StyleGuide: https://github.com/bbatsov/ruby-style-guide#until-for-negatives Enabled: false Style/NestedTernaryOperator: Description: Use one expression per branch in a ternary operator. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-nested-ternary Enabled: true Style/NilComparison: Description: Prefer x.nil? to x == nil. StyleGuide: https://github.com/bbatsov/ruby-style-guide#predicate-methods Enabled: false Style/Not: Description: Use ! instead of not. StyleGuide: https://github.com/bbatsov/ruby-style-guide#bang-not-not Enabled: false Style/OneLineConditional: Description: Favor the ternary operator(?:) over if/then/else/end constructs. StyleGuide: https://github.com/bbatsov/ruby-style-guide#ternary-operator Enabled: false Style/OpMethod: Description: When defining binary operators, name the argument other. StyleGuide: https://github.com/bbatsov/ruby-style-guide#other-arg Enabled: false Style/PerlBackrefs: Description: Avoid Perl-style regex back references. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-perl-regexp-last-matchers Enabled: false Style/Proc: Description: Use proc instead of Proc.new. StyleGuide: https://github.com/bbatsov/ruby-style-guide#proc Enabled: false Style/RedundantBegin: Description: Don't use begin blocks when they are not needed. StyleGuide: https://github.com/bbatsov/ruby-style-guide#begin-implicit Enabled: true Style/RedundantException: Description: Checks for an obsolete RuntimeException argument in raise/fail. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-explicit-runtimeerror Enabled: true Style/RedundantSelf: Description: Don't use self where it's not needed. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-self-unless-required Enabled: true Style/RescueModifier: Description: Avoid using rescue in its modifier form. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-rescue-modifiers Enabled: true Style/SelfAssignment: Description: Checks for places where self-assignment shorthand should have been used. StyleGuide: https://github.com/bbatsov/ruby-style-guide#self-assignment Enabled: false Style/SingleSpaceBeforeFirstArg: Description: Checks that exactly one space is used between a method name and the first argument for method calls without parentheses. Enabled: true Style/SpaceAfterColon: Description: Use spaces after colons. StyleGuide: https://github.com/bbatsov/ruby-style-guide#spaces-operators Enabled: true Style/SpaceAfterComma: Description: Use spaces after commas. StyleGuide: https://github.com/bbatsov/ruby-style-guide#spaces-operators Enabled: true Style/SpaceAfterControlKeyword: Description: Use spaces after if/elsif/unless/while/until/case/when. Enabled: true Style/SpaceAfterMethodName: Description: Do not put a space between a method name and the opening parenthesis in a method definition. StyleGuide: https://github.com/bbatsov/ruby-style-guide#parens-no-spaces Enabled: true Style/SpaceAfterNot: Description: Tracks redundant space after the ! operator. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-space-bang Enabled: true Style/SpaceAfterSemicolon: Description: Use spaces after semicolons. StyleGuide: https://github.com/bbatsov/ruby-style-guide#spaces-operators Enabled: true Style/SpaceBeforeComma: Description: No spaces before commas. Enabled: true Style/SpaceBeforeComment: Description: Checks for missing space between code and a comment on the same line. Enabled: true Style/SpaceBeforeSemicolon: Description: No spaces before semicolons. Enabled: true Style/SpaceAroundOperators: Description: Use spaces around operators. StyleGuide: https://github.com/bbatsov/ruby-style-guide#spaces-operators Enabled: true Style/SpaceBeforeModifierKeyword: Description: Put a space before the modifier keyword. Enabled: true Style/SpaceInsideBrackets: Description: No spaces after [ or before ]. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-spaces-braces Enabled: true Style/SpaceInsideParens: Description: No spaces after ( or before ). StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-spaces-braces Enabled: true Style/SpaceInsideRangeLiteral: Description: No spaces inside range literals. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-space-inside-range-literals Enabled: true Style/SpecialGlobalVars: Description: Avoid Perl-style global variables. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-cryptic-perlisms Enabled: false Style/StructInheritance: Description: Checks for inheritance from Struct.new. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-extend-struct-new Enabled: true Style/Tab: Description: No hard tabs. StyleGuide: https://github.com/bbatsov/ruby-style-guide#spaces-indentation Enabled: true Style/TrailingWhitespace: Description: Avoid trailing whitespace. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-trailing-whitespace Enabled: true Style/UnlessElse: Description: Do not use unless with else. Rewrite these with the positive case first. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-else-with-unless Enabled: true Style/UnneededCapitalW: Description: Checks for %W when interpolation is not needed. Enabled: true Style/UnneededPercentQ: Description: Checks for %q/%Q when single quotes or double quotes would do. StyleGuide: https://github.com/bbatsov/ruby-style-guide#percent-q Enabled: true # Style/UnneededPercentX: # Description: Checks for %x when `` would do. # StyleGuide: https://github.com/bbatsov/ruby-style-guide#percent-x # Enabled: true Style/VariableInterpolation: Description: Don't interpolate global, instance and class variables directly in strings. StyleGuide: https://github.com/bbatsov/ruby-style-guide#curlies-interpolate Enabled: false Style/WhenThen: Description: Use when x then ... for one-line cases. StyleGuide: https://github.com/bbatsov/ruby-style-guide#one-line-cases Enabled: false Style/WhileUntilDo: Description: Checks for redundant do after while or until. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-multiline-while-do Enabled: true Lint/AmbiguousOperator: Description: Checks for ambiguous operators in the first argument of a method invocation without parentheses. StyleGuide: https://github.com/bbatsov/ruby-style-guide#parens-as-args Enabled: false Lint/AmbiguousRegexpLiteral: Description: Checks for ambiguous regexp literals in the first argument of a method invocation without parenthesis. Enabled: false Lint/BlockAlignment: Description: Align block ends correctly. Enabled: true Lint/ConditionPosition: Description: Checks for condition placed in a confusing position relative to the keyword. StyleGuide: https://github.com/bbatsov/ruby-style-guide#same-line-condition Enabled: false Lint/Debugger: Description: Check for debugger calls. Enabled: true Lint/DeprecatedClassMethods: Description: Check for deprecated class method calls. Enabled: false Lint/DuplicateMethods: Description: Check for duplicate methods calls. Enabled: true Lint/ElseLayout: Description: Check for odd code arrangement in an else block. Enabled: false Lint/EmptyEnsure: Description: Checks for empty ensure block. Enabled: true Lint/EmptyInterpolation: Description: Checks for empty string interpolation. Enabled: true Lint/EndInMethod: Description: END blocks should not be placed inside method definitions. Enabled: true Lint/EnsureReturn: Description: Do not use return in an ensure block. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-return-ensure Enabled: true Lint/Eval: Description: The use of eval represents a serious security risk. Enabled: true Lint/HandleExceptions: Description: Don't suppress exception. StyleGuide: https://github.com/bbatsov/ruby-style-guide#dont-hide-exceptions Enabled: false Lint/InvalidCharacterLiteral: Description: Checks for invalid character literals with a non-escaped whitespace character. Enabled: false Lint/LiteralInCondition: Description: Checks of literals used in conditions. Enabled: false Lint/LiteralInInterpolation: Description: Checks for literals used in interpolation. Enabled: false Lint/Loop: Description: Use Kernel#loop with break rather than begin/end/until or begin/end/while for post-loop tests. StyleGuide: https://github.com/bbatsov/ruby-style-guide#loop-with-break Enabled: false Lint/ParenthesesAsGroupedExpression: Description: Checks for method calls with a space before the opening parenthesis. StyleGuide: https://github.com/bbatsov/ruby-style-guide#parens-no-spaces Enabled: false Lint/RequireParentheses: Description: Use parentheses in the method call to avoid confusion about precedence. Enabled: false Lint/RescueException: Description: Avoid rescuing the Exception class. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-blind-rescues Enabled: true Lint/ShadowingOuterLocalVariable: Description: Do not use the same name as outer local variable for block arguments or block local variables. Enabled: true Lint/SpaceBeforeFirstArg: Description: Put a space between a method name and the first argument in a method call without parentheses. Enabled: true Lint/StringConversionInInterpolation: Description: Checks for Object#to_s usage in string interpolation. StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-to-s Enabled: true Lint/UnderscorePrefixedVariableName: Description: Do not use prefix `_` for a variable that is used. Enabled: false Lint/UnusedBlockArgument: Description: Checks for unused block arguments. StyleGuide: https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars Enabled: true Lint/UnusedMethodArgument: Description: Checks for unused method arguments. StyleGuide: https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars Enabled: true Lint/UnreachableCode: Description: Unreachable code. Enabled: true Lint/UselessAccessModifier: Description: Checks for useless access modifiers. Enabled: true Lint/UselessAssignment: Description: Checks for useless assignment to a local variable. StyleGuide: https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars Enabled: true Lint/UselessComparison: Description: Checks for comparison of something with itself. Enabled: true Lint/UselessElseWithoutRescue: Description: Checks for useless `else` in `begin..end` without `rescue`. Enabled: true Lint/UselessSetterCall: Description: Checks for useless setter call to a local variable. Enabled: true Lint/Void: Description: Possible use of operator/literal/variable in void context. Enabled: false Rails/Delegate: Description: Prefer delegate method for delegations. Enabled: false tmuxinator-0.9.0/.travis.yml0000644000175000017500000000117112776077541015717 0ustar uwabamiuwabamilanguage: ruby rvm: - "1.9.3" - "2.0.0" - "2.1.7" - "2.2.3" env: - TMUX_VERSION=master - TMUX_VERSION=2.1 - TMUX_VERSION=2.0 - TMUX_VERSION=1.9 - TMUX_VERSION=1.8 - TMUX_VERSION=1.7 - TMUX_VERSION=1.6 - TMUX_VERSION=1.5 matrix: allow_failures: - env: TMUX_VERSION=1.7 before_install: - gem install bundler - sudo apt-get update -qq - sudo apt-get install -qq libevent-dev libncurses-dev - git clone https://github.com/tmux/tmux.git tmux - cd tmux - git checkout $TMUX_VERSION - sh autogen.sh - ./configure && make && sudo make install - cd .. - tmux -V script: bundle exec rake test tmuxinator-0.9.0/CHANGELOG.md0000644000175000017500000001577112776077541015432 0ustar uwabamiuwabami## 0.9.0 ### Misc - Temporarily hiding Shorthand entry in README.md to prevent new bug reports about the mux symlink being broken - Use `alias` (bash, zsh) and `abbr` (fish) instead of a symlink to hash `mux`. #401 - replace instances of `File.exists?` (deprecated) with `File.exist?` - Refactor Config.root ### New Features - Allow mulitple panes to be defined using yaml hash or array #266, #406 - Add `startup_pane` #380 - Add synchronizations panes support #97 - Add `before` and `after` options to synchronization functionality - Add deprecation warning if `synchronize: true` or `before` is used ### Bugfixes - Supress `tmux ls` non-zero exit status/message when no sessions exist (#414) - Will no longer crash when no panes are specified in a window - Locking activesupport at < 5.0.0 to prevent broken builds on Ruby < 2.2.3 - Fixed whitespace issues in help ## 0.8.1 ### Bugfixes - Fixed broken shell completions ## 0.8.0 ### New features - Add support for deleting multiple projects at once, using `mux delete ...` - Add stop command to kill tmux sessions ### Bugfixes - Bugfix for issue with using numbers as window names - Bugfix for zsh-completion loading throwing an error if tmuxinator is not yet available. - Bugfix for using `mux delete` to delete local projects ## 0.7.2 - Bugfix for attaching to sessions by prefix when running `start` - Bugfix for "pane could not be created" error ## 0.7.1 - Bugfix where `mux open` or similar would delete the contents of the file ## 0.7.0 ### New features - Add support for starting in detached mode #307 - Support windows without names #292, #323 - Add per project `.tmuxinator.yml` support #335 :sparkles: - Support passing args on the command line #343 :tada: ### Bug fixes and Misc - Fix some RSpec deprecations - Explain what EBR is in the readme #319 - Prevent project names containing only numbers from raising a NoMethodError #324 - Fix YAML syntax highlighting in readme #325 - Add `asset_path` helper #326 - Switch to just plain Rubocop instead of hound #339 - Fix typo in readme #346 - Fix thor not returning correct exit status #192 - Add gitter badge ## 0.6.11 - Add aliasing of projects to create multiple sessions for a single project #143, #273 - ERB support for projects #267 - Post and attach options #293 - Fix typo in gemspec #294 - Fix completions not searching subdirectory #295 - Remove duplicate attribute #298 - Fix support for tmux 1.8 and below - Project cleanup #311 - Fix error when no project name is provided #303 ## 0.6.10 - Interpret config file as ERB template #255 - Fix zsh completions #262 - Alias `e` to edit and `o` to open #275 - Fix fish completions #280 - Add `startup_window` #282 - Add per window root option #283 - Fix project path detection #274 - Include completions in gemspec #270 ## 0.6.9 - Update to RSpec 3.x - Allow for earlier versions of thor #234, #235 - Remove dependency on git and fix warnings in gemspec #232, #233, #239 - Switch from `which` to `type` to stop errors in OSX 10.10 #236, #237 - Optional project root #185, #144 - Clear rbenv environment variables before starting tmux #208 - Update readme with correct fish completions path #247 - Escape path to deal with special characters #251, #256, #257 - Fix `copy` overwriting files #254, #258 ## 0.6.8 - Remove some duplication #212 - Add wemux support #88 - Thanks to Andrew Thal (@athal7) - Fix typos in readme #217, #216 - Fix encoding bug #229 - Fix specs not running due to changes in thor ## 0.6.7 - Remove use of grep for base-index #171 - Fix bugs in `Tmuxinator::Config.default?` #169 - Fix path for Rails log in directory sample #177 - Add completions for fish shell #179 - Fix grammar in readme #184 - Make commands take precedence over project names #182 - Improve error messages when $EDITOR isn't set #186, #194 - Add confirmation to deletion prompt #197 - Fix broken badge references after organisation move - Remove dependancy on ActiveSupport #199 - Fix compatability with tmux 1.9 ## 0.6.6 - Fix a bug caused by not escaping the root path #145 - Fix bash completion with a single argument #148 - Fix regression where an array of commands for a window wasn't working #149 - Add an option to call tmux wrappers or derivatives #154 - Refactor build\_panes to always return an array #157 - Clean up some branching code using `.presence` #163 - Setup TravisCI test matrix for different tmux versions #164 - Fix some grammar and spelling in readme #166 - Make multiple commands use tmux's `send-keys` rather than just using `&&` for both panes and windows #100 ## 0.6.5 - Change deprecation continue message from any key to just the enter key - Dramatically clean up the readme to be clearer for new users - Update the contributing guide with references to the GitHub styleguide and add examples of how to leave good commit messages - Use Erubis to render the project sample and fix a bad binding reference - Update the sample project to be much simpler - Fix not working delete command #142 - Fix an error in the bash completion script - Fix an issue where the wrong project path was being returned - Fix an issue where command aliases were being ignored ## 0.6.4 - Fixes broken backwards compatibility of multiple pre commands #129 - Fixes tmuxinator ignoring project root when started from within a tmux session #132 - Add gem version badge ## 0.6.3 - Remove stray pry #128 - Allow starting a tmuxinator project while inside a tmux session #130 - Set the tmux layout after pane creation to avoid pane too small errors #131 - Check for both pane-base-index and base-index #126 ## 0.6.2 - Also pass command line options to the `base_index` lookup. - Fixed bug #116. ## 0.6.1 - Remove stray binding.pry - Fix nil error when creating a new project. ## 0.6.0 - Rewrote core functionality with proper abstractions and unit tests - Fixed outstanding bugs #72 #89 #90 #93 #101 #102 #103 #104 #109 - Switched to thor for command line argument parsing - Switched to Erubis for more Rails like ERB - Added simplecov for test coverage - Added debug command line option to view generated shell commands - Added commands and completion options for completion scripts - Added `pre_window` option for running commands before all panes and windows - Deprecated `rbenv` in favour of `pre_window` - Deprecated `rvm` in favour of `pre_window` - Deprecated `cli_args` in favour of `tmux_options` - Deprecated `tabs` in favour of `windows` - Dropped support for Ruby 1.9.2 ## 0.5.0 - Added optional socket name support (Thanks to Adam Walters) - Added auto completion (Thanks to Jose Pablo Barrantes) ## 0.4.0 - Does not crash if given an invalid yaml file format. report it and exit gracefully. - Removed clunky scripts & shell aliases (Thanks to Dane O'Connor) - Config files are now rendered JIT (Thanks to Dane O'Connor) - Can now start sessions from cli (Thanks to Dane O'Connor) ## 0.3.0 - Added pre command (Thanks to Ian Yang) - Added multiple pre command (Thanks to Bjørn Arild Mæland) - Using tmux set default-path for project root - New aliases ## 0.2.0 - Added pane support (Thanks to Aaron Spiegel) - RVM support (Thanks to Jay Adkisoon) tmuxinator-0.9.0/CONTRIBUTING.md0000644000175000017500000000344212776077541016042 0ustar uwabamiuwabami# Contributing ## First * Check if the issue you're going to submit isn't already submitted in the [Issues](https://github.com/tmuxinator/tmuxinator/issues) page. ## Issues * Submit a ticket for your issue, assuming one does not already exist. * The issue must: * Clearly describe the problem including steps to reproduce when it is a bug. * Also include all the information you can to make it easier for us to reproduce it, like OS version, gem versions, rbenv or rvm versions etc... * Even better, provide a failing test case for it. ## Pull Requests If you've gone the extra mile and have a patch that fixes the issue, you should submit a Pull Request! * Please follow the [GitHub Styleguide](https://github.com/styleguide/ruby) for Ruby in both implementation and tests! * Fork the repo on Github. * Create a topic branch from where you want to base your work. * Add a test for your change. Only refactoring and documentation changes require no new tests. If you are adding functionality or fixing a bug, we need a test! * Run _all_ the tests to ensure nothing else was broken. We only take pull requests with passing tests. You can run the tests with `rake test`. * Make a note in the `CHANGELOG.md` file with a brief summary of your change under the heading "Unreleased" at the top of the file. If that heading does not exist, you should add it. * Check for unnecessary whitespace with `git diff --check` before committing. * Structure your commit messages like this: ``` Summarize clearly in one line what the commit is about Describe the problem the commit solves or the use case for a new feature. Justify why you chose the particular solution. ``` * Use "fix", "add", "change" instead of "fixed", "added", "changed" in your commit messages. * Push to your fork and submit a pull request. tmuxinator-0.9.0/Rakefile0000644000175000017500000000025312776077541015253 0ustar uwabamiuwabamirequire "bundler/gem_tasks" require "rubocop/rake_task" require "rspec/core/rake_task" RuboCop::RakeTask.new RSpec::Core::RakeTask.new task :test => ["spec", "rubocop"] tmuxinator-0.9.0/tmuxinator.gemspec0000644000175000017500000000306012776077541017364 0ustar uwabamiuwabami# coding: utf-8 lib = File.expand_path("../lib", __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require "tmuxinator/version" Gem::Specification.new do |s| s.name = "tmuxinator" s.version = Tmuxinator::VERSION s.authors = ["Allen Bargi", "Christopher Chow"] s.email = ["allen.bargi@gmail.com", "chris@chowie.net"] s.description = %q{Create and manage complex tmux sessions easily.} s.summary = %q{Create and manage complex tmux sessions easily.} s.homepage = "https://github.com/tmuxinator/tmuxinator" s.license = "MIT" s.files = Dir["lib/**/*", "spec/**/*", "bin/*", "completion/*"] s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) } s.test_files = s.files.grep(%r{^(test|spec|features)/}) s.require_paths = ["lib"] s.post_install_message = %q{ __________________________________________________________ .......................................................... Thank you for installing tmuxinator. Make sure that you've set these variables in your ENV: $EDITOR, $SHELL You can run `tmuxinator doctor` to make sure everything is set. Happy tmuxing with tmuxinator! .......................................................... __________________________________________________________ } s.required_rubygems_version = ">= 1.8.23" s.required_ruby_version = ">= 1.9.3" s.add_dependency "thor", "~> 0.19", ">= 0.15.0" s.add_dependency "erubis", "~> 2.6" s.add_development_dependency "bundler", "~> 1.3" end tmuxinator-0.9.0/spec/0000755000175000017500000000000012776077541014540 5ustar uwabamiuwabamitmuxinator-0.9.0/spec/matchers/0000755000175000017500000000000012776077541016346 5ustar uwabamiuwabamitmuxinator-0.9.0/spec/matchers/pane_matcher.rb0000644000175000017500000000167712776077541021334 0ustar uwabamiuwabamiRSpec::Matchers.alias_matcher :be_a_pane, :a_pane RSpec::Matchers.define :a_pane do attr_reader :commands match do result = is_pane result && attributes_match if @expected_attrs result &&= commands_match if commands result end failure_message do |actual| return "Expected #{actual} to be a Tmuxinator::Pane" unless is_pane msg = "Actual pane does not match expected" msg << "\n Expected #{@commands} but has #{actual.commands}" if @commands msg << "\n Expected pane to have #{@expected_attrs}" if @expected_attrs end chain :with do |attrs| @expected_attrs = attrs end chain :with_commands do |*expected| @commands = expected end alias_method :and_commands, :with_commands private def attributes_match expect(@actual).to have_attributes(@expected_attrs) end def commands_match @actual.commands == commands end def is_pane @actual.is_a? Tmuxinator::Pane end end tmuxinator-0.9.0/spec/spec_helper.rb0000644000175000017500000000233212776077541017356 0ustar uwabamiuwabamirequire "coveralls" require "simplecov" require "pry" formatters = [ SimpleCov::Formatter::HTMLFormatter, Coveralls::SimpleCov::Formatter ] SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(formatters) SimpleCov.start do add_filter "vendor/cache" end require "tmuxinator" require "factory_girl" FactoryGirl.find_definitions # Custom Matchers require_relative "matchers/pane_matcher" RSpec.configure do |config| config.order = "random" end # Copied from minitest. def capture_io require "stringio" captured_stdout = StringIO.new captured_stderr = StringIO.new orig_stdout = $stdout orig_stderr = $stderr $stdout = captured_stdout $stderr = captured_stderr yield return captured_stdout.string, captured_stderr.string ensure $stdout = orig_stdout $stderr = orig_stderr end def tmux_config(options = {}) standard_options = [ "assume-paste-time 1", "bell-action any", "bell-on-alert off", ] if base_index = options.fetch(:base_index) { 1 } standard_options << "base-index #{base_index}" end if pane_base_index = options.fetch(:pane_base_index) { 1 } standard_options << "pane-base-index #{pane_base_index}" end "echo '#{standard_options.join("\n")}'" end tmuxinator-0.9.0/spec/lib/0000755000175000017500000000000012776077541015306 5ustar uwabamiuwabamitmuxinator-0.9.0/spec/lib/tmuxinator/0000755000175000017500000000000012776077541017520 5ustar uwabamiuwabamitmuxinator-0.9.0/spec/lib/tmuxinator/cli_spec.rb0000644000175000017500000003704512776077541021637 0ustar uwabamiuwabamirequire "spec_helper" describe Tmuxinator::Cli do let(:cli) { Tmuxinator::Cli } before do ARGV.clear allow(Kernel).to receive(:system) allow(FileUtils).to receive(:copy_file) allow(FileUtils).to receive(:rm) allow(FileUtils).to receive(:remove_dir) end context "no arguments" do it "runs without error" do _, err = capture_io { cli.start } expect(err).to be_empty end end describe "#completions" do before do ARGV.replace(["completions", "start"]) allow(Tmuxinator::Config).to receive_messages(configs: ["test.yml", "foo.yml"]) end it "gets completions" do out, _err = capture_io { cli.start } expect(out).to include("test.yml\nfoo.yml") end end describe "#commands" do before do ARGV.replace(["commands"]) end it "lists the commands" do out, _err = capture_io { cli.start } expected = %w(commands completions new edit open start stop local debug copy delete implode version doctor list) expect(out).to eq "#{expected.join("\n")}\n" end end describe "#start" do before do ARGV.replace(["start", "foo"]) allow(Tmuxinator::Config).to receive_messages(validate: project) allow(Tmuxinator::Config).to receive_messages(version: 1.9) allow(Kernel).to receive(:exec) end context "no deprecations" do let(:project) { FactoryGirl.build(:project) } it "starts the project" do expect(Kernel).to receive(:exec) capture_io { cli.start } end it "accepts a flag for alternate name" do ARGV.replace(["start", "foo" "--name=bar"]) expect(Kernel).to receive(:exec) capture_io { cli.start } end it "accepts additional arguments" do ARGV.replace(["start", "foo", "bar", "three=four"]) expect(Kernel).to receive(:exec) capture_io { cli.start } end end context "deprecations" do before do allow($stdin).to receive_messages(getc: "y") end let(:project) { FactoryGirl.build(:project_with_deprecations) } it "prints the deprecations" do out, _err = capture_io { cli.start } expect(out).to include "DEPRECATION" end end end describe "#stop" do before do ARGV.replace(["stop", "foo"]) allow(Tmuxinator::Config).to receive_messages(validate: project) allow(Tmuxinator::Config).to receive_messages(version: 1.9) allow(Kernel).to receive(:exec) end context "with project name" do let(:project) { FactoryGirl.build(:project) } it "stop the project" do expect(Kernel).to receive(:exec) out, err = capture_io { cli.start } expect(err).to eq "" expect(out).to eq "" end end end describe "#local" do shared_examples_for :local_project do before do allow(Tmuxinator::Config).to receive_messages(validate: project) allow(Tmuxinator::Config).to receive_messages(version: 1.9) allow(Kernel).to receive(:exec) end let(:project) { FactoryGirl.build(:project) } it "starts the project" do expect(Kernel).to receive(:exec) out, err = capture_io { cli.start } expect(err).to eq "" expect(out).to eq "" end end context "when the command used is 'local'" do before do ARGV.replace ["local"] end it_should_behave_like :local_project end context "when the command used is '.'" do before do ARGV.replace ["."] end it_should_behave_like :local_project end end describe "#start(custom_name)" do before do ARGV.replace(["start", "foo", "bar"]) allow(Tmuxinator::Config).to receive_messages(validate: project) allow(Tmuxinator::Config).to receive_messages(version: 1.9) allow(Kernel).to receive(:exec) end context "no deprecations" do let(:project) { FactoryGirl.build(:project) } it "starts the project" do expect(Kernel).to receive(:exec) capture_io { cli.start } end end end describe "#edit" do let(:file) { StringIO.new } let(:name) { "test" } let(:path) { Tmuxinator::Config.default_project(name) } context "when the project file _does_ already exist" do let(:extra) { " - extra: echo 'foobar'" } before do # make sure that no project file exists initially FileUtils.remove_file(path) if File.exist?(path) expect(File).not_to exist(path) # now generate a project file expect(Tmuxinator::Cli.new.generate_project_file(name, path)).to eq path expect(File).to exist path # add some content to the project file File.open(path, "w") do |f| f.write(extra) f.flush end expect(File.read(path)).to match %r{#{extra}} # get ready to run `tmuxinator edit #{name}` ARGV.replace ["edit", name] end it "should _not_ generate a new project file" do capture_io { cli.start } expect(File.read(path)).to match %r{#{extra}} end end end describe "#new" do let(:file) { StringIO.new } let(:name) { "test" } before do allow(File).to receive(:open) { |&block| block.yield file } end context "without the --local option" do before do ARGV.replace(["new", name]) end context "existing project doesn't exist" do before do expect(File).to receive_messages(exist?: false) end it "creates a new tmuxinator project file" do capture_io { cli.start } expect(file.string).to_not be_empty end end context "files exists" do let(:root_path) { "#{ENV['HOME']}\/\.tmuxinator\/#{name}\.yml" } before do allow(File).to receive(:exist?).with(anything).and_return(false) expect(File).to receive(:exist?).with(root_path).and_return(true) end it "just opens the file" do expect(Kernel).to receive(:system).with(%r{#{root_path}}) capture_io { cli.start } end end end context "with the --local option" do before do ARGV.replace ["new", name, "--local"] end context "existing project doesn't exist" do before do allow(File).to receive(:exist?).at_least(:once) do false end end it "creates a new tmuxinator project file" do capture_io { cli.start } expect(file.string).to_not be_empty end end context "files exists" do let(:path) { Tmuxinator::Config::LOCAL_DEFAULT } before do expect(File).to receive(:exist?).with(path) { true } end it "just opens the file" do expect(Kernel).to receive(:system).with(%r{#{path}}) capture_io { cli.start } end end end end describe "#copy" do before do ARGV.replace(["copy", "foo", "bar"]) allow(Tmuxinator::Config).to receive(:exists?) { true } end context "new project already exists" do before do allow(Thor::LineEditor).to receive_messages(readline: "y") end it "prompts user to confirm overwrite" do expect(FileUtils).to receive(:copy_file) capture_io { cli.start } end end context "existing project doens't exist" do before do allow(Tmuxinator::Config).to receive(:exists?) { false } end it "exit with error code" do expect { capture_io { cli.start } }.to raise_error SystemExit end end end describe "#debug" do let(:project) { FactoryGirl.build(:project) } let(:project_with_force_attach) do FactoryGirl.build(:project_with_force_attach) end let(:project_with_force_detach) do FactoryGirl.build(:project_with_force_detach) end before do allow(Tmuxinator::Config).to receive_messages(validate: project) expect(project).to receive(:render) end it "renders the project" do ARGV.replace(["debug", "foo"]) capture_io { cli.start } end it "force attach renders the project with attach code" do ARGV.replace(["debug", "--attach=true", "sample"]) capture_io { cli.start } # Currently no project is rendered at all, # because the project file is not found # expect(out).to include "attach-session" end it "force detach renders the project without attach code" do ARGV.replace(["debug", "--attach=false", "sample"]) capture_io { cli.start } # Currently no project is rendered at all # expect(out).to_not include "attach-session" end it "renders the project with custom session" do ARGV.replace(["debug", "sample", "bar"]) capture_io { cli.start } end end describe "#delete" do context "with a single argument" do before do ARGV.replace(["delete", "foo"]) allow(Thor::LineEditor).to receive_messages(readline: "y") end context "project exists" do before do allow(Tmuxinator::Config).to receive(:exists?) { true } end it "deletes the project" do expect(FileUtils).to receive(:rm) capture_io { cli.start } end end context "local project exists" do before do allow(Tmuxinator::Config).to receive(:exists?) { true } expect(Tmuxinator::Config).to receive(:project) { "local" } end it "deletes the local project" do expect(FileUtils).to receive(:rm).with("local") capture_io { cli.start } end end context "project doesn't exist" do before do allow(Tmuxinator::Config).to receive(:exists?) { false } end it "outputs an error message" do expect(capture_io { cli.start }[0]).to match(/foo does not exist!/) end end end context "with multiple arguments" do before do ARGV.replace(["delete", "foo", "bar"]) allow(Thor::LineEditor).to receive_messages(readline: "y") end context "all projects exist" do before do allow(Tmuxinator::Config).to receive(:exists?).and_return(true) end it "deletes the projects" do expect(FileUtils).to receive(:rm).exactly(2).times capture_io { cli.start } end end context "only one project exists" do before do allow(Tmuxinator::Config).to receive(:exists?).with("foo") { true } allow(Tmuxinator::Config).to receive(:exists?).with("bar") { false } end it "deletes one project" do expect(FileUtils).to receive(:rm) capture_io { cli.start } end it "outputs an error message" do expect(capture_io { cli.start }[0]).to match(/bar does not exist!/) end end context "all projects do not exist" do before do allow(Tmuxinator::Config).to receive(:exists?).and_return(false) end it "outputs multiple error messages" do expect(capture_io { cli.start }[0]). to match(/foo does not exist!\nbar does not exist!/) end end end end describe "#implode" do before do ARGV.replace(["implode"]) allow(Thor::LineEditor).to receive_messages(readline: "y") end it "confirms deletion of all projects" do expect(Thor::LineEditor).to receive(:readline).and_return("y") capture_io { cli.start } end it "deletes all projects" do expect(FileUtils).to receive(:remove_dir) capture_io { cli.start } end end describe "#list" do before do ARGV.replace(["list"]) allow(Dir).to receive_messages(:[] => ["/path/to/project.yml"]) end it "lists all projects" do expect { capture_io { cli.start } }.to_not raise_error end end describe "#version" do before do ARGV.replace(["version"]) end it "prints the current version" do out, _err = capture_io { cli.start } expect(out).to eq "tmuxinator #{Tmuxinator::VERSION}\n" end end describe "#doctor" do before do ARGV.replace(["doctor"]) end it "checks requirements" do expect(Tmuxinator::Config).to receive(:installed?) expect(Tmuxinator::Config).to receive(:editor?) expect(Tmuxinator::Config).to receive(:shell?) capture_io { cli.start } end end describe "#find_project_file" do let(:name) { "foobar" } let(:path) { Tmuxinator::Config.default_project(name) } after(:each) do FileUtils.remove_file(path) if File.exist?(path) end context "when the project file does not already exist" do before do expect(File).not_to exist(path), "expected file at #{path} not to exist" end it "should generate a project file" do new_path = Tmuxinator::Cli.new.find_project_file(name, false) expect(new_path).to eq path expect(File).to exist new_path end end context "when the project file _does_ already exist" do let(:extra) { " - extra: echo 'foobar'" } before do expect(File).not_to exist(path), "expected file at #{path} not to exist" expect(Tmuxinator::Cli.new.generate_project_file(name, path)).to eq path expect(File).to exist path File.open(path, "w") do |f| f.write(extra) f.flush end expect(File.read(path)).to match %r{#{extra}} end it "should _not_ generate a new project file" do new_path = Tmuxinator::Cli.new.find_project_file(name, false) expect(new_path).to eq path expect(File).to exist new_path expect(File.read(new_path)).to match %r{#{extra}} end end end describe "#generate_project_file" do let(:name) { "foobar" } let(:path) { Tmuxinator::Config.default_project(name) } before do expect(File).not_to exist(path), "expected file at #{path} not to exist" end after(:each) do FileUtils.remove_file(path) if File.exist?(path) end it "should always generate a project file" do new_path = Tmuxinator::Cli.new.generate_project_file(name, path) expect(new_path).to eq path expect(File).to exist new_path end end describe "#create_project" do shared_examples_for :a_proper_project do it "should create a valid project" do expect(subject).to be_a Tmuxinator::Project expect(subject.name).to eq name end end let(:name) { "sample" } let(:custom_name) { nil } let(:cli_options) { {} } let(:path) { File.expand_path("../../../fixtures", __FILE__) } context "when creating a traditional named project" do let(:params) do { name: name, custom_name: custom_name } end subject { described_class.new.create_project(params) } before do allow(Tmuxinator::Config).to receive_messages(root: path) end it_should_behave_like :a_proper_project end end context "exit status" do before do ARGV.replace(["non-existent-command"]) end it "returns a non-zero status when an error occurs" do expect { capture_io { cli.start } }.to raise_error(SystemExit) do |e| expect(e.status).to eq 1 end end end end tmuxinator-0.9.0/spec/lib/tmuxinator/window_spec.rb0000644000175000017500000002133312776077541022370 0ustar uwabamiuwabamirequire "spec_helper" describe Tmuxinator::Window do let(:project) { double } let(:panes) { ["vim", nil, "top"] } let(:window_name) { "editor" } let(:synchronize) { false } let(:yaml) do { window_name => { "pre" => [ "echo 'I get run in each pane. Before each pane command!'", nil ], "synchronize" => synchronize, "layout" => "main-vertical", "panes" => panes } } end let(:yaml_root) do { "editor" => { "root" => "/project/override", "root?" => true, "pre" => [ "echo 'I get run in each pane. Before each pane command!'", nil ], "layout" => "main-vertical", "panes" => panes } } end let(:window) { Tmuxinator::Window.new(yaml, 0, project) } let(:window_root) { Tmuxinator::Window.new(yaml_root, 0, project) } shared_context "window command context" do let(:project) { double(:project) } let(:window) { Tmuxinator::Window.new(yaml, 0, project) } let(:root?) { true } let(:root) { "/project/tmuxinator" } before do allow(project).to receive_messages( name: "test", tmux: "tmux", root: root, root?: root?, base_index: 1 ) end let(:tmux_part) { project.tmux } end before do allow(project).to receive_messages( tmux: "tmux", name: "test", base_index: 1, root: "/project/tmuxinator", root?: true ) end describe "#initialize" do it "creates an instance" do expect(window).to be_a(Tmuxinator::Window) end end describe "#root" do context "without window root" do it "gets the project root" do expect(window.root).to include("/project/tmuxinator") end end context "with window root" do it "gets the window root" do expect(window_root.root).to include("/project/override") end end end describe "#panes" do context "with a three element Array" do let(:panes) { ["vim", "ls", "top"] } it "creates three panes" do expect(Tmuxinator::Pane).to receive(:new).exactly(3).times window.panes end it "returns three panes" do expect(window.panes).to all be_a_pane.with( project: project, tab: window ) expect(window.panes).to match([ a_pane.with(index: 0).and_commands("vim"), a_pane.with(index: 1).and_commands("ls"), a_pane.with(index: 2).and_commands("top") ]) end end context "with a String" do let(:panes) { "vim" } it "returns one pane in an Array" do expect(window.panes.first).to be_a_pane. with(index: 0).and_commands("vim") end end context "with nil" do let(:panes) { nil } it "returns an empty Array" do expect(window.panes).to be_empty end end context "nested collections" do let(:command1) { "cd /tmp/" } let(:command2) { "ls" } let(:panes) { ["vim", nested_collection] } context "with nested hash" do let(:nested_collection) { { pane2: [command1, command2] } } it "returns two panes in an Array" do expect(window.panes).to match [ a_pane.with(index: 0).and_commands("vim"), a_pane.with(index: 1).and_commands(command1, command2) ] end end context "with nested array" do let(:nested_collection) { [command1, command2] } it "returns two panes in an Array" do expect(window.panes).to match [ a_pane.with(index: 0).and_commands("vim"), a_pane.with(index: 1).and_commands(command1, command2) ] end end end end describe "#pre" do context "pre is a string" do before do yaml["editor"]["pre"] = "vim" end it "returns the pre command" do expect(window.pre).to eq "vim" end end context "pre is not present" do before do yaml["editor"].delete("pre") end it "returns nil" do expect(window.pre).to be_nil end end end describe "#build_commands" do context "command is an array" do before do yaml["editor"] = ["git fetch", "git status"] end it "returns the flattened command" do expect(window.commands).to eq [ "tmux send-keys -t test:1 git\\ fetch C-m", "tmux send-keys -t test:1 git\\ status C-m" ] end end context "command is a string" do before do yaml["editor"] = "vim" end it "returns the command" do expect(window.commands).to eq ["tmux send-keys -t test:1 vim C-m"] end end context "command is empty" do before do yaml["editor"] = "" end it "returns an empty array" do expect(window.commands).to be_empty end end context "command is a hash" do before do yaml["editor"] = { "layout" => "main-horizontal", "panes" => [nil] } end it "returns an empty array" do expect(window.commands).to be_empty end end end describe "#name_options" do context "with a name" do let(:window_name) { "editor" } it "specifies name with tmux name option" do expect(window.tmux_window_name_option).to eq "-n #{window_name}" end end context "without a name" do let(:window_name) { nil } it "specifies no tmux name option" do expect(window.tmux_window_name_option).to be_empty end end end describe "#synchronize_before?" do subject { window.synchronize_before? } context "synchronize is 'before'" do let(:synchronize) { "before" } it { is_expected.to be true } end context "synchronize is true" do let(:synchronize) { true } it { is_expected.to be true } end context "synchronize is 'after'" do let(:synchronize) { "after" } it { is_expected.to be false } end context "synchronization disabled" do let(:synchronize) { false } it { is_expected.to be false } end context "synchronization not specified" do it { is_expected.to be false } end end describe "#synchronize_after?" do subject { window.synchronize_after? } context "synchronization is 'after'" do let(:synchronize) { "after" } it { is_expected.to be true } end context "synchronization is true" do let(:synchronize) { true } it { is_expected.to be false } end context "synchronization is 'before'" do let(:synchronize) { "before" } it { is_expected.to be false } end context "synchronization disabled" do let(:synchronize) { false } it { is_expected.to be false } end context "synchronization not specified" do it { is_expected.to be false } end end describe "#tmux_synchronize_panes" do include_context "window command context" let(:window_option_set_part) { "set-window-option" } let(:target_part) { "-t #{window.tmux_window_target}" } let(:synchronize_panes_part) { "synchronize-panes" } context "synchronization enabled" do let(:synchronize) { true } let(:enabled) { "on" } let(:full_command) do "#{tmux_part} #{window_option_set_part} #{target_part} #{synchronize_panes_part} #{enabled}" end it "should set the synchronize-panes window option on" do expect(window.tmux_synchronize_panes).to eq full_command end end end describe "#tmux_new_window_command" do include_context "window command context" let(:window_part) { "new-window" } let(:name_part) { window.tmux_window_name_option } let(:target_part) { "-t #{window.tmux_window_target}" } let(:path_part) { "#{path_option} #{project.root}" } let(:path_option) { "-c" } let(:full_command) do "#{tmux_part} #{window_part} #{path_part} #{target_part} #{name_part}" end before do allow(Tmuxinator::Config).to receive(:default_path_option) { path_option } end it "contstructs window command with path, target, and name options" do expect(window.tmux_new_window_command).to eq full_command end context "root not set" do let(:root?) { false } let(:root) { nil } let(:path_part) { nil } it "has an extra space instead of path_part" do expect(window.tmux_new_window_command).to eq full_command end end context "name not set" do let(:window_name) { nil } let(:full_command) do "#{tmux_part} #{window_part} #{path_part} #{target_part} " end it "does not set name option" do expect(window.tmux_new_window_command).to eq full_command end end end end tmuxinator-0.9.0/spec/lib/tmuxinator/config_spec.rb0000644000175000017500000001652512776077541022335 0ustar uwabamiuwabamirequire "spec_helper" describe Tmuxinator::Config do describe "#root" do it "is ~/.tmuxintaor" do expect(Tmuxinator::Config.root).to eq "#{ENV['HOME']}/.tmuxinator" end end describe "#sample" do it "gets the path of the sample project" do expect(Tmuxinator::Config.sample).to include("sample.yml") end end describe "#default" do it "gets the path of the default config" do expect(Tmuxinator::Config.default).to include("default.yml") end end describe "#default_path_option" do context ">= 1.8" do before do allow(Tmuxinator::Config).to receive(:version).and_return(1.8) end it "returns -c" do expect(Tmuxinator::Config.default_path_option).to eq "-c" end end context "< 1.8" do before do allow(Tmuxinator::Config).to receive(:version).and_return(1.7) end it "returns default-path" do expect(Tmuxinator::Config.default_path_option).to eq "default-path" end end end describe "#default?" do let(:root) { Tmuxinator::Config.root } let(:local_default) { Tmuxinator::Config::LOCAL_DEFAULT } let(:proj_default) { Tmuxinator::Config.default } context "when the file exists" do before do allow(File).to receive(:exist?).with(local_default) { false } allow(File).to receive(:exist?).with(proj_default) { true } end it "returns true" do expect(Tmuxinator::Config.default?).to be_truthy end end context "when the file doesn't exist" do before do allow(File).to receive(:exist?).with(local_default) { false } allow(File).to receive(:exist?).with(proj_default) { false } end it "returns true" do expect(Tmuxinator::Config.default?).to be_falsey end end end describe "#configs" do before do allow(Dir).to receive_messages(:[] => ["test.yml"]) end it "gets a list of all projects" do expect(Tmuxinator::Config.configs).to include("test") end end describe "#installed?" do context "tmux is installed" do before do allow(Kernel).to receive(:system) { true } end it "returns true" do expect(Tmuxinator::Config.installed?).to be_truthy end end context "tmux is not installed" do before do allow(Kernel).to receive(:system) { false } end it "returns true" do expect(Tmuxinator::Config.installed?).to be_falsey end end end describe "#editor?" do context "$EDITOR is set" do before do allow(ENV).to receive(:[]).with("EDITOR") { "vim" } end it "returns true" do expect(Tmuxinator::Config.editor?).to be_truthy end end context "$EDITOR is not set" do before do allow(ENV).to receive(:[]).with("EDITOR") { nil } end it "returns false" do expect(Tmuxinator::Config.editor?).to be_falsey end end end describe "#shell?" do context "$SHELL is set" do before do allow(ENV).to receive(:[]).with("SHELL") { "vim" } end it "returns true" do expect(Tmuxinator::Config.shell?).to be_truthy end end context "$SHELL is not set" do before do allow(ENV).to receive(:[]).with("SHELL") { nil } end it "returns false" do expect(Tmuxinator::Config.shell?).to be_falsey end end end describe "#exists?" do before do allow(File).to receive_messages(exist?: true) allow(Tmuxinator::Config).to receive_messages(project: "") end it "checks if the given project exists" do expect(Tmuxinator::Config.exists?("test")).to be_truthy end end describe "#project_in_root" do let(:root) { Tmuxinator::Config.root } let(:base) { "#{root}/sample.yml" } before do path = File.expand_path("../../../fixtures/", __FILE__) allow(Tmuxinator::Config).to receive_messages(root: path) end context "with project yml" do it "gets the project as path to the yml file" do expect(Tmuxinator::Config.project_in_root("sample")).to eq base end end context "without project yml" do it "gets the project as path to the yml file" do expect(Tmuxinator::Config.project_in_root("new-project")).to be_nil end end end describe "#local?" do it "checks if the given project exists" do path = Tmuxinator::Config::LOCAL_DEFAULT expect(File).to receive(:exist?).with(path) { true } expect(Tmuxinator::Config.local?).to be_truthy end end describe "#project_in_local" do let(:default) { Tmuxinator::Config::LOCAL_DEFAULT } context "with a project yml" do it "gets the project as path to the yml file" do expect(File).to receive(:exist?).with(default) { true } expect(Tmuxinator::Config.project_in_local).to eq default end end context "without project yml" do it "gets the project as path to the yml file" do expect(Tmuxinator::Config.project_in_local).to be_nil end end end describe "#project" do let(:root) { Tmuxinator::Config.root } let(:path) { File.expand_path("../../../fixtures/", __FILE__) } let(:default) { Tmuxinator::Config::LOCAL_DEFAULT } context "with project yml in the root directory" do before do allow(Tmuxinator::Config).to receive_messages(root: path) end it "gets the project as path to the yml file" do expect(Tmuxinator::Config.project("sample")).to eq "#{root}/sample.yml" end end context "with a local project, but no project in root" do it "gets the project as path to the yml file" do expect(File).to receive(:exist?).with(default) { true } expect(Tmuxinator::Config.project("sample")).to eq "./.tmuxinator.yml" end end context "without project yml" do let(:expected) { "#{root}/new-project.yml" } it "gets the project as path to the yml file" do expect(Tmuxinator::Config.project("new-project")).to eq expected end end end describe "#validate" do let(:path) { File.expand_path("../../../fixtures", __FILE__) } let(:default) { Tmuxinator::Config::LOCAL_DEFAULT } context "when a project name is provided" do it "should raise if the project file can't be found" do expect do Tmuxinator::Config.validate(name: "sample") end.to raise_error RuntimeError, %r{Project.+doesn't.exist} end it "should load and validate the project" do expect(Tmuxinator::Config).to receive_messages(root: path) expect(Tmuxinator::Config.validate(name: "sample")).to \ be_a Tmuxinator::Project end end context "when no project name is provided" do it "should raise if the local project file doesn't exist" do expect(File).to receive(:exist?).with(default) { false } expect do Tmuxinator::Config.validate end.to raise_error RuntimeError, %r{Project.+doesn't.exist} end it "should load and validate the project" do content = File.read(File.join(path, "sample.yml")) expect(File).to receive(:exist?).with(default).at_least(:once) { true } expect(File).to receive(:read).with(default).and_return(content) expect(Tmuxinator::Config.validate).to be_a Tmuxinator::Project end end end end tmuxinator-0.9.0/spec/lib/tmuxinator/util_spec.rb0000644000175000017500000000015512776077541022035 0ustar uwabamiuwabamirequire "spec_helper" describe Tmuxinator::Util do let(:util) { Object.new.extend(Tmuxinator::Util) } end tmuxinator-0.9.0/spec/lib/tmuxinator/pane_spec.rb0000644000175000017500000000025312776077541022002 0ustar uwabamiuwabamirequire "spec_helper" describe Tmuxinator::Pane do it "creates an instance" do expect(Tmuxinator::Pane.new("vim", 0, nil, nil)).to be_a(Tmuxinator::Pane) end end tmuxinator-0.9.0/spec/lib/tmuxinator/project_spec.rb0000644000175000017500000003664312776077541022541 0ustar uwabamiuwabamirequire "spec_helper" describe Tmuxinator::Project do let(:project) { FactoryGirl.build(:project) } let(:project_with_custom_name) do FactoryGirl.build(:project_with_custom_name) end let(:project_with_number_as_name) do FactoryGirl.build(:project_with_number_as_name) end let(:project_with_literals_as_window_name) do FactoryGirl.build(:project_with_literals_as_window_name) end let(:project_with_deprecations) do FactoryGirl.build(:project_with_deprecations) end let(:project_with_force_attach) do FactoryGirl.build(:project_with_force_attach) end let(:project_with_force_detach) do FactoryGirl.build(:project_with_force_detach) end let(:wemux_project) { FactoryGirl.build(:wemux_project) } let(:noname_project) { FactoryGirl.build(:noname_project) } let(:noroot_project) { FactoryGirl.build(:noroot_project) } let(:nameless_window_project) do FactoryGirl.build(:nameless_window_project) end describe "#initialize" do context "valid yaml" do it "creates an instance" do expect(project).to be_a(Tmuxinator::Project) end end end describe "#render" do it "renders the tmux config" do expect(project.render).to_not be_empty end context "wemux" do it "renders the wemux config" do expect(wemux_project.render).to_not be_empty end end context "custom name" do it "renders the tmux config with custom name" do rendered = project_with_custom_name.render expect(rendered).to_not be_empty expect(rendered).to include("custom") expect(rendered).to_not include("sample") end end end describe "#tmux_has_session?" do context "no active sessions" do before do cmd = "#{project.tmux_command} ls 2> /dev/null" resp = "" call_tmux_ls = receive(:`).with(cmd).at_least(:once).and_return(resp) expect(project).to call_tmux_ls end it "should return false if no sessions are found" do expect(project.tmux_has_session?("no server running")).to be false end end context "active sessions" do before do cmd = "#{project.tmux_command} ls 2> /dev/null" resp = ""\ "foo: 1 window (created Sun May 25 10:12:00 1986) [0x0] (detached)\n"\ "bar: 1 window (created Sat Sept 01 00:00:00 1990) [0x0] (detached)" call_tmux_ls = receive(:`).with(cmd).at_least(:once).and_return(resp) expect(project).to call_tmux_ls end it "should return true only when `tmux ls` has the named session" do expect(project.tmux_has_session?("foo")).to be true expect(project.tmux_has_session?("bar")).to be true expect(project.tmux_has_session?("quux")).to be false end it "should return false if a partial (prefix) match is found" do expect(project.tmux_has_session?("foobar")).to be false end end end describe "#windows" do context "without deprecations" do it "gets the list of windows" do expect(project.windows).to_not be_empty end end context "with deprecations" do it "still gets the list of windows" do expect(project_with_deprecations.windows).to_not be_empty end end end describe "#root" do context "without deprecations" do it "gets the root" do expect(project.root).to include("test") end end context "with deprecations" do it "still gets the root" do expect(project_with_deprecations.root).to include("test") end end context "without root" do it "doesn't throw an error" do expect { noroot_project.root }.to_not raise_error end end end describe "#name" do context "without deprecations" do it "gets the name" do expect(project.name).to eq "sample" end end context "with deprecations" do it "still gets the name" do expect(project_with_deprecations.name).to eq "sample" end end context "wemux" do it "is wemux" do expect(wemux_project.name).to eq "wemux" end end context "without name" do it "displays error message" do expect { noname_project.name }.to_not raise_error end end context "as number" do it "will gracefully handle a name given as a number" do rendered = project_with_number_as_name expect(rendered.name.to_i).to_not equal 0 end end context "window as non-string literal" do it "will gracefully handle a window name given as a non-string literal" do rendered = project_with_literals_as_window_name expect(rendered.windows.map(&:name)).to match_array( %w(222 222333 111222333444555666777 222.3 4e5 4E5 true false nil // /sample/)) end end end describe "#pre_window" do it "gets the pre_window command" do expect(project.pre_window).to eq "rbenv shell 2.0.0-p247" end context "with deprecations" do context "rbenv option is present" do before do allow(project).to receive_messages(rbenv?: true) allow(project).to \ receive_message_chain(:yaml, :[]).and_return("2.0.0-p247") end it "still gets the correct pre_window command" do expect(project.pre_window).to eq "rbenv shell 2.0.0-p247" end end context "rvm option is present" do before do allow(project).to receive_messages(rbenv?: false) allow(project).to \ receive_message_chain(:yaml, :[]).and_return("ruby-2.0.0-p247") end it "still gets the correct pre_window command" do expect(project.pre_window).to eq "rvm use ruby-2.0.0-p247" end end context "pre_tab is present" do before do allow(project).to receive_messages(rbenv?: false) allow(project).to receive_messages(pre_tab?: true) end it "still gets the correct pre_window command" do expect(project.pre_window).to be_nil end end end end describe "#socket" do context "socket path is present" do before do allow(project).to receive_messages(socket_path: "/tmp") end it "gets the socket path" do expect(project.socket).to eq " -S /tmp" end end end describe "#tmux_command" do context "tmux_command specified" do before do project.yaml["tmux_command"] = "byobu" end it "gets the custom tmux command" do expect(project.tmux_command).to eq "byobu" end end context "tmux_command is not specified" do it "returns the default" do expect(project.tmux_command).to eq "tmux" end end end describe "#tmux_options" do context "no tmux options" do before do allow(project).to receive_messages(tmux_options?: false) end it "returns nothing" do expect(project.tmux_options).to eq "" end end context "with deprecations" do before do allow(project_with_deprecations).to receive_messages(cli_args?: true) end it "still gets the tmux options" do expect(project_with_deprecations.tmux_options).to \ eq " -f ~/.tmux.mac.conf" end end end describe "#get_pane_base_index" do it "extracts the pane_base_index from tmux_options" do allow(project).to \ receive_messages(show_tmux_options: tmux_config(pane_base_index: 3)) expect(project.get_pane_base_index).to eq("3") end end describe "#get_base_index" do it "extracts the base index from options" do allow(project).to \ receive_messages(show_tmux_options: tmux_config(base_index: 1)) expect(project.get_base_index).to eq("1") end end describe "#base_index" do context "pane base index present" do before do allow(project).to receive_messages(get_pane_base_index: "1") allow(project).to receive_messages(get_base_index: "1") end it "gets the pane base index" do expect(project.base_index).to eq 1 end end context "pane base index no present" do before do allow(project).to receive_messages(get_pane_base_index: nil) allow(project).to receive_messages(get_base_index: "0") end it "gets the base index" do expect(project.base_index).to eq 0 end end end describe "#startup_window" do context "startup window specified" do it "gets the startup window from project config" do project.yaml["startup_window"] = "logs" expect(project.startup_window).to eq("logs") end end context "startup window not specified" do it "returns base index instead" do allow(project).to receive_messages(base_index: 8) expect(project.startup_window).to eq 8 end end end describe "#startup_pane" do context "startup pane specified" do it "get the startup pane index from project config" do project.yaml["startup_pane"] = 1 expect(project.startup_pane).to eq(1) end end context "startup pane not specified" do it "returns the base pane instead" do allow(project).to receive_messages(pane_base_index: 4) expect(project.startup_pane).to eq(4) end end end describe "#window" do it "gets the window and index for tmux" do expect(project.window(1)).to eq "sample:1" end end describe "#name?" do context "name is present" do it "returns true" do expect(project.name?).to be_truthy end end end describe "#windows?" do context "windows are present" do it "returns true" do expect(project.windows?).to be_truthy end end end describe "#root?" do context "root are present" do it "returns true" do expect(project.root?).to be_truthy end end end describe "#send_keys" do context "no command for window" do it "returns empty string" do expect(project.send_keys("", 1)).to be_empty end end context "command for window is not empty" do it "returns the tmux command" do expect(project.send_keys("vim", 1)).to \ eq "tmux -f ~/.tmux.mac.conf -L foo send-keys -t sample:1 vim C-m" end end end describe "#send_pane_command" do context "no command for pane" do it "returns empty string" do expect(project.send_pane_command("", 0, 0)).to be_empty end end context "command for pane is not empty" do it "returns the tmux command" do expect(project.send_pane_command("vim", 1, 0)).to \ eq "tmux -f ~/.tmux.mac.conf -L foo send-keys -t sample:1 vim C-m" end end end describe "#deprecations" do context "without deprecations" do it "is empty" do expect(project.deprecations).to be_empty end end context "with deprecations" do it "is not empty" do expect(project_with_deprecations.deprecations).to_not be_empty end end end describe "#commands" do let(:window) { project.windows.keep_if { |w| w.name == "shell" }.first } it "splits commands into an array" do commands = [ "tmux -f ~/.tmux.mac.conf -L foo send-keys -t sample:1 git\\ pull C-m", "tmux -f ~/.tmux.mac.conf -L foo send-keys -t sample:1 git\\ merge C-m" ] expect(window.commands).to eq(commands) end end describe "#pre" do subject(:pre) { project.pre } context "pre in yaml is string" do before { project.yaml["pre"] = "mysql.server start" } it "returns the string" do expect(pre).to eq("mysql.server start") end end context "pre in yaml is Array" do before do project.yaml["pre"] = [ "mysql.server start", "memcached -d" ] end it "joins array using ;" do expect(pre).to eq("mysql.server start; memcached -d") end end end describe "#attach?" do context "attach is true in yaml" do before { project.yaml["attach"] = true } it "returns true" do expect(project.attach?).to be_truthy end end context "attach is not defined in yaml" do it "returns true" do expect(project.attach?).to be_truthy end end context "attach is false in yaml" do before { project.yaml["attach"] = false } it "returns false" do expect(project.attach?).to be_falsey end end context "attach is true in yaml, but command line forces detach" do before { project_with_force_attach.yaml["attach"] = true } it "returns false" do expect(project_with_force_detach.attach?).to be_falsey end end context "attach is false in yaml, but command line forces attach" do before { project_with_force_detach.yaml["attach"] = false } it "returns true" do expect(project_with_force_attach.attach?).to be_truthy end end end describe "tmux_new_session_command" do let(:command) { "#{executable} new-session -d -s #{session} -n #{window}" } let(:executable) { project.tmux } let(:session) { project.name } let(:window) { project.windows.first.name } context "when first window has a name" do it "returns command to start a new detatched session" do expect(project.tmux_new_session_command).to eq command end end context "when first window is nameless" do let(:project) { nameless_window_project } let(:command) { "#{project.tmux} new-session -d -s #{project.name} " } it "returns command to for new detatched session without a window name" do expect(project.tmux_new_session_command).to eq command end end end describe "tmux_kill_session_command" do let(:command) { "#{executable} kill-session -t #{session}" } let(:executable) { project.tmux } let(:session) { project.name } context "when first window has a name" do it "returns command to start a new detatched session" do expect(project.tmux_kill_session_command).to eq command end end end describe "::load" do let(:path) { File.expand_path("../../../fixtures/sample.yml", __FILE__) } let(:options) { {} } it "should raise if the project file doesn't parse" do bad_yaml = <<-Y name: "foo" subkey: Y expect(File).to receive(:read).with(path) { bad_yaml } expect do described_class.load(path, options) end.to raise_error RuntimeError, %r{Failed.to.parse.config.file} end it "should return an instance of the class if the file loads" do expect(described_class.load(path, options)).to be_a Tmuxinator::Project end end describe "::parse_settings" do let(:args) { ["one", "two=three"] } it "returns settings in a hash" do expect(described_class.parse_settings(args)["two"]).to eq("three") end it "removes settings from args" do described_class.parse_settings(args) expect(args).to eq(["one"]) end end describe "#validate!" do it "should raise if there are no windows defined" do nowindows_project = FactoryGirl.build(:nowindows_project) expect do nowindows_project.validate! end.to raise_error RuntimeError, %r{should.include.some.windows} end it "should raise if there is not a project name" do expect do noname_project.validate! end.to raise_error RuntimeError, %r{didn't.specify.a.'project_name'} end end end tmuxinator-0.9.0/spec/lib/tmuxinator/wemux_support_spec.rb0000644000175000017500000000214312776077541024020 0ustar uwabamiuwabamirequire "spec_helper" describe Tmuxinator::WemuxSupport do let(:klass) { Class.new { include Tmuxinator::WemuxSupport } } let(:instance) { klass.new } it { expect(instance).to respond_to :wemux? } it { expect(instance).to respond_to :load_wemux_overrides } describe "#load_wemux_overrides" do before { instance.load_wemux_overrides } it "adds a render method" do expect(instance).to respond_to :render end it "adds a name method" do expect(instance).to respond_to :name end it "adds a tmux method" do expect(instance).to respond_to :tmux end end describe "#render" do before { instance.load_wemux_overrides } it "renders the template" do expect(File).to receive(:read).at_least(:once) { "wemux ls 2>/dev/null" } expect(instance.render).to match %r{wemux.ls.2>\/dev\/null} end end describe "#name" do before { instance.load_wemux_overrides } it { expect(instance.name).to eq "wemux" } end describe "#tmux" do before { instance.load_wemux_overrides } it { expect(instance.tmux).to eq "wemux" } end end tmuxinator-0.9.0/spec/factories/0000755000175000017500000000000012776077541016517 5ustar uwabamiuwabamitmuxinator-0.9.0/spec/factories/projects.rb0000644000175000017500000000516212776077541020701 0ustar uwabamiuwabamidef yaml_load(file) YAML.load(File.read(File.expand_path(file))) end FactoryGirl.define do factory :project, class: Tmuxinator::Project do transient do file { yaml_load("spec/fixtures/sample.yml") } end initialize_with { Tmuxinator::Project.new(file) } end factory :project_with_force_attach, class: Tmuxinator::Project do transient do file { yaml_load("spec/fixtures/detach.yml") } end initialize_with { Tmuxinator::Project.new(file, force_attach: true) } end factory :project_with_force_detach, class: Tmuxinator::Project do transient do file { yaml_load("spec/fixtures/detach.yml") } end initialize_with { Tmuxinator::Project.new(file, force_detach: true) } end factory :project_with_custom_name, class: Tmuxinator::Project do transient do file { yaml_load("spec/fixtures/sample.yml") } end initialize_with { Tmuxinator::Project.new(file, custom_name: "custom") } end factory :project_with_number_as_name, class: Tmuxinator::Project do transient do file { yaml_load("spec/fixtures/sample_number_as_name.yml") } end initialize_with { Tmuxinator::Project.new(file) } end factory :project_with_literals_as_window_name, class: Tmuxinator::Project do transient do file { yaml_load("spec/fixtures/sample_literals_as_window_name.yml") } end initialize_with { Tmuxinator::Project.new(file) } end factory :project_with_deprecations, class: Tmuxinator::Project do transient do file { yaml_load("spec/fixtures/sample.deprecations.yml") } end initialize_with { Tmuxinator::Project.new(file) } end factory :wemux_project, class: Tmuxinator::Project do transient do file { yaml_load("spec/fixtures/sample_wemux.yml") } end initialize_with { Tmuxinator::Project.new(file) } end factory :noname_project, class: Tmuxinator::Project do transient do file { yaml_load("spec/fixtures/noname.yml") } end initialize_with { Tmuxinator::Project.new(file) } end factory :noroot_project, class: Tmuxinator::Project do transient do file { yaml_load("spec/fixtures/noroot.yml") } end initialize_with { Tmuxinator::Project.new(file) } end factory :nowindows_project, class: Tmuxinator::Project do transient do file { yaml_load("spec/fixtures/nowindows.yml") } end initialize_with { Tmuxinator::Project.new(file) } end factory :nameless_window_project, class: Tmuxinator::Project do transient do file { yaml_load("spec/fixtures/nameless_window.yml") } end initialize_with { Tmuxinator::Project.new(file) } end end tmuxinator-0.9.0/spec/fixtures/0000755000175000017500000000000012776077541016411 5ustar uwabamiuwabamitmuxinator-0.9.0/spec/fixtures/noroot.yml0000644000175000017500000000014312776077541020452 0ustar uwabamiuwabami# ~/.tmuxinator/noroot.yml # you can make as many tabs as you wish... windows: - test: echo foo tmuxinator-0.9.0/spec/fixtures/sample.deprecations.yml0000644000175000017500000000164612776077541023103 0ustar uwabamiuwabami# ~/.tmuxinator/sample.deprecations.yml project_name: sample project_root: ~/test socket_name: foo # Remove to use default socket pre: sudo /etc/rc.d/mysqld start # Runs before everything rbenv: 2.0.0-p247 cli_args: -f ~/.tmux.mac.conf # Pass arguments to tmux tabs: - editor: pre: - echo "I get run in each pane, before each pane command!" - layout: main-vertical panes: - vim - #empty, will just run plain bash - top - shell: git pull - guard: layout: tiled pre: - echo "I get run in each pane." - echo "Before each pane command!" panes: - - #empty, will just run plain bash - - database: bundle exec rails db - server: bundle exec rails s - logs: tail -f log/development.log - console: bundle exec rails c - capistrano: - server: ssh user@example.com windows: - sample: - synchronize: true tmuxinator-0.9.0/spec/fixtures/sample.yml0000644000175000017500000000210112776077541020407 0ustar uwabamiuwabami# ~/.tmuxinator/sample.yml # you can make as many tabs as you wish... name: sample root: ~/test socket_name: foo # Remove to use default socket pre: sudo /etc/rc.d/mysqld start # Runs before everything pre_window: rbenv shell 2.0.0-p247 # Runs in each tab and pane tmux_options: -f ~/.tmux.mac.conf # Pass arguments to tmux tmux_detached: false windows: - editor: pre: - echo "I get run in each pane, before each pane command!" - layout: main-vertical panes: - vim - #empty, will just run plain bash - top - pane_with_multiple_commands: - ssh server - echo "Hello" - shell: - git pull - git merge - guard: layout: tiled pre: - echo "I get run in each pane." - echo "Before each pane command!" panes: - - #empty, will just run plain bash - - database: bundle exec rails db - server: bundle exec rails s - logs: tail -f log/development.log - console: bundle exec rails c - capistrano: - server: ssh user@example.com tmuxinator-0.9.0/spec/fixtures/noname.yml0000644000175000017500000000016012776077541020406 0ustar uwabamiuwabami# ~/.tmuxinator/noname.yml # you can make as many tabs as you wish... root: ~/test windows: - test: echo foo tmuxinator-0.9.0/spec/fixtures/sample_literals_as_window_name.yml0000644000175000017500000000112312776077541025363 0ustar uwabamiuwabami# ~/.tmuxinator/sample_literals_as_window_name.yml name: sample windows: - 222: echo Fixnum as window name fixture - 222_333: echo Fixnum as window name fixture - 111222333444555666777: echo BigNum as window name fixture - 222.3: echo Float as window name fixture - 4e5: echo Float as window name fixture - 4E5: echo Float as window name fixture - true: echo TrueClass as window name fixture - false: echo FalseClass as window name fixture - nil: echo NilClass as window name fixture - //: echo RegExp as window name fixture - /sample/: echo RegExp as window name fixture tmuxinator-0.9.0/spec/fixtures/nowindows.yml0000644000175000017500000000003312776077541021157 0ustar uwabamiuwabaminame: no_windows root: ~/ tmuxinator-0.9.0/spec/fixtures/detach.yml0000644000175000017500000000207212776077541020365 0ustar uwabamiuwabami# ~/.tmuxinator/sample.yml # you can make as many tabs as you wish... name: sample root: ~/test socket_name: foo # Remove to use default socket pre: sudo /etc/rc.d/mysqld start # Runs before everything pre_window: rbenv shell 2.0.0-p247 # Runs in each tab and pane tmux_options: -f ~/.tmux.mac.conf # Pass arguments to tmux attach: false windows: - editor: pre: - echo "I get run in each pane, before each pane command!" - layout: main-vertical panes: - vim - #empty, will just run plain bash - top - pane_with_multiple_commands: - ssh server - echo "Hello" - shell: - git pull - git merge - guard: layout: tiled pre: - echo "I get run in each pane." - echo "Before each pane command!" panes: - - #empty, will just run plain bash - - database: bundle exec rails db - server: bundle exec rails s - logs: tail -f log/development.log - console: bundle exec rails c - capistrano: - server: ssh user@example.com tmuxinator-0.9.0/spec/fixtures/nameless_window.yml0000644000175000017500000000017512776077541022335 0ustar uwabamiuwabaminame: nameless_window root: ~/ windows: - ~: echo "this is a window with no name" - other: echo "this window has a name" tmuxinator-0.9.0/spec/fixtures/sample_number_as_name.yml0000644000175000017500000000014612776077541023451 0ustar uwabamiuwabami# ~/.tmuxinator/sample_number_as_name.yml name: 222 windows: - number: echo number as name fixture tmuxinator-0.9.0/spec/fixtures/sample_wemux.yml0000644000175000017500000000167312776077541021651 0ustar uwabamiuwabami# ~/.tmuxinator/sample_wemux.yml # you can make as many tabs as you wish... name: sample root: ~/test pre: sudo /etc/rc.d/mysqld start # Runs before everything pre_window: rbenv shell 2.0.0-p247 # Runs in each tab and pane tmux_options: -f ~/.tmux.mac.conf # Pass arguments to tmux tmux_command: wemux windows: - editor: pre: - echo "I get run in each pane, before each pane command!" - layout: main-vertical panes: - vim - #empty, will just run plain bash - top - shell: - git pull - git merge - guard: layout: tiled pre: - echo "I get run in each pane." - echo "Before each pane command!" panes: - - #empty, will just run plain bash - - database: bundle exec rails db - server: bundle exec rails s - logs: tail -f log/development.log - console: bundle exec rails c - capistrano: - server: ssh user@example.com tmuxinator-0.9.0/Gemfile0000644000175000017500000000056212776077541015104 0ustar uwabamiuwabamisource "https://rubygems.org" # Specify your gem's dependencies in tmuxinator.gemspec gemspec gem "rake", "~> 10.4" gem "rspec", "~> 3.3" gem "simplecov", "~> 0.11.0" gem "coveralls", "~> 0.7" gem "awesome_print", "~> 1.2" gem "pry", "~> 0.10" gem "factory_girl", "~> 4.5" gem "rubocop", "0.35.1", require: false gem "activesupport", "< 5.0.0" # Please see issue #432 tmuxinator-0.9.0/README.md0000644000175000017500000002121612776077541015067 0ustar uwabamiuwabami# Tmuxinator [![Gem Version](https://badge.fury.io/rb/tmuxinator.svg)](http://badge.fury.io/rb/tmuxinator) [![Build Status](https://secure.travis-ci.org/tmuxinator/tmuxinator.png)](http://travis-ci.org/tmuxinator/tmuxinator?branch=master) [![Coverage Status](https://img.shields.io/coveralls/tmuxinator/tmuxinator.svg)](https://coveralls.io/r/tmuxinator/tmuxinator?branch=master) [![Code Climate](https://codeclimate.com/github/tmuxinator/tmuxinator/badges/gpa.svg)](https://codeclimate.com/github/tmuxinator/tmuxinator) [![Dependency Status](https://gemnasium.com/tmuxinator/tmuxinator.svg)](https://gemnasium.com/tmuxinator/tmuxinator) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/tmuxinator/tmuxinator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) Create and manage tmux sessions easily. ![Screenshot](https://f.cloud.github.com/assets/141213/916084/065fef7c-fe82-11e2-9c23-a9622c7d83c3.png) ## Installation ``` gem install tmuxinator ``` ## Editor and Shell tmuxinator uses your shell's default editor for opening files. If you're not sure what that is type: ``` bash echo $EDITOR ``` For me that produces "vim". If you want to change your default editor simply put a line in ~/.bashrc that changes it. Mine looks like this: ``` export EDITOR='vim' ``` ## tmux The recommended version of tmux to use is 1.8. Your mileage may vary for earlier versions. Refer to the FAQ for any odd behaviour. ### base-index If you use a `base-index` other than the default, please be sure to also set the `pane-base-index` ``` set-window-option -g pane-base-index 1 ``` ## Completion Download the appropriate completion file from the repo and `source` the file. The following are example where the completion file has been downloaded into `~/.bin`. ### bash Add the following to your `~/.bashrc`: source ~/.bin/tmuxinator.bash ### zsh Add the following to your `~/.zshrc`: source ~/.bin/tmuxinator.zsh ### fish Move `tmuxinator.fish` to your `completions` folder: cp ~/.bin/tmuxinator.fish ~/.config/fish/completions/ ## Usage A working knowledge of tmux is assumed. You should understand what windows and panes are in tmux. If not please consult the [man pages](http://manpages.ubuntu.com/manpages/precise/en/man1/tmux.1.html#contenttoc6) for tmux. ### Create a project Create or edit your projects with: ``` tmuxinator new [project] ``` For editing you can also use `tmuxinator open [project]`. `new` is aliased to `o`,`open`, `e`, `edit` and `n`. Please note that dots can't be used in project names as tmux uses them internally to delimit between windows and panes. Your default editor (`$EDITOR`) is used to open the file. If this is a new project you will see this default config: ```yaml # ~/.tmuxinator/sample.yml name: sample root: ~/ # Optional. tmux socket # socket_name: foo # Runs before everything. Use it to start daemons etc. # pre: sudo /etc/rc.d/mysqld start # Runs in each window and pane before window/pane specific commands. Useful for setting up interpreter versions. # pre_window: rbenv shell 2.0.0-p247 # Pass command line options to tmux. Useful for specifying a different tmux.conf. # tmux_options: -f ~/.tmux.mac.conf # Change the command to call tmux. This can be used by derivatives/wrappers like byobu. # tmux_command: byobu # Specifies (by name or index) which window will be selected on project startup. If not set, the first window is used. # startup_window: logs windows: - editor: layout: main-vertical panes: - vim - guard - server: bundle exec rails s - logs: tail -f log/development.log ``` ## Windows The windows option allows the specification of any number of tmux windows. Each window is denoted by a YAML array entry, followed by a name and command to be run. ```yaml windows: - editor: vim ``` ### Window specific root An optional root option can be specified per window: ```yaml name: test root: ~/projects/company windows: - small_project: root: ~/projects/company/small_project panes: - start this - start that ``` This takes precedence over the main root option. ## Panes **_Note that if you wish to use panes, make sure that you do not have `.` in your project name. tmux uses `.` to delimit between window and pane indices, and tmuxinator uses the project name in combination with these indices to target the correct pane or window._** Panes are optional and are children of window entries, but unlike windows, they do not need a name. In the following example, the `editor` window has 2 panes, one running vim, the other guard. ```yaml windows: - editor: layout: main-vertical panes: - vim - guard ``` The layout setting gets handed down to tmux directly, so you can choose from one of [the five standard layouts](http://manpages.ubuntu.com/manpages/precise/en/man1/tmux.1.html#contenttoc6) or [specify your own](http://stackoverflow.com/a/9976282/183537). ## Interpreter Managers & Environment Variables To use tmuxinator with rbenv, RVM, NVM etc, use the `pre_window` option. ```yaml pre_window: rbenv shell 2.0.0-p247 ``` These command(s) will run before any subsequent commands in all panes and windows. ## Custom attachment and post commands You can set tmuxinator to skip auto-attaching to the session by using the `attach` option. ```yaml attach: false ``` You can also run arbitrary commands by using the `post` option. This is useful if you want to attach to tmux in a non-standard way (e.g. for a program that makes use of tmux control mode like iTerm2). ```yaml post: tmux -CC attach ``` ## Passing directly to send-keys tmuxinator passes commands directly to send keys. This differs from simply chaining commands together using `&&` or `;`, in that tmux will directly send the commands to a shell as if you typed them in. This allows commands to be executed on a remote server over SSH for example. To support this both the window and pane options can take an array as an argument: ```yaml name: sample root: ~/ windows: - stats: - ssh stats@example.com - tail -f /var/log/stats.log - logs: layout: main-vertical panes: - logs: - ssh logs@example.com - cd /var/logs - tail -f development.log ``` ## ERB Project files support [ERB](https://en.wikipedia.org/wiki/ERuby#erb) for reusability across environments. Eg: ```yaml root: <%= ENV["MY_CUSTOM_DIR"] %> ``` You can also pass arguments to your projects, and access them with ERB. Simple arguments are available in an array named `@args`. Eg: ```bash $ tmuxinator start project foo ``` ```yaml # ~/.tmuxinator/project.yml name: project root: ~/<%= @args[0] %> ... ``` You can also pass key-value pairs using the format `key=value`. These will be available in a hash named `@settings`. Eg: ```bash $ tmuxinator start project workspace=~/workspace/todo ``` ```yaml # ~/.tmuxinator/project.yml name: project root: ~/<%= @settings["workspace"] %> ... ``` ## Starting a session This will fire up tmux with all the tabs and panes you configured. ``` tmuxinator start [project] -n [name] ``` If you use the optional `[name]` argument, it will start a new tmux session with the custom name provided. This is to enable reuse of a project without tmux session name collision. If there is a `./.tmuxinator.yml` file in the current working directory but not a named project file in `~/.tmuxinator`, tmuxinator will use the local file. This is primarily intended to be used for sharing tmux configurations in complex development environments. ## Shorthand The [shell completion files](#completion) also include a shorthand alias for tmuxinator that can be used in place of the full name. ``` mux [command] ``` ## Other Commands Copy an existing project. Aliased to `c` and `cp` ``` tmuxinator copy [existing] [new] ``` List all the projects you have configured. Aliased to `l` and `ls` ``` tmuxinator list ``` Remove a project. Aliased to `rm` ``` tmuxinator delete [project] ``` Remove all tmuxinator configs, aliases and scripts. Aliased to `i` ``` tmuxinator implode ``` Examines your environment and identifies problems with your configuration ``` tmuxinator doctor ``` Shows tmuxinator's help. Aliased to `h` ``` tmuxinator help ``` Shows the shell commands that get executed for a project ``` tmuxinator debug [project] ``` Shows tmuxinator's version. ``` tmuxinator version ``` ## FAQ ### Window names are not displaying properly? Add `export DISABLE_AUTO_TITLE=true` to your `.zshrc` or `.bashrc` ## Contributing To contribute, please read the [contributing guide](https://github.com/tmuxinator/tmuxinator/blob/master/CONTRIBUTING.md). ## Copyright Copyright (c) 2010-2016 Allen Bargi, Christopher Chow. See LICENSE for further details.