feat: Add support for tmuxinator append
All checks were successful
Integration Tests / test (3.1.6, 1.5) (push) Successful in 1m44s
Integration Tests / test (3.1.6, 1.6) (push) Successful in 56s
Integration Tests / test (3.1.6, 1.7) (push) Successful in 59s
Integration Tests / test (3.1.6, 1.9) (push) Successful in 1m9s
Integration Tests / test (3.1.6, 2.0) (push) Successful in 1m12s
Integration Tests / test (3.1.6, 1.8) (push) Successful in 1m7s
Integration Tests / test (3.1.6, 2.1) (push) Successful in 1m9s
Integration Tests / test (3.1.6, 2.2) (push) Successful in 1m10s
Integration Tests / test (3.1.6, 2.3) (push) Successful in 1m9s
Integration Tests / test (3.1.6, 2.4) (push) Successful in 1m9s
Integration Tests / test (3.1.6, 2.5) (push) Successful in 1m10s
Integration Tests / test (3.1.6, 2.6) (push) Successful in 1m12s
Integration Tests / test (3.1.6, 2.7) (push) Successful in 1m13s
Integration Tests / test (3.1.6, 2.8) (push) Successful in 1m13s
Integration Tests / test (3.1.6, 2.9) (push) Successful in 1m13s
Integration Tests / test (3.1.6, 2.9a) (push) Successful in 1m15s
Integration Tests / test (3.1.6, 3.0) (push) Successful in 1m14s
Integration Tests / test (3.1.6, 3.0a) (push) Successful in 1m14s
Integration Tests / test (3.1.6, 3.1) (push) Successful in 1m18s
Integration Tests / test (3.1.6, 3.1a) (push) Successful in 1m20s
Integration Tests / test (3.1.6, 3.1b) (push) Successful in 1m14s
Integration Tests / test (3.1.6, 3.1c) (push) Successful in 1m15s
Integration Tests / test (3.1.6, 3.2) (push) Successful in 1m23s
Integration Tests / test (3.1.6, 3.2a) (push) Successful in 1m22s
Integration Tests / test (3.1.6, 3.3) (push) Successful in 1m24s
Integration Tests / test (3.1.6, 3.3a) (push) Successful in 1m24s
Integration Tests / test (3.1.6, 3.4) (push) Successful in 1m24s
Integration Tests / test (3.1.6, 3.5) (push) Successful in 1m28s
Integration Tests / test (3.1.6, 3.5a) (push) Successful in 1m24s
Integration Tests / test (3.2.5, 1.5) (push) Successful in 1m18s
Integration Tests / test (3.2.5, 1.8) (push) Successful in 1m7s
Integration Tests / test (3.2.5, 1.9) (push) Successful in 1m11s
Integration Tests / test (3.2.5, 2.3) (push) Successful in 1m10s
Integration Tests / test (3.2.5, 2.6) (push) Successful in 1m15s
Integration Tests / test (3.2.5, 2.8) (push) Successful in 1m32s
Integration Tests / test (3.2.5, 3.0a) (push) Successful in 1m39s
Integration Tests / test (3.2.5, 3.1b) (push) Successful in 1m35s
Integration Tests / test (3.2.5, 3.1c) (push) Successful in 1m34s
Integration Tests / test (3.2.5, 3.2a) (push) Successful in 1m45s
Integration Tests / test (3.2.5, 1.6) (push) Successful in 1m1s
Integration Tests / test (3.2.5, 1.7) (push) Successful in 1m1s
Integration Tests / test (3.2.5, 2.0) (push) Successful in 1m12s
Integration Tests / test (3.2.5, 2.1) (push) Successful in 1m8s
Integration Tests / test (3.2.5, 2.2) (push) Successful in 1m7s
Integration Tests / test (3.2.5, 2.4) (push) Successful in 1m12s
Integration Tests / test (3.2.5, 2.5) (push) Successful in 1m11s
Integration Tests / test (3.2.5, 2.7) (push) Successful in 1m30s
Integration Tests / test (3.2.5, 2.9) (push) Successful in 1m31s
Integration Tests / test (3.2.5, 2.9a) (push) Successful in 1m37s
Integration Tests / test (3.2.5, 3.0) (push) Successful in 1m35s
Integration Tests / test (3.2.5, 3.1) (push) Successful in 1m38s
Integration Tests / test (3.2.5, 3.1a) (push) Successful in 1m28s
Integration Tests / test (3.2.5, 3.2) (push) Successful in 1m46s
Integration Tests / test (3.2.5, 3.3) (push) Successful in 1m42s
Integration Tests / test (3.2.5, 3.3a) (push) Successful in 1m50s
Integration Tests / test (3.2.5, 3.4) (push) Successful in 1m46s
Integration Tests / test (3.2.5, 3.5) (push) Successful in 1m47s
Integration Tests / test (3.2.5, 3.5a) (push) Successful in 1m48s
Integration Tests / test (3.3.5, 1.5) (push) Successful in 1m44s
Integration Tests / test (3.3.5, 1.6) (push) Successful in 1m16s
Integration Tests / test (3.3.5, 1.7) (push) Successful in 1m22s
Integration Tests / test (3.3.5, 1.8) (push) Successful in 1m33s
Integration Tests / test (3.3.5, 1.9) (push) Successful in 1m25s
Integration Tests / test (3.3.5, 2.0) (push) Successful in 1m43s
Integration Tests / test (3.3.5, 2.1) (push) Successful in 1m30s
Integration Tests / test (3.3.5, 2.2) (push) Successful in 1m33s
Integration Tests / test (3.3.5, 2.3) (push) Successful in 1m35s
Integration Tests / test (3.3.5, 2.4) (push) Successful in 1m34s
Integration Tests / test (3.3.5, 2.5) (push) Successful in 1m35s
Integration Tests / test (3.3.5, 2.6) (push) Successful in 1m34s
Integration Tests / test (3.3.5, 2.7) (push) Successful in 1m37s
Integration Tests / test (3.3.5, 2.8) (push) Successful in 1m34s
Integration Tests / test (3.3.5, 2.9) (push) Successful in 1m44s
Integration Tests / test (3.3.5, 2.9a) (push) Successful in 1m36s
Integration Tests / test (3.3.5, 3.0) (push) Successful in 1m37s
Integration Tests / test (3.3.5, 3.0a) (push) Successful in 1m36s
Integration Tests / test (3.3.5, 3.1) (push) Successful in 1m36s
Integration Tests / test (3.3.5, 3.1a) (push) Successful in 1m32s
Integration Tests / test (3.3.5, 3.1b) (push) Successful in 1m40s
Integration Tests / test (3.3.5, 3.1c) (push) Successful in 1m35s
Integration Tests / test (3.3.5, 3.2) (push) Successful in 1m40s
Integration Tests / test (3.3.5, 3.2a) (push) Successful in 1m43s
Integration Tests / test (3.3.5, 3.3) (push) Successful in 1m44s
Integration Tests / test (3.3.5, 3.3a) (push) Successful in 1m45s
Integration Tests / test (3.3.5, 3.4) (push) Successful in 1m50s
Integration Tests / test (3.3.5, 3.5) (push) Successful in 1m42s
Integration Tests / test (3.3.5, 3.5a) (push) Successful in 1m48s

