[DRE-commits] [tmuxinator] 01/05: Imported Upstream version 0.8.1

Youhei SASAKI uwabami-guest at moszumanska.debian.org
Wed Jun 1 12:33:55 UTC 2016


This is an automated email from the git hooks/post-receive script.

uwabami-guest pushed a commit to branch master
in repository tmuxinator.

commit 07ee2756b84cf0eb10a8a65b3e1162f2ec04dc7a
Author: Youhei SASAKI <uwabami at gfd-dennou.org>
Date:   Wed Jun 1 20:58:14 2016 +0900

    Imported Upstream version 0.8.1
---
 .travis.yml                                      |  10 +-
 CHANGELOG.md                                     |  36 +++-
 CONTRIBUTING.md                                  |   5 +-
 Gemfile                                          |   4 +-
 LICENSE                                          |   2 +-
 README.md                                        |   4 +-
 Rakefile                                         |  18 +-
 code_of_conduct.md                               |  74 ++++++++
 completion/tmuxinator.bash                       |   2 +-
 completion/tmuxinator.zsh                        |   4 +-
 lib/tmuxinator/assets/template.erb               |   9 +-
 lib/tmuxinator/cli.rb                            |  82 ++++++---
 lib/tmuxinator/project.rb                        |  10 +
 lib/tmuxinator/version.rb                        |   2 +-
 lib/tmuxinator/window.rb                         |   6 +-
 spec/factories/projects.rb                       |   8 +
 spec/fixtures/sample_literals_as_window_name.yml |  15 ++
 spec/lib/tmuxinator/cli_spec.rb                  | 223 ++++++++++++++++++++---
 spec/lib/tmuxinator/project_spec.rb              |  46 +++++
 spec/spec_helper.rb                              |   3 +-
 20 files changed, 471 insertions(+), 92 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 1adf0af..7191a2e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,10 +2,11 @@ language: ruby
 rvm:
   - "1.9.3"
   - "2.0.0"
-  - "2.1.6"
-  - "2.2.2"
+  - "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
@@ -16,6 +17,7 @@ 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
@@ -25,6 +27,4 @@ before_install:
   - ./configure && make && sudo make install
   - cd ..
   - tmux -V
-script:
-  - bundle exec rspec spec
-  - bundle exec rake rubocop
+script: bundle exec rake test
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8468ef2..4f2b7fe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,27 @@
+## 0.8.1
+### Bugfixes
+
+- Fixed broken shell completions
+
+## 0.8.0
+### New features
+
+- Add support for deleting multiple projects at once, using `mux delete <p1> <p2> ...`
+- 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
 
@@ -29,13 +53,13 @@
 - 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 
+- 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 
+- Add per window root option #283
+- Fix project path detection #274
 - Include completions in gemspec #270
 
 ## 0.6.9
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d45f14b..4f8cac9 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -3,7 +3,7 @@
 ## First
 
 * Check if the issue you're going to submit isn't already submitted in
