[DRE-commits] [tmuxinator] 01/02: Imported Upstream version 0.7.0
Youhei SASAKI
uwabami-guest at moszumanska.debian.org
Sun Dec 6 12:01:42 UTC 2015
This is an automated email from the git hooks/post-receive script.
uwabami-guest pushed a commit to branch master
in repository tmuxinator.
commit d1f90daf8720414aebd1127ae234327e6f794043
Author: Youhei SASAKI <uwabami at gfd-dennou.org>
Date: Sun Dec 6 20:55:57 2015 +0900
Imported Upstream version 0.7.0
---
.rubocop.yml | 1058 +++++++++++++++++++++++++++++
.travis.yml | 4 +-
CHANGELOG.md | 19 +
Gemfile | 15 +-
README.md | 54 +-
Rakefile | 19 +
bin/tmuxinator | 15 +-
lib/tmuxinator/assets/template.erb | 12 +-
lib/tmuxinator/assets/wemux_template.erb | 2 +-
lib/tmuxinator/cli.rb | 144 +++-
lib/tmuxinator/config.rb | 82 ++-
lib/tmuxinator/pane.rb | 26 +-
lib/tmuxinator/project.rb | 123 +++-
lib/tmuxinator/version.rb | 2 +-
lib/tmuxinator/wemux_support.rb | 8 +-
lib/tmuxinator/window.rb | 20 +-
spec/factories/projects.rb | 66 +-
spec/fixtures/{sample.yml => detach.yml} | 1 +
spec/fixtures/nameless_window.yml | 5 +
spec/fixtures/nowindows.yml | 3 +
spec/fixtures/sample.yml | 1 +
spec/fixtures/sample_number_as_name.yml | 5 +
spec/lib/tmuxinator/cli_spec.rb | 221 +++++-
spec/lib/tmuxinator/config_spec.rb | 113 ++-
spec/lib/tmuxinator/project_spec.rb | 200 +++++-
spec/lib/tmuxinator/util_spec.rb | 1 -
spec/lib/tmuxinator/wemux_support_spec.rb | 47 ++
spec/lib/tmuxinator/window_spec.rb | 103 ++-
spec/spec_helper.rb | 31 +-
29 files changed, 2139 insertions(+), 261 deletions(-)
diff --git a/.rubocop.yml b/.rubocop.yml
new file mode 100644
index 0000000..746d9ef
--- /dev/null
+++ b/.rubocop.yml
@@ -0,0 +1,1058 @@
+AllCops:
+ 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
+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
diff --git a/.travis.yml b/.travis.yml
index 855cccd..1adf0af 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -25,4 +25,6 @@ before_install:
- ./configure && make && sudo make install
- cd ..
- tmux -V
-script: bundle exec rspec spec
+script:
+ - bundle exec rspec spec
+ - bundle exec rake rubocop
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c2eea0c..8468ef2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,22 @@
+## 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
diff --git a/Gemfile b/Gemfile
index 6700e4b..5afc8c0 100644
--- a/Gemfile
+++ b/Gemfile
@@ -3,10 +3,11 @@ source "https://rubygems.org"
# Specify your gem's dependencies in tmuxinator.gemspec
gemspec
-gem 'rake', '~> 10.4'
-gem 'rspec', '~> 3.1'
-gem 'simplecov', '~> 0.9'
-gem 'coveralls', '~> 0.7'
-gem 'awesome_print', '~> 1.2'
-gem 'pry', '~> 0.10'
-gem 'factory_girl', '~> 4.4'
+gem "rake", "~> 10.4"
+gem "rspec", "~> 3.3"
+gem "simplecov", "~> 0.9"
+gem "coveralls", "~> 0.7"
+gem "awesome_print", "~> 1.2"
+gem "pry", "~> 0.10"
+gem "factory_girl", "~> 4.5"
+gem "rubocop", "~> 0.34", require: false
diff --git a/README.md b/README.md
index f9a0090..2fc5f66 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# 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/tmuxina [...]
+[![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/tmuxina [...]
Create and manage tmux sessions easily.
@@ -123,7 +123,7 @@ 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
```
@@ -132,7 +132,7 @@ windows:
An optional root option can be specified per window:
-```
+```yaml
name: test
root: ~/projects/company
@@ -170,7 +170,7 @@ or [specify your own](http://stackoverflow.com/a/9976282/183537).
To use tmuxinator with rbenv, RVM, NVM etc, use the `pre_window` option.
-```
+```yaml
pre_window: rbenv shell 2.0.0-p247
```
@@ -178,15 +178,15 @@ These command(s) will run before any subsequent commands in all panes and window
## Custom attachment and post commands
-You can set tmuxiniator to skip auto-attaching to the session by using the `attach` option.
+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
```
@@ -198,7 +198,7 @@ SSH for example.
To support this both the window and pane options can take an array as an argument:
-```
+```yaml
name: sample
root: ~/
@@ -217,12 +217,44 @@ windows:
## ERB
-Project files support ERB for reusability across environments. Eg:
+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.
@@ -235,6 +267,8 @@ If you use the optional `[alias]` argument, it will start a new tmux session
with the custom alias 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
A shorthand alias for tmuxinator can also be used.
diff --git a/Rakefile b/Rakefile
index 2995527..f3909fb 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1 +1,20 @@
require "bundler/gem_tasks"
+require "rubocop/rake_task"
+
+RuboCop::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"]
diff --git a/bin/tmuxinator b/bin/tmuxinator
index 3a7dea8..d83b5ae 100755
--- a/bin/tmuxinator
+++ b/bin/tmuxinator
@@ -4,16 +4,13 @@ $: << File.expand_path("../../lib/", __FILE__)
require "thor"
require "tmuxinator"
-if ARGV.length == 1
- name = ARGV[0]
+name = ARGV[0] || nil
- if Tmuxinator::Cli::COMMANDS.keys.include?(name.to_sym)
- Tmuxinator::Cli.start
- elsif Tmuxinator::Config.exists?(name)
- Tmuxinator::Cli.new.start(name)
- else
- Tmuxinator::Cli.start
- end
+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
diff --git a/lib/tmuxinator/assets/template.erb b/lib/tmuxinator/assets/template.erb
index fb60651..e5eb1ef 100644
--- a/lib/tmuxinator/assets/template.erb
+++ b/lib/tmuxinator/assets/template.erb
@@ -14,7 +14,7 @@ if [ "$?" -eq 1 ]; then
# Create the session and the first window. Manually switch to root
# directory if required to support tmux < 1.9
- TMUX= <%= tmux %> new-session -d -s <%= name %> -n <%= windows.first.name %>
+ TMUX= <%= tmux_new_session_command %>
<% if windows.first.root? %>
<%= windows.first.tmux_window_command_prefix %> <%= "cd #{windows.first.root}".shellescape %> C-m
<% end %>
@@ -71,11 +71,11 @@ if [ "$?" -eq 1 ]; then
fi
<%- if attach? -%>
-if [ -z "$TMUX" ]; then
- <%= tmux %> -u attach-session -t <%= name %>
-else
- <%= tmux %> -u switch-client -t <%= name %>
-fi
+ if [ -z "$TMUX" ]; then
+ <%= tmux %> -u attach-session -t <%= name %>
+ else
+ <%= tmux %> -u switch-client -t <%= name %>
+ fi
<%- end -%>
<%= post %>
diff --git a/lib/tmuxinator/assets/wemux_template.erb b/lib/tmuxinator/assets/wemux_template.erb
index 8fb9947..f60335f 100644
--- a/lib/tmuxinator/assets/wemux_template.erb
+++ b/lib/tmuxinator/assets/wemux_template.erb
@@ -8,7 +8,7 @@ if [ "$?" -eq 127 ]; then
<%= pre %>
# Create the session and the first window.
- TMUX= <%= tmux %> new-session -d -s <%= name %> -n <%= windows.first.name %>
+ TMUX= <%= tmux_new_session_command %>
# Set the default path.
<%- if root? -%>
diff --git a/lib/tmuxinator/cli.rb b/lib/tmuxinator/cli.rb
index 842ecf2..5b0b383 100644
--- a/lib/tmuxinator/cli.rb
+++ b/lib/tmuxinator/cli.rb
@@ -1,5 +1,11 @@
module 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 = {
@@ -7,9 +13,16 @@ module Tmuxinator
completions: "Used for shell completion",
new: "Create a new project file and open it in your editor",
open: "Alias of new",
- start: "Start a tmux session using a project's tmuxinator config, with an optional [ALIAS] for project reuse",
+ start: <<-DESC,
+ Start a tmux session using a project's tmuxinator config,
+ with an optional [ALIAS] for project reuse
+ DESC
+ local: "Start a tmux session using ./.tmuxinator.yml",
debug: "Output the shell commands that are generated by tmuxinator",
- copy: "Copy an existing project to a new project and open it in your editor",
+ copy: <<-DESC,
+ Copy an existing project to a new project and open it in
+ your editor
+ DESC
delete: "Deletes given project",
implode: "Deletes all tmuxinator projects",
version: "Display installed tmuxinator version",
@@ -17,18 +30,19 @@ module Tmuxinator
list: "Lists all tmuxinator projects"
}
- package_name "tmuxinator" unless Gem::Version.create(Thor::VERSION) < Gem::Version.create("0.18")
+ 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
+ COMMANDS.map do |command, desc|
+ "#{command}:#{desc}"
+ end.join("\n")
+ else
+ COMMANDS.keys.join("\n")
+ end
puts out
end
@@ -48,39 +62,100 @@ module Tmuxinator
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)
- config = Tmuxinator::Config.project(name)
-
- unless Tmuxinator::Config.exists?(name)
- template = Tmuxinator::Config.default? ? Tmuxinator::Config.default : Tmuxinator::Config.sample
- erb = Erubis::Eruby.new(File.read(template)).result(binding)
- File.open(config, "w") { |f| f.write(erb) }
+ project_file = if options[:local]
+ Tmuxinator::Config::LOCAL_DEFAULT
+ else
+ Tmuxinator::Config.default_project(name)
+ end
+ unless Tmuxinator::Config.exists?(project_file)
+ 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) }
end
- Kernel.system("$EDITOR #{config}") || doctor
+ Kernel.system("$EDITOR #{project_file}") || doctor
end
- desc "start [PROJECT] [SESSION_NAME]", COMMANDS[:start]
- map "s" => :start
+ no_commands do
+ 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 start(name, custom_name = nil)
- project = Tmuxinator::Config.validate(name, custom_name )
+ def render_project(project)
+ if project.deprecations.any?
+ project.deprecations.each { |deprecation| say deprecation, :red }
+ puts
+ print "Press ENTER to continue."
+ STDIN.getc
+ end
- if project.deprecations.any?
- project.deprecations.each { |deprecation| say deprecation, :red }
- puts
- print "Press ENTER to continue."
- STDIN.getc
+ Kernel.exec(project.render)
end
+ end
- Kernel.exec(project.render)
+ 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 "debug [PROJECT]", COMMANDS[:debug]
+ desc "local", COMMANDS[:local]
+ map "." => :local
+
+ def local
+ render_project(create_project(attach: options[:attach]))
+ end
- def debug(name, custom_name = nil)
- project = Tmuxinator::Config.validate(name, custom_name )
+ 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)
puts project.render
end
@@ -92,9 +167,12 @@ module Tmuxinator
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)
+ exit!("Project #{existing} doesn't exist!") \
+ unless Tmuxinator::Config.exists?(existing)
- if !Tmuxinator::Config.exists?(new) or yes?("#{new} already exists, would you like to overwrite it?", :red)
+ 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
@@ -108,7 +186,7 @@ module Tmuxinator
def delete(project)
if Tmuxinator::Config.exists?(project)
- config = "#{Tmuxinator::Config.root}/#{project}.yml"
+ config = "#{Tmuxinator::Config.root}/#{project}.yml"
if yes?("Are you sure you want to delete #{project}?(y/n)", :red)
FileUtils.rm(config)
@@ -156,7 +234,7 @@ module Tmuxinator
yes_no Tmuxinator::Config.editor?
say "Checking if $SHELL is set ==> "
- yes_no Tmuxinator::Config.shell?
+ yes_no Tmuxinator::Config.shell?
end
end
end
diff --git a/lib/tmuxinator/config.rb b/lib/tmuxinator/config.rb
index 4ba12ee..5637269 100644
--- a/lib/tmuxinator/config.rb
+++ b/lib/tmuxinator/config.rb
@@ -1,17 +1,21 @@
module Tmuxinator
class Config
+ LOCAL_DEFAULT = "./.tmuxinator.yml".freeze
+ NO_LOCAL_FILE_MSG = "Project file at ./.tmuxinator.yml doesn't exist."
+
class << self
def root
- Dir.mkdir("#{ENV["HOME"]}/.tmuxinator") unless File.directory?(File.expand_path("~/.tmuxinator"))
- "#{ENV["HOME"]}/.tmuxinator"
+ root_dir = File.expand_path("~/.tmuxinator")
+ Dir.mkdir("#{ENV['HOME']}/.tmuxinator") unless File.directory?(root_dir)
+ "#{ENV['HOME']}/.tmuxinator"
end
def sample
- "#{File.dirname(__FILE__)}/assets/sample.yml"
+ asset_path "sample.yml"
end
def default
- "#{ENV["HOME"]}/.tmuxinator/default.yml"
+ "#{ENV['HOME']}/.tmuxinator/default.yml"
end
def default?
@@ -42,18 +46,33 @@ module Tmuxinator
File.exists?(project(name))
end
- def project(name)
+ def project_in_root(name)
projects = Dir.glob("#{root}/**/*.yml")
- project_file = projects.detect { |project| File.basename(project, ".yml") == name }
- project_file || "#{root}/#{name}.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.exists?(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
- "#{File.dirname(__FILE__)}/assets/template.erb"
+ asset_path "template.erb"
end
def wemux_template
- "#{File.dirname(__FILE__)}/assets/wemux_template.erb"
+ asset_path "wemux_template.erb"
end
def configs
@@ -62,34 +81,27 @@ module Tmuxinator
end
end
- def validate(name, custom_name = nil)
- unless Tmuxinator::Config.exists?(name)
- puts "Project #{name} doesn't exist."
- exit!
- end
-
- config_path = Tmuxinator::Config.project(name)
-
- yaml = begin
- YAML.load(Erubis::Eruby.new(File.read(config_path)).result(binding))
- rescue SyntaxError, StandardError
- puts "Failed to parse config file. Please check your formatting."
- exit!
- end
-
- project = Tmuxinator::Project.new(yaml, custom_name)
-
- unless project.windows?
- puts "Your project file should include some windows."
- exit!
- 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
- unless project.name?
- puts "Your project file didn't specify a 'project_name'"
- exit!
- end
+ private
- project
+ def asset_path(asset)
+ "#{File.dirname(__FILE__)}/assets/#{asset}"
end
end
end
diff --git a/lib/tmuxinator/pane.rb b/lib/tmuxinator/pane.rb
index 00a9a51..82ba096 100644
--- a/lib/tmuxinator/pane.rb
+++ b/lib/tmuxinator/pane.rb
@@ -10,27 +10,43 @@ module Tmuxinator
end
def tmux_window_and_pane_target
- "#{project.name}:#{tab.index + project.base_index}.#{index + project.base_index}"
+ x = tab.index + project.base_index
+ y = index + project.base_index
+ "#{project.name}:#{x}.#{y}"
end
def tmux_pre_command
return unless tab.pre
- "#{project.tmux} send-keys -t #{tmux_window_and_pane_target} #{tab.pre.shellescape} C-m"
+ 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
- "#{project.tmux} send-keys -t #{tmux_window_and_pane_target} #{project.pre_window.shellescape} C-m"
+ 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)
- command ? "#{project.tmux} send-keys -t #{project.name}:#{tab.index + project.base_index}.#{index + tab.project.base_index} #{command.shellescape} C-m" : ""
+ 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 = tab.root? ? "#{Tmuxinator::Config.default_path_option} #{tab.root}" : nil
+ path = if tab.root?
+ "#{Tmuxinator::Config.default_path_option} #{tab.root}"
+ end
"#{project.tmux} splitw #{path} -t #{tab.tmux_window_target}"
end
diff --git a/lib/tmuxinator/project.rb b/lib/tmuxinator/project.rb
index 1ba2931..5cf68c5 100644
--- a/lib/tmuxinator/project.rb
+++ b/lib/tmuxinator/project.rb
@@ -4,11 +4,75 @@ module Tmuxinator
include Tmuxinator::Deprecations
include Tmuxinator::WemuxSupport
- attr_reader :yaml, :custom_name
+ 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
+
+ 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?
- def initialize(yaml, custom_name = nil)
@yaml = yaml
- @custom_name = custom_name
+
+ @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
@@ -20,7 +84,7 @@ module Tmuxinator
def windows
windows_yml = yaml["tabs"] || yaml["windows"]
- @windows ||= windows_yml.map.with_index do |window_yml, index|
+ @windows ||= (windows_yml || {}).map.with_index do |window_yml, index|
Tmuxinator::Window.new(window_yml, index, self)
end
end
@@ -32,7 +96,7 @@ module Tmuxinator
def name
name = custom_name || yaml["project_name"] || yaml["name"]
- name.blank? ? nil : name.shellescape
+ name.blank? ? nil : name.to_s.shellescape
end
def pre
@@ -44,11 +108,21 @@ module Tmuxinator
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"]}"
+ "rbenv shell #{yaml['rbenv']}"
elsif rvm?
- "rvm use #{yaml["rvm"]}"
+ "rvm use #{yaml['rvm']}"
elsif pre_tab?
yaml["pre_tab"]
else
@@ -56,14 +130,6 @@ module Tmuxinator
end
end
- def attach
- attach = true
- if !yaml["attach"].nil?
- attach = yaml["attach"]
- end
- attach
- end
-
def post
post_config = yaml["post"]
if post_config.is_a?(Array)
@@ -86,8 +152,6 @@ module Tmuxinator
" -S #{socket_path}"
elsif socket_name
" -L #{socket_name}"
- else
- nil
end
end
@@ -101,9 +165,9 @@ module Tmuxinator
def tmux_options
if cli_args?
- " #{yaml["cli_args"].to_s.strip}"
+ " #{yaml['cli_args'].to_s.strip}"
elsif tmux_options?
- " #{yaml["tmux_options"].to_s.strip}"
+ " #{yaml['tmux_options'].to_s.strip}"
else
""
end
@@ -133,15 +197,11 @@ module Tmuxinator
!name.nil?
end
- def attach?
- !!attach
- end
-
def window(i)
"#{name}:#{i}"
end
- def send_pane_command(cmd, window_index, pane_index)
+ def send_pane_command(cmd, window_index, _pane_index)
if cmd.empty?
""
else
@@ -151,7 +211,7 @@ module Tmuxinator
def send_keys(cmd, window_index)
if cmd.empty?
- ""
+ ""
else
"#{tmux} send-keys -t #{window(window_index)} #{cmd.shellescape} C-m"
end
@@ -159,9 +219,9 @@ module Tmuxinator
def deprecations
deprecations = []
- deprecations << "DEPRECATION: rbenv/rvm specific options have been replaced by the pre_tab option and will not be supported in 0.8.0." if yaml["rbenv"] || yaml["rvm"]
- deprecations << "DEPRECATION: The tabs option has been replaced by the windows option and will not be supported in 0.8.0." if yaml["tabs"]
- deprecations << "DEPRECATION: The cli_args option has been replaced by the tmux_options option and will not be supported in 0.8.0." if yaml["cli_args"]
+ 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
end
@@ -177,6 +237,11 @@ module Tmuxinator
"#{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
+
private
def tmux_config
@@ -187,7 +252,7 @@ module Tmuxinator
options_hash = {}
options_string = `#{show_tmux_options}`
- options_string.encode!("UTF-8", :invalid => :replace)
+ options_string.encode!("UTF-8", invalid: :replace)
options_string.split("\n").map do |entry|
key, value = entry.split("\s")
options_hash[key] = value
diff --git a/lib/tmuxinator/version.rb b/lib/tmuxinator/version.rb
index f350429..863f7f7 100644
--- a/lib/tmuxinator/version.rb
+++ b/lib/tmuxinator/version.rb
@@ -1,3 +1,3 @@
module Tmuxinator
- VERSION = "0.6.11"
+ VERSION = "0.7.0"
end
diff --git a/lib/tmuxinator/wemux_support.rb b/lib/tmuxinator/wemux_support.rb
index a03a255..793f380 100644
--- a/lib/tmuxinator/wemux_support.rb
+++ b/lib/tmuxinator/wemux_support.rb
@@ -5,17 +5,17 @@ module Tmuxinator
end
def load_wemux_overrides
- self.instance_eval do
- def render
+ class_eval do
+ define_method :render do
template = File.read(Tmuxinator::Config.wemux_template)
Erubis::Eruby.new(template).result(binding)
end
- def name
+ define_method :name do
"wemux"
end
- def tmux
+ define_method :tmux do
"wemux"
end
end
diff --git a/lib/tmuxinator/window.rb b/lib/tmuxinator/window.rb
index 899cfe8..0ab8e1b 100644
--- a/lib/tmuxinator/window.rb
+++ b/lib/tmuxinator/window.rb
@@ -5,7 +5,9 @@ module Tmuxinator
attr_reader :name, :root, :panes, :layout, :commands, :index, :project
def initialize(window_yaml, index, project)
- @name = !window_yaml.keys.first.nil? ? window_yaml.keys.first.shellescape : nil
+ @name = if !window_yaml.keys.first.nil?
+ window_yaml.keys.first.shellescape
+ end
@root = nil
@panes = []
@layout = nil
@@ -18,7 +20,11 @@ module Tmuxinator
if value.is_a?(Hash)
@layout = value["layout"] ? value["layout"].shellescape : nil
@pre = value["pre"] if value["pre"]
- @root = value["root"] ? File.expand_path(value["root"]).shellescape : project.root? ? project.root : nil
+ @root = if value["root"]
+ File.expand_path(value["root"]).shellescape
+ elsif project.root?
+ project.root
+ end
@panes = build_panes(value["panes"])
else
@@ -29,7 +35,7 @@ module Tmuxinator
def build_panes(panes_yml)
Array(panes_yml).map.with_index do |pane_yml, index|
if pane_yml.is_a?(Hash)
- pane_yml.map do |name, commands|
+ pane_yml.map do |_name, commands|
Tmuxinator::Pane.new(index, project, self, *commands)
end
else
@@ -38,7 +44,7 @@ module Tmuxinator
end.flatten
end
- def build_commands(prefix, command_yml)
+ 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
@@ -80,9 +86,13 @@ module Tmuxinator
"#{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} -n #{name}"
+ "#{project.tmux} new-window #{path} -t #{tmux_window_target} #{tmux_window_name_option}"
end
def tmux_layout_command
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 236fb63..0f72352 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -1,39 +1,81 @@
+def yaml_load(file)
+ YAML.load(File.read(File.expand_path(file)))
+end
FactoryGirl.define do
- factory :project, :class => Tmuxinator::Project do
+ factory :project, class: Tmuxinator::Project do
transient do
- file { YAML.load(File.read("#{File.expand_path("spec/fixtures/sample.yml")}")) }
+ file { yaml_load("spec/fixtures/sample.yml") }
end
initialize_with { Tmuxinator::Project.new(file) }
end
- factory :project_with_custom_name, :class => Tmuxinator::Project do
- ignore do
- file { YAML.load(File.read("#{File.expand_path("spec/fixtures/sample.yml")}")) }
+ 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
- initialize_with { Tmuxinator::Project.new(file, "custom") }
+ 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_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 :project_with_deprecations, :class => Tmuxinator::Project do
+ factory :noname_project, class: Tmuxinator::Project do
transient do
- file { YAML.load(File.read("#{File.expand_path("spec/fixtures/sample.deprecations.yml")}")) }
+ file { yaml_load("spec/fixtures/noname.yml") }
end
initialize_with { Tmuxinator::Project.new(file) }
end
- factory :wemux_project, :class => Tmuxinator::Project do
+ factory :nowindows_project, class: Tmuxinator::Project do
transient do
- file { YAML.load(File.read("#{File.expand_path("spec/fixtures/sample_wemux.yml")}")) }
+ file { yaml_load("spec/fixtures/nowindows.yml") }
end
initialize_with { Tmuxinator::Project.new(file) }
end
- factory :noname_project, :class => Tmuxinator::Project do
+ factory :nameless_window_project, class: Tmuxinator::Project do
transient do
- file { YAML.load(File.read("#{File.expand_path("spec/fixtures/noname.yml")}")) }
+ file { yaml_load("spec/fixtures/nameless_window.yml") }
end
initialize_with { Tmuxinator::Project.new(file) }
diff --git a/spec/fixtures/sample.yml b/spec/fixtures/detach.yml
similarity index 98%
copy from spec/fixtures/sample.yml
copy to spec/fixtures/detach.yml
index bac06cb..0a00cc3 100644
--- a/spec/fixtures/sample.yml
+++ b/spec/fixtures/detach.yml
@@ -7,6 +7,7 @@ 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:
diff --git a/spec/fixtures/nameless_window.yml b/spec/fixtures/nameless_window.yml
new file mode 100644
index 0000000..a6d4779
--- /dev/null
+++ b/spec/fixtures/nameless_window.yml
@@ -0,0 +1,5 @@
+name: nameless_window
+root: ~/
+windows:
+ - ~: echo "this is a window with no name"
+ - other: echo "this window has a name"
diff --git a/spec/fixtures/nowindows.yml b/spec/fixtures/nowindows.yml
new file mode 100644
index 0000000..fe580de
--- /dev/null
+++ b/spec/fixtures/nowindows.yml
@@ -0,0 +1,3 @@
+name: no_windows
+root: ~/
+
diff --git a/spec/fixtures/sample.yml b/spec/fixtures/sample.yml
index bac06cb..b9332cb 100644
--- a/spec/fixtures/sample.yml
+++ b/spec/fixtures/sample.yml
@@ -7,6 +7,7 @@ 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:
diff --git a/spec/fixtures/sample_number_as_name.yml b/spec/fixtures/sample_number_as_name.yml
new file mode 100644
index 0000000..0463ddc
--- /dev/null
+++ b/spec/fixtures/sample_number_as_name.yml
@@ -0,0 +1,5 @@
+# ~/.tmuxinator/sample_number_as_name.yml
+
+name: 222
+windows:
+ - number: echo number as name fixture
diff --git a/spec/lib/tmuxinator/cli_spec.rb b/spec/lib/tmuxinator/cli_spec.rb
index 951fa8a..8b7b9f1 100644
--- a/spec/lib/tmuxinator/cli_spec.rb
+++ b/spec/lib/tmuxinator/cli_spec.rb
@@ -20,11 +20,11 @@ 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"])
end
it "gets completions" do
- out, _ = capture_io { cli.start }
+ out, _err = capture_io { cli.start }
expect(out).to include("test.yml")
end
end
@@ -35,16 +35,29 @@ describe Tmuxinator::Cli do
end
it "lists the commands" do
- out, _ = capture_io { cli.start }
- expect(out).to eq "#{%w(commands completions new open start debug copy delete implode version doctor list).join("\n")}\n"
+ out, _err = capture_io { cli.start }
+ expected = %w(commands
+ completions
+ new
+ open
+ start
+ 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(Tmuxinator::Config).to receive_messages(validate: project)
+ allow(Tmuxinator::Config).to receive_messages(version: 1.9)
allow(Kernel).to receive(:exec)
end
@@ -55,27 +68,74 @@ describe Tmuxinator::Cli 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")
+ allow($stdin).to receive_messages(getc: "y")
end
let(:project) { FactoryGirl.build(:project_with_deprecations) }
it "prints the deprecations" do
- out, _ = capture_io { cli.start }
+ out, _err = capture_io { cli.start }
expect(out).to include "DEPRECATION"
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(Tmuxinator::Config).to receive_messages(validate: project)
+ allow(Tmuxinator::Config).to receive_messages(version: 1.9)
allow(Kernel).to receive(:exec)
end
@@ -91,31 +151,70 @@ describe Tmuxinator::Cli do
describe "#new" do
let(:file) { StringIO.new }
+ let(:name) { "test" }
before do
- ARGV.replace(["new", "test"])
allow(File).to receive(:open) { |&block| block.yield file }
end
- context "existing project doesn't exist" do
+ context "without the --local option" do
before do
- allow(Tmuxinator::Config).to receive_messages(:exists? => false)
+ ARGV.replace(["new", name])
end
- it "creates a new tmuxinator project file" do
- capture_io { cli.start }
- expect(file.string).to_not be_empty
+ context "existing project doesn't exist" do
+ before do
+ expect(Tmuxinator::Config).to receive_messages(exists?: 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(:command) { "#{ENV['HOME']}\/\.tmuxinator\/#{name}\.yml" }
+
+ before do
+ expect(Tmuxinator::Config).to receive_messages(exists?: true)
+ end
+
+ it "just opens the file" do
+ expect(Kernel).to receive(:system).with(%r{#{command}})
+ capture_io { cli.start }
+ end
end
end
- context "files exists" do
+ context "with the --local option" do
before do
- allow(File).to receive_messages(:exists? => true)
+ ARGV.replace ["new", name, "--local"]
end
- it "just opens the file" do
- expect(Kernel).to receive(:system)
- capture_io { cli.start }
+ context "existing project doesn't exist" do
+ before do
+ expect(Tmuxinator::Config).to receive(:exists?).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(Tmuxinator::Config).to receive(:exists?).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
@@ -128,7 +227,7 @@ describe Tmuxinator::Cli do
context "new project already exists" do
before do
- allow(Thor::LineEditor).to receive_messages(:readline => "y")
+ allow(Thor::LineEditor).to receive_messages(readline: "y")
end
it "prompts user to confirm overwrite" do
@@ -150,20 +249,40 @@ describe Tmuxinator::Cli do
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
- ARGV.replace(["debug", "foo"])
- allow(Tmuxinator::Config).to receive_messages(:validate => project)
+ allow(Tmuxinator::Config).to receive_messages(validate: project)
+ expect(project).to receive(:render)
end
it "renders the project" do
- expect(project).to receive(:render)
+ 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"])
- expect(project).to receive(:render)
capture_io { cli.start }
end
end
@@ -171,7 +290,7 @@ describe Tmuxinator::Cli do
describe "#delete" do
before do
ARGV.replace(["delete", "foo"])
- allow(Thor::LineEditor).to receive_messages(:readline => "y")
+ allow(Thor::LineEditor).to receive_messages(readline: "y")
end
context "project exists" do
@@ -188,7 +307,7 @@ describe Tmuxinator::Cli do
context "project doesn't exist" do
before do
allow(Tmuxinator::Config).to receive(:exists?) { false }
- allow(Thor::LineEditor).to receive_messages(:readline => "y")
+ allow(Thor::LineEditor).to receive_messages(readline: "y")
end
it "exits with error message" do
@@ -200,7 +319,7 @@ describe Tmuxinator::Cli do
describe "#implode" do
before do
ARGV.replace(["implode"])
- allow(Thor::LineEditor).to receive_messages(:readline => "y")
+ allow(Thor::LineEditor).to receive_messages(readline: "y")
end
it "confirms deletion of all projects" do
@@ -231,7 +350,7 @@ describe Tmuxinator::Cli do
end
it "prints the current version" do
- out, _ = capture_io { cli.start }
+ out, _err = capture_io { cli.start }
expect(out).to eq "tmuxinator #{Tmuxinator::VERSION}\n"
end
end
@@ -248,4 +367,46 @@ describe Tmuxinator::Cli do
capture_io { cli.start }
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
diff --git a/spec/lib/tmuxinator/config_spec.rb b/spec/lib/tmuxinator/config_spec.rb
index 0600a40..bdf685c 100644
--- a/spec/lib/tmuxinator/config_spec.rb
+++ b/spec/lib/tmuxinator/config_spec.rb
@@ -3,7 +3,7 @@ require "spec_helper"
describe Tmuxinator::Config do
describe "#root" do
it "is ~/.tmuxintaor" do
- expect(Tmuxinator::Config.root).to eq "#{ENV["HOME"]}/.tmuxinator"
+ expect(Tmuxinator::Config.root).to eq "#{ENV['HOME']}/.tmuxinator"
end
end
@@ -43,10 +43,13 @@ describe Tmuxinator::Config do
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(:exists?).with(Tmuxinator::Config.default) { true }
+ allow(File).to receive(:exists?).with(local_default) { false }
+ allow(File).to receive(:exists?).with(proj_default) { true }
end
it "returns true" do
@@ -56,7 +59,8 @@ describe Tmuxinator::Config do
context "when the file doesn't exist" do
before do
- allow(File).to receive(:exists?).with(Tmuxinator::Config.default) { false }
+ allow(File).to receive(:exists?).with(local_default) { false }
+ allow(File).to receive(:exists?).with(proj_default) { false }
end
it "returns true" do
@@ -143,8 +147,8 @@ describe Tmuxinator::Config do
describe "#exists?" do
before do
- allow(File).to receive_messages(:exists? => true)
- allow(Tmuxinator::Config).to receive_messages(:project => "")
+ allow(File).to receive_messages(exists?: true)
+ allow(Tmuxinator::Config).to receive_messages(project: "")
end
it "checks if the given project exists" do
@@ -152,23 +156,116 @@ describe Tmuxinator::Config do
end
end
- describe "#project" do
+ 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)
+ 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(:exists?).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(:exists?).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(:exists?).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 "#{root}/new-project.yml"
+ 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(:exists?).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(:exists?).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
diff --git a/spec/lib/tmuxinator/project_spec.rb b/spec/lib/tmuxinator/project_spec.rb
index 619ded8..b8f14fa 100644
--- a/spec/lib/tmuxinator/project_spec.rb
+++ b/spec/lib/tmuxinator/project_spec.rb
@@ -2,10 +2,27 @@ require "spec_helper"
describe Tmuxinator::Project do
let(:project) { FactoryGirl.build(:project) }
- let(:project_with_custom_name) { FactoryGirl.build(:project_with_custom_name) }
- let(:project_with_deprecations) { FactoryGirl.build(:project_with_deprecations) }
+ 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_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(:nameless_window_project) do
+ FactoryGirl.build(:nameless_window_project)
+ end
describe "#initialize" do
context "valid yaml" do
@@ -65,7 +82,7 @@ describe Tmuxinator::Project do
context "without root" do
it "doesn't throw an error" do
- expect{noname_project.root}.to_not raise_error
+ expect { noname_project.root }.to_not raise_error
end
end
end
@@ -91,7 +108,14 @@ describe Tmuxinator::Project do
context "without name" do
it "displays error message" do
- expect{noname_project.name}.to_not raise_error
+ 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
end
@@ -104,8 +128,9 @@ describe Tmuxinator::Project do
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")
+ 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
@@ -115,8 +140,9 @@ describe Tmuxinator::Project do
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")
+ 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
@@ -126,8 +152,8 @@ describe Tmuxinator::Project do
context "pre_tab is present" do
before do
- allow(project).to receive_messages(:rbenv? => false)
- allow(project).to receive_messages(:pre_tab? => true)
+ 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
@@ -140,7 +166,7 @@ describe Tmuxinator::Project do
describe "#socket" do
context "socket path is present" do
before do
- allow(project).to receive_messages(:socket_path => "/tmp")
+ allow(project).to receive_messages(socket_path: "/tmp")
end
it "gets the socket path" do
@@ -170,7 +196,7 @@ describe Tmuxinator::Project do
describe "#tmux_options" do
context "no tmux options" do
before do
- allow(project).to receive_messages(:tmux_options? => false)
+ allow(project).to receive_messages(tmux_options?: false)
end
it "returns nothing" do
@@ -180,18 +206,20 @@ describe Tmuxinator::Project do
context "with deprecations" do
before do
- allow(project_with_deprecations).to receive_messages(:cli_args? => true)
+ 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"
+ 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))
+ allow(project).to \
+ receive_messages(show_tmux_options: tmux_config(pane_base_index: 3))
expect(project.get_pane_base_index).to eq("3")
end
@@ -199,7 +227,8 @@ describe Tmuxinator::Project do
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))
+ allow(project).to \
+ receive_messages(show_tmux_options: tmux_config(base_index: 1))
expect(project.get_base_index).to eq("1")
end
@@ -208,8 +237,8 @@ describe Tmuxinator::Project do
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")
+ 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
@@ -219,8 +248,8 @@ describe Tmuxinator::Project do
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")
+ 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
@@ -234,15 +263,15 @@ describe Tmuxinator::Project do
it "gets the startup window from project config" do
project.yaml["startup_window"] = "logs"
- expect(project.startup_window).to eq("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)
+ allow(project).to receive_messages(base_index: 8)
- expect(project.startup_window).to eq 8
+ expect(project.startup_window).to eq 8
end
end
end
@@ -286,7 +315,8 @@ describe Tmuxinator::Project do
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"
+ 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
@@ -300,7 +330,8 @@ describe Tmuxinator::Project do
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"
+ 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
@@ -323,7 +354,11 @@ describe Tmuxinator::Project do
let(:window) { project.windows.keep_if { |w| w.name == "shell" }.first }
it "splits commands into an array" do
- expect(window.commands).to eq(["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"])
+ 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
@@ -339,16 +374,125 @@ describe Tmuxinator::Project do
end
context "pre in yaml is Array" do
- before {
+ 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 "::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
diff --git a/spec/lib/tmuxinator/util_spec.rb b/spec/lib/tmuxinator/util_spec.rb
index 2c11363..27abab8 100644
--- a/spec/lib/tmuxinator/util_spec.rb
+++ b/spec/lib/tmuxinator/util_spec.rb
@@ -2,5 +2,4 @@ require "spec_helper"
describe Tmuxinator::Util do
let(:util) { Object.new.extend(Tmuxinator::Util) }
-
end
diff --git a/spec/lib/tmuxinator/wemux_support_spec.rb b/spec/lib/tmuxinator/wemux_support_spec.rb
new file mode 100644
index 0000000..a7b9624
--- /dev/null
+++ b/spec/lib/tmuxinator/wemux_support_spec.rb
@@ -0,0 +1,47 @@
+require "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
diff --git a/spec/lib/tmuxinator/window_spec.rb b/spec/lib/tmuxinator/window_spec.rb
index 0c5613f..5e1f074 100644
--- a/spec/lib/tmuxinator/window_spec.rb
+++ b/spec/lib/tmuxinator/window_spec.rb
@@ -3,10 +3,14 @@ require "spec_helper"
describe Tmuxinator::Window do
let(:project) { double }
let(:panes) { ["vim", nil, "top"] }
+ let(:window_name) { "editor" }
let(:yaml) do
{
- "editor" => {
- "pre" => ["echo 'I get run in each pane. Before each pane command!'", nil],
+ window_name => {
+ "pre" => [
+ "echo 'I get run in each pane. Before each pane command!'",
+ nil
+ ],
"layout" => "main-vertical",
"panes" => panes
}
@@ -17,7 +21,10 @@ describe Tmuxinator::Window do
"editor" => {
"root" => "/project/override",
"root?" => true,
- "pre" => ["echo 'I get run in each pane. Before each pane command!'", nil],
+ "pre" => [
+ "echo 'I get run in each pane. Before each pane command!'",
+ nil
+ ],
"layout" => "main-vertical",
"panes" => panes
}
@@ -29,12 +36,12 @@ describe Tmuxinator::Window do
before do
allow(project).to receive_messages(
- :tmux => "tmux",
- :name => "test",
- :base_index => 1,
- :root => "/project/tmuxinator",
- :root? => true
- )
+ tmux: "tmux",
+ name: "test",
+ base_index: 1,
+ root: "/project/tmuxinator",
+ root?: true
+ )
end
describe "#initialize" do
@@ -61,7 +68,7 @@ describe Tmuxinator::Window do
let(:pane) { double(:pane) }
before do
- allow(Tmuxinator::Pane).to receive_messages :new => pane
+ allow(Tmuxinator::Pane).to receive_messages new: pane
end
context "with a three element Array" do
@@ -133,7 +140,10 @@ describe Tmuxinator::Window do
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"]
+ 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
@@ -158,27 +168,78 @@ describe Tmuxinator::Window do
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 "#tmux_new_window_command" 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 => "",
- :tmux => "tmux",
- :root => "/project/tmuxinator",
- :root? => true,
- :base_index => 1
+ name: "test",
+ tmux: "tmux",
+ root: root,
+ root?: root?,
+ base_index: 1
)
end
- context "tmux 1.6 and below" do
- before do
- allow(Tmuxinator::Config).to receive_messages(:version => 1.6)
+ let(:tmux_part) { project.tmux }
+ 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 "specifies root path by passing default-path to tmux" do
- expect(window.tmux_new_window_command).to include("default-path /project/tmuxinator")
+ it "does not set name option" do
+ expect(window.tmux_new_window_command).to eq full_command
end
end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 57a6cdb..2a4b73f 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -7,13 +7,12 @@ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
Coveralls::SimpleCov::Formatter
]
SimpleCov.start do
- add_filter 'vendor/cache'
+ add_filter "vendor/cache"
end
require "tmuxinator"
require "factory_girl"
-
FactoryGirl.find_definitions
RSpec.configure do |config|
@@ -22,21 +21,23 @@ end
# Copied from minitest.
def capture_io
- begin
- require 'stringio'
+ require "stringio"
- captured_stdout, captured_stderr = StringIO.new, StringIO.new
+ captured_stdout = StringIO.new
+ captured_stderr = StringIO.new
- orig_stdout, orig_stderr = $stdout, $stderr
- $stdout, $stderr = captured_stdout, captured_stderr
+ orig_stdout = $stdout
+ orig_stderr = $stderr
- yield
+ $stdout = captured_stdout
+ $stderr = captured_stderr
- return captured_stdout.string, captured_stderr.string
- ensure
- $stdout = orig_stdout
- $stderr = orig_stderr
- end
+ yield
+
+ return captured_stdout.string, captured_stderr.string
+ensure
+ $stdout = orig_stdout
+ $stderr = orig_stderr
end
def tmux_config(options = {})
@@ -46,11 +47,11 @@ def tmux_config(options = {})
"bell-on-alert off",
]
- if base_index = options.fetch(:base_index) {1}
+ 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}
+ if pane_base_index = options.fetch(:pane_base_index) { 1 }
standard_options << "pane-base-index #{pane_base_index}"
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