Adds support for tmuxinator append

Adds ability to specify default loading behavior (start or append)

- Use start when not possible to append

nits

nits and improvements

refactor Cli::bootstrap (#1)

Adds reference to the new command

use say

cli: Adds tests for bootstraping with option set to append

adds tests for project window index

refactor to use start --append instead of append. improve config loading

reduce complexity of the start method

reduce complexity in cli.rb

void(commit)

extract get params

Update lib/tmuxinator/config.rb

Update lib/tmuxinator/project.rb

Update lib/tmuxinator/cli.rb

Co-authored-by: Noah Frederick <code@noahfrederick.com>
Co-authored-by: Andrew Kofink <ajkofink@gmail.com>
Signed-off-by: Andrew Kofink <ajkofink@gmail.com>
This commit is contained in:
Florent Vilmart
2018-09-16 14:37:08 -04:00
committed by Andrew Kofink
parent 11de7f6102
commit 5ef509d783
8 changed files with 145 additions and 40 deletions

View File

@@ -1,4 +1,6 @@
## Unreleased
### Features
- Add support for tmuxinator start --append
## 3.3.3
### Features

View File

@@ -398,6 +398,11 @@ Shows tmuxinator's version.
tmuxinator version
```
Append a project's windows to the current session (instead of creating a new session)
```
tmuxinator start [project] --append
```
## Project Configuration Location
Using environment variables, it's possible to define which directory

View File

@@ -1,17 +1,19 @@
#!<%= ENV["SHELL"] || "/bin/bash" %>
# Clear rbenv variables before starting tmux
unset RBENV_VERSION
unset RBENV_DIR
<%- if !append? -%>
# Clear rbenv variables before starting tmux
unset RBENV_VERSION
unset RBENV_DIR
<%= tmux %> start-server;
<%= tmux %> start-server;
<%- end -%>
cd <%= root || "." %>
# Run on_project_start command.
<%= hook_on_project_start %>
<%- if !tmux_has_session? name -%>
<%- if append? || !tmux_has_session?(name) -%>
# Run pre command.
<%= pre %>
@@ -98,7 +100,7 @@ cd <%= root || "." %>
<%= hook_on_project_restart %>
<%- end -%>
<%- if attach? -%>
<%- if attach? && !append? -%>
if [ -z "$TMUX" ]; then
<%= tmux %> -u attach-session -t <%= name %>
else

View File

@@ -190,7 +190,8 @@ module Tmuxinator
force_attach: attach,
force_detach: detach,
name: project_options[:name],
project_config: project_options[:project_config]
project_config: project_options[:project_config],
append: project_options[:append]
}
begin
@@ -227,6 +228,24 @@ module Tmuxinator
def kill_project(project)
Kernel.exec(project.kill)
end
def start_params(name = nil, *args)
# project-config takes precedence over a named project in the case that
# both are provided.
if options["project-config"]
args.unshift name if name
name = nil
end
{
args: args,
attach: options[:attach],
custom_name: options[:name],
name: name,
project_config: options["project-config"],
append: options["append"],
}
end
end
desc "start [PROJECT] [ARGS]", COMMANDS[:start]
@@ -240,22 +259,11 @@ module Tmuxinator
desc: "Path to project config file"
method_option "suppress-tmux-version-warning",
desc: "Don't show a warning for unsupported tmux versions"
method_option :append, type: :boolean,
desc: "Appends the project windows and panes in " \
"the current session"
def start(name = nil, *args)
# project-config takes precedence over a named project in the case that
# both are provided.
if options["project-config"]
args.unshift name if name
name = nil
end
params = {
args: args,
attach: options[:attach],
custom_name: options[:name],
name: name,
project_config: options["project-config"]
}
params = start_params(name, *args)
show_version_warning if version_warning?(
options["suppress-tmux-version-warning"]
@@ -312,24 +320,15 @@ module Tmuxinator
desc: "Give the session a different name"
method_option "project-config", aliases: "-p",
desc: "Path to project config file"
method_option :append, type: :boolean,
desc: "Appends the project windows and panes in " \
"the current session"
def debug(name = nil, *args)
# project-config takes precedence over a named project in the case that
# both are provided.
if options["project-config"]
args.unshift name if name
name = nil
end
params = {
args: args,
attach: options[:attach],
custom_name: options[:name],
name: name,
project_config: options["project-config"]
}
params = start_params(name, *args)
project = create_project(params)
say project.render
end

View File

@@ -87,13 +87,23 @@ module Tmuxinator
@force_attach = options[:force_attach]
@force_detach = options[:force_detach]
@append = options[:append]
raise "Cannot force_attach and force_detach at the same time" \
if @force_attach && @force_detach
validate_options
extend Tmuxinator::WemuxSupport if wemux?
end
def validate_options
if @force_attach && @force_detach
raise "Cannot force_attach and force_detach at the same time"
end
if append? && !tmux_has_session?(name)
raise "Cannot append to a session that does not exist"
end
end
def render
self.class.render_template(Tmuxinator::Config.template, binding)
end
@@ -120,11 +130,25 @@ module Tmuxinator
blank?(root) ? nil : File.expand_path(root).shellescape
end
def current_session_name
`[[ -n "${TMUX+set}" ]] && tmux display-message -p "#S"`.strip
end
def name
name = custom_name || yaml["project_name"] || yaml["name"]
name =
if append?
current_session_name
else
custom_name || yaml["project_name"] || yaml["name"]
end
blank?(name) ? nil : name.to_s.shellescape
end
def append?
@append
end
def pre
pre_config = yaml["pre"]
parsed_parameters(pre_config)
@@ -167,6 +191,8 @@ module Tmuxinator
end
def tmux_has_session?(name)
return false unless 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.
@@ -208,7 +234,13 @@ module Tmuxinator
end
end
def last_window_index
`tmux list-windows -F '#I'`.split.last.to_i
end
def base_index
return last_window_index + 1 if append?
get_base_index.to_i
end
@@ -241,7 +273,7 @@ module Tmuxinator
end
def window(index)
"#{name}:#{index}"
append? ? ":#{index}" : "#{name}:#{index}"
end
def send_pane_command(cmd, window_index, _pane_index)
@@ -329,6 +361,8 @@ module Tmuxinator
end
def tmux_new_session_command
return if append?
window = windows.first.tmux_window_name_option
"#{tmux} new-session -d -s #{name} #{window}"
end

View File

@@ -115,4 +115,12 @@ FactoryBot.define do
initialize_with { Tmuxinator::Project.load(file) }
end
factory :project_with_append, class: Tmuxinator::Project do
transient do
file { "spec/fixtures/sample.yml" }
end
initialize_with { Tmuxinator::Project.load(file, append: true) }
end
end

View File

@@ -104,6 +104,17 @@ describe Tmuxinator::Cli do
expect(instance).to receive(:start).with(*args)
subject
end
context "and the append option is passed" do
let(:args) { ["sample", "--append"] }
it "should call #start" do
instance = instance_double(cli)
expect(cli).to receive(:new).and_return(instance)
expect(instance).to receive(:start).with("sample", "--append")
subject
end
end
end
context "a thor command" do

View File

@@ -37,6 +37,10 @@ describe Tmuxinator::Project do
FactoryBot.build(:project_with_alias)
end
let(:project_with_append) do
FactoryBot.build(:project_with_append)
end
it "should include Hooks" do
expect(project).to be_kind_of(Tmuxinator::Hooks::Project)
end
@@ -46,6 +50,21 @@ describe Tmuxinator::Project do
it "creates an instance" do
expect(project).to be_a(Tmuxinator::Project)
end
it "validates append outside a current session" do
Tmuxinator::Project.any_instance.stub(tmux_has_session?: false)
expect { project_with_append }.to(
raise_error(
RuntimeError,
"Cannot append to a session that does not exist"
)
)
end
it "validates append within a current session" do
Tmuxinator::Project.any_instance.stub(tmux_has_session?: true)
expect { project_with_append }.to_not raise_error
end
end
end
@@ -368,6 +387,17 @@ describe Tmuxinator::Project do
expect(project.base_index).to eq 0
end
end
context "with append set" do
before do
Tmuxinator::Project.any_instance.stub(tmux_has_session?: true)
project_with_append.stub(last_window_index: 3)
end
it "defaults to the next window index" do
expect(project_with_append.base_index).to eq 4
end
end
end
describe "#startup_window" do
@@ -410,6 +440,13 @@ describe Tmuxinator::Project do
it "gets the window and index for tmux" do
expect(project.window(1)).to eq "sample:1"
end
context "with append set" do
it "excludes the session name" do
Tmuxinator::Project.any_instance.stub(tmux_has_session?: true)
expect(project_with_append.window(1)).to eq ":1"
end
end
end
describe "#name?" do
@@ -576,6 +613,13 @@ describe Tmuxinator::Project do
expect(project.tmux_new_session_command).to eq command
end
end
context "with append set" do
it "returns nothing" do
Tmuxinator::Project.any_instance.stub(tmux_has_session?: true)
expect(project_with_append.tmux_new_session_command).to be_nil
end
end
end
describe "tmux_kill_session_command" do