-  the [Issues](https://github.com/aziz/tmuxinator/issues) page.
+  the [Issues](https://github.com/tmuxinator/tmuxinator/issues) page.
 
 ## Issues
 
@@ -26,7 +26,8 @@ should submit a Pull Request!
 * 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 assure nothine else was broken. We only take pull requests with passing tests.
+* 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:
 
diff --git a/Gemfile b/Gemfile
index 5afc8c0..6650106 100644
--- a/Gemfile
+++ b/Gemfile
@@ -5,9 +5,9 @@ gemspec
 
 gem "rake", "~> 10.4"
 gem "rspec", "~> 3.3"
-gem "simplecov", "~> 0.9"
+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.34", require: false
+gem "rubocop", "0.35.1", require: false
diff --git a/LICENSE b/LICENSE
index 335abf6..d55b18c 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2010-2014 Allen Bargi, Christopher Chow
+Copyright (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
diff --git a/README.md b/README.md
index 2fc5f66..96cc440 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ sure what that is type:
 echo $EDITOR
 ```
 
-For me that produces "vim" If you want to change your default editor simply
+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:
 
 ```
@@ -331,4 +331,4 @@ To contribute, please read the [contributing guide](https://github.com/tmuxinato
 
 ## Copyright
 
-Copyright (c) 2010-2014 Allen Bargi, Christopher Chow. See LICENSE for further details.
+Copyright (c) 2010-2016 Allen Bargi, Christopher Chow. See LICENSE for further details.
diff --git a/Rakefile b/Rakefile
index f3909fb..687f6e2 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,20 +1,8 @@
 require "bundler/gem_tasks"
 require "rubocop/rake_task"
+require "rspec/core/rake_task"
 
 RuboCop::RakeTask.new
+RSpec::Core::RakeTask.new
 
-namespace :hound do
-  BASE_CMD = "git diff --no-commit-id --name-only -r master | grep rb"
-
-  task :count do
-    n = %x{#{BASE_CMD} | wc -l}.chomp
-    puts "Cop'ing #{n} files"
-  end
-
-  task :check do
-    cmd = "#{BASE_CMD} | xargs rubocop"
-    system cmd
-  end
-end
-
-task :check => ["hound:count", "hound:check"]
+task :test => ["spec", "rubocop"]
diff --git a/code_of_conduct.md b/code_of_conduct.md
new file mode 100644
index 0000000..9499818
--- /dev/null
+++ b/code_of_conduct.md
@@ -0,0 +1,74 @@
+# 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 at 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/
diff --git a/completion/tmuxinator.bash b/completion/tmuxinator.bash
index 05ba7bb..476d1e2 100755
--- a/completion/tmuxinator.bash
+++ b/completion/tmuxinator.bash
@@ -8,7 +8,7 @@ _tmuxinator() {
     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
diff --git a/completion/tmuxinator.zsh b/completion/tmuxinator.zsh
index 4c76c94..e2ff4ed 100755
--- a/completion/tmuxinator.zsh
+++ b/completion/tmuxinator.zsh
@@ -1,5 +1,3 @@
-#compdef tmuxinator mux
-
 _tmuxinator() {
   local commands projects
   commands=(${(f)"$(tmuxinator commands zsh)"})
@@ -19,7 +17,7 @@ _tmuxinator() {
   return
 }
 
-_tmuxinator
+compdef _tmuxinator tmuxinator mux
 
 # Local Variables:
 # mode: Shell-Script
diff --git a/lib/tmuxinator/assets/template.erb b/lib/tmuxinator/assets/template.erb
index e5eb1ef..0907098 100644
--- a/lib/tmuxinator/assets/template.erb
+++ b/lib/tmuxinator/assets/template.erb
@@ -4,9 +4,9 @@
 unset RBENV_VERSION
 unset RBENV_DIR
 
-<%= tmux %> start-server\; has-session -t <%= name %> 2>/dev/null
+<%= tmux %> start-server;
 
-if [ "$?" -eq 1 ]; then
+<%- if !tmux_has_session? name -%>
   cd <%= root || "." %>
 
   # Run pre command.
@@ -60,15 +60,16 @@ if [ "$?" -eq 1 ]; then
         <% unless pane.last? %>
   <%= pane.tmux_split_command %>
         <% end %>
-  <%= window.tmux_layout_command %>
+  <%= window.tmux_tiled_layout_command %>
       <% end %>
 
+  <%= window.tmux_layout_command %>
   <%= window.tmux_select_first_pane %>
     <% end %>
   <% end %>
 
   <%= tmux %> select-window -t <%= startup_window %>
-fi
+<%- end -%>
 
 <%- if attach? -%>
   if [ -z "$TMUX" ]; then
diff --git a/lib/tmuxinator/cli.rb b/lib/tmuxinator/cli.rb
index 5b0b383..e94ed7d 100644
--- a/lib/tmuxinator/cli.rb
+++ b/lib/tmuxinator/cli.rb
@@ -17,6 +17,9 @@ module Tmuxinator
         Start a tmux session using a project's tmuxinator config,
         with an optional [ALIAS] for project reuse
       DESC
+      stop: <<-DESC,
+        Stop a tmux session using a project's tmuxinator config.
+      DESC
       local: "Start a tmux session using ./.tmuxinator.yml",
       debug: "Output the shell commands that are generated by tmuxinator",
       copy: <<-DESC,
@@ -44,15 +47,15 @@ module Tmuxinator
               COMMANDS.keys.join("\n")
             end
 
-      puts out
+      say out
     end
 
     desc "completions [arg1 arg2]", COMMANDS[:completions]
 
     def completions(arg)
-      if %w(start open copy delete).include?(arg)
+      if %w(start stop open copy delete).include?(arg)
         configs = Tmuxinator::Config.configs
-        puts configs
+        say configs.join("\n")
       end
     end
 
@@ -67,22 +70,32 @@ module Tmuxinator
                           desc: "Create local project file at ./.tmuxinator.yml"
 
     def new(name)
-      project_file = if options[:local]
-                       Tmuxinator::Config::LOCAL_DEFAULT
-                     else
-                       Tmuxinator::Config.default_project(name)
-                     end
-      unless Tmuxinator::Config.exists?(project_file)
+      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.exists?(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(project_file, "w") { |f| f.write(erb) }
+        File.open(path, "w") { |f| f.write(erb) }
+        path
       end
 
-      Kernel.system("$EDITOR #{project_file}") || doctor
-    end
-
-    no_commands do
       def create_project(project_options = {})
         attach_opt = project_options[:attach]
         attach = !attach_opt.nil? && attach_opt ? true : false
@@ -106,13 +119,17 @@ module Tmuxinator
       def render_project(project)
         if project.deprecations.any?
           project.deprecations.each { |deprecation| say deprecation, :red }
-          puts
+          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]
@@ -134,6 +151,17 @@ module Tmuxinator
       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
 
@@ -156,7 +184,7 @@ module Tmuxinator
         args: args
       }
       project = create_project(params)
-      puts project.render
+      say project.render
     end
 
     desc "copy [EXISTING] [NEW]", COMMANDS[:copy]
@@ -180,20 +208,22 @@ module Tmuxinator
       Kernel.system("$EDITOR #{new_config_path}")
     end
 
-    desc "delete [PROJECT]", COMMANDS[:delete]
+    desc "delete [PROJECT1] [PROJECT2] ...", COMMANDS[:delete]
     map "d" => :delete
     map "rm" => :delete
 
-    def delete(project)
-      if Tmuxinator::Config.exists?(project)
-        config = "#{Tmuxinator::Config.root}/#{project}.yml"
-
-        if yes?("Are you sure you want to delete #{project}?(y/n)", :red)
-          FileUtils.rm(config)
-          say "Deleted #{project}"
+    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
-      else
-        exit!("That file doesn't exist.")
       end
     end
 
diff --git a/lib/tmuxinator/project.rb b/lib/tmuxinator/project.rb
index 5cf68c5..124626b 100644
--- a/lib/tmuxinator/project.rb
+++ b/lib/tmuxinator/project.rb
@@ -147,6 +147,12 @@ module Tmuxinator
       yaml["tmux_command"] || "tmux"
     end
 
+    def tmux_has_session?(name)
+      sessions = `#{tmux_command} ls`
+
+      !!sessions.match("^#{name}:")
+    end
+
     def socket
       if socket_path
         " -S #{socket_path}"
@@ -242,6 +248,10 @@ module Tmuxinator
       "#{tmux} new-session -d -s #{name} #{window}"
     end
 
+    def tmux_kill_session_command
+      "#{tmux} kill-session -t #{name}"
+    end
+
     private
 
     def tmux_config
diff --git a/lib/tmuxinator/version.rb b/lib/tmuxinator/version.rb
index 863f7f7..319ab8d 100644
--- a/lib/tmuxinator/version.rb
+++ b/lib/tmuxinator/version.rb
@@ -1,3 +1,3 @@
 module Tmuxinator
-  VERSION = "0.7.0"
+  VERSION = "0.8.1"
 end
diff --git a/lib/tmuxinator/window.rb b/lib/tmuxinator/window.rb
index 0ab8e1b..c4ba159 100644
--- a/lib/tmuxinator/window.rb
+++ b/lib/tmuxinator/window.rb
@@ -6,7 +6,7 @@ module Tmuxinator
 
     def initialize(window_yaml, index, project)
       @name = if !window_yaml.keys.first.nil?
-                window_yaml.keys.first.shellescape
+                window_yaml.keys.first.to_s.shellescape
               end
       @root = nil
       @panes = []
@@ -95,6 +95,10 @@ module Tmuxinator
       "#{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_layout_command
       "#{project.tmux} select-layout -t #{tmux_window_target} #{layout}"
     end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 0f72352..4c0eec6 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -41,6 +41,14 @@ FactoryGirl.define do
     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") }
diff --git a/spec/fixtures/sample_literals_as_window_name.yml b/spec/fixtures/sample_literals_as_window_name.yml
new file mode 100644
index 0000000..07ff198
--- /dev/null
+++ b/spec/fixtures/sample_literals_as_window_name.yml
@@ -0,0 +1,15 @@
+# ~/.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
diff --git a/spec/lib/tmuxinator/cli_spec.rb b/spec/lib/tmuxinator/cli_spec.rb
index 8b7b9f1..353c46f 100644
--- a/spec/lib/tmuxinator/cli_spec.rb
+++ b/spec/lib/tmuxinator/cli_spec.rb
@@ -20,12 +20,13 @@ describe Tmuxinator::Cli do
   describe "#completions" do
     before do
       ARGV.replace(["completions", "start"])
-      allow(Tmuxinator::Config).to receive_messages(configs: ["test.yml"])
+      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")
+      expect(out).to include("test.yml\nfoo.yml")
     end
   end
 
@@ -41,6 +42,7 @@ describe Tmuxinator::Cli do
                     new
                     open
                     start
+                    stop
                     local
                     debug
                     copy
@@ -98,6 +100,26 @@ describe Tmuxinator::Cli do
     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
@@ -149,6 +171,41 @@ describe Tmuxinator::Cli do
     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.exists?(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" }
@@ -164,7 +221,7 @@ describe Tmuxinator::Cli do
 
       context "existing project doesn't exist" do
         before do
-          expect(Tmuxinator::Config).to receive_messages(exists?: false)
+          expect(File).to receive_messages(exists?: false)
         end
 
         it "creates a new tmuxinator project file" do
@@ -174,14 +231,15 @@ describe Tmuxinator::Cli do
       end
 
       context "files exists" do
-        let(:command) { "#{ENV['HOME']}\/\.tmuxinator\/#{name}\.yml" }
+        let(:root_path) { "#{ENV['HOME']}\/\.tmuxinator\/#{name}\.yml" }
 
         before do
-          expect(Tmuxinator::Config).to receive_messages(exists?: true)
+          allow(File).to receive(:exists?).with(anything).and_return(false)
+          expect(File).to receive(:exists?).with(root_path).and_return(true)
         end
 
         it "just opens the file" do
-          expect(Kernel).to receive(:system).with(%r{#{command}})
+          expect(Kernel).to receive(:system).with(%r{#{root_path}})
           capture_io { cli.start }
         end
       end
@@ -194,7 +252,7 @@ describe Tmuxinator::Cli do
 
       context "existing project doesn't exist" do
         before do
-          expect(Tmuxinator::Config).to receive(:exists?).at_least(:once) do
+          allow(File).to receive(:exists?).at_least(:once) do
             false
           end
         end
@@ -208,7 +266,7 @@ describe Tmuxinator::Cli do
       context "files exists" do
         let(:path) { Tmuxinator::Config::LOCAL_DEFAULT }
         before do
-          expect(Tmuxinator::Config).to receive(:exists?).with(path) { true }
+          expect(File).to receive(:exists?).with(path) { true }
         end
 
         it "just opens the file" do
@@ -288,30 +346,88 @@ describe Tmuxinator::Cli do
   end
 
   describe "#delete" do
-    before do
-      ARGV.replace(["delete", "foo"])
-      allow(Thor::LineEditor).to receive_messages(readline: "y")
-    end
-
-    context "project exists" do
+    context "with a single argument" do
       before do
-        allow(Tmuxinator::Config).to receive(:exists?) { true }
+        ARGV.replace(["delete", "foo"])
+        allow(Thor::LineEditor).to receive_messages(readline: "y")
       end
 
-      it "deletes the project" do
-        expect(FileUtils).to receive(:rm)
-        capture_io { cli.start }
+      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 "project doesn't exist" do
+    context "with multiple arguments" do
       before do
-        allow(Tmuxinator::Config).to receive(:exists?) { false }
+        ARGV.replace(["delete", "foo", "bar"])
         allow(Thor::LineEditor).to receive_messages(readline: "y")
       end
 
-      it "exits with error message" do
-        expect { capture_io { cli.start } }.to raise_error SystemExit
+      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
@@ -368,6 +484,69 @@ describe Tmuxinator::Cli do
     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.exists?(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.exists?(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
diff --git a/spec/lib/tmuxinator/project_spec.rb b/spec/lib/tmuxinator/project_spec.rb
index b8f14fa..8ef5f71 100644
--- a/spec/lib/tmuxinator/project_spec.rb
+++ b/spec/lib/tmuxinator/project_spec.rb
@@ -8,6 +8,9 @@ describe Tmuxinator::Project do
   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
@@ -53,6 +56,28 @@ describe Tmuxinator::Project do
     end
   end
 
+  describe "#tmux_has_session?" do
+    before do
+      cmd = "#{project.tmux_command} ls"
+      resp = ""\
+        "foo: 1 window (created Sun May 25 10:12:00 1986) [50x50] (detached)\n"\
+        "bar: 1 window (created Sat Sept 01 00:00:00 1990) [50x50] (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
+
   describe "#windows" do
     context "without deprecations" do
       it "gets the list of windows" do
@@ -118,6 +143,15 @@ describe Tmuxinator::Project do
         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
@@ -448,6 +482,18 @@ describe Tmuxinator::Project do
     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) { {} }
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 2a4b73f..9dbfea1 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -2,10 +2,11 @@ require "coveralls"
 require "simplecov"
 require "pry"
 
-SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
+formatters = [
   SimpleCov::Formatter::HTMLFormatter,
   Coveralls::SimpleCov::Formatter
 ]
+SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(formatters)
 SimpleCov.start do
   add_filter "vendor/cache"
 end

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/tmuxinator.git



More information about the Pkg-ruby-extras-commits mailing list