Compare commits
No commits in common. "master" and "gh-pages" have entirely different histories.
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,6 +0,0 @@
|
||||
*.gem
|
||||
.rvmrc
|
||||
.local*
|
||||
.yardoc
|
||||
doc
|
||||
pkg
|
@ -1,2 +0,0 @@
|
||||
rvm: 1.9.2
|
||||
script: "bundle exec rake spec"
|
32
Gemfile.lock
32
Gemfile.lock
@ -1,32 +0,0 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
teamocil (0.3.2)
|
||||
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
diff-lcs (1.1.3)
|
||||
maruku (0.6.0)
|
||||
syntax (>= 1.0.0)
|
||||
rake (0.9.2)
|
||||
rspec (2.6.0)
|
||||
rspec-core (~> 2.6.0)
|
||||
rspec-expectations (~> 2.6.0)
|
||||
rspec-mocks (~> 2.6.0)
|
||||
rspec-core (2.6.4)
|
||||
rspec-expectations (2.6.0)
|
||||
diff-lcs (~> 1.1.2)
|
||||
rspec-mocks (2.6.0)
|
||||
syntax (1.0.0)
|
||||
yard (0.7.5)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
maruku
|
||||
rake
|
||||
rspec
|
||||
teamocil!
|
||||
yard
|
3
LICENSE
3
LICENSE
@ -1,3 +0,0 @@
|
||||
Copyright 2011-2012 Rémi Prévost.
|
||||
You may use this work without restrictions, as long as this notice is included.
|
||||
The work is provided "as is" without warranty of any kind, neither express nor implied.
|
204
README.md
204
README.md
@ -1,204 +0,0 @@
|
||||
# Teamocil
|
||||
|
||||
Teamocil is a simple tool used to automatically create sessions, windows and splits in [tmux](http://tmux.sourceforge.net/) with YAML files.
|
||||
|
||||
[![Build Status](https://secure.travis-ci.org/remiprev/teamocil.png)](http://travis-ci.org/remiprev/teamocil)
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
$ gem install teamocil
|
||||
$ mkdir ~/.teamocil
|
||||
$ teamocil --edit sample
|
||||
$ tmux
|
||||
$ teamocil sample
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
* `--here` opens the session in the current window, it doesn’t create an empty first window.
|
||||
* `--layout` takes a custom file path to a YAML layout file.
|
||||
* `--edit` opens the layout file (whether or not `--layout` is used) with `$EDITOR`.
|
||||
* `--list` lists all available layouts.
|
||||
|
||||
## Layout file structure
|
||||
|
||||
A layout file is a single YAML file located in `~/.teamocil` (eg. `~/.teamocil/my-project.yml`).
|
||||
|
||||
### Session
|
||||
|
||||
You can wrap your entire layout file in a `session` and Teamocil will rename the current session (so that you can find it more easily when running `tmux list-sessions`) before creating your windows.
|
||||
|
||||
#### Keys
|
||||
|
||||
* `name` (the name of the session)
|
||||
|
||||
#### Example
|
||||
|
||||
```yaml
|
||||
session:
|
||||
name: "my-awesome-session"
|
||||
windows:
|
||||
[windows list]
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
If you are not using a top-level `session` key, then the first key of your layout file will be `windows`, an array of window items.
|
||||
|
||||
#### Item keys
|
||||
|
||||
* `name` (the name that will appear in `tmux` statusbar)
|
||||
* `root` (the directory in which every split will be created)
|
||||
* `filters` (a hash of `before` and `after` commands to run for each split)
|
||||
* `splits` (an array of split items)
|
||||
* `options` (a hash of tmux options, see `man tmux` for a list)
|
||||
|
||||
#### Example
|
||||
|
||||
```yaml
|
||||
windows:
|
||||
- name: "my-first-window"
|
||||
options:
|
||||
synchronize-panes: true
|
||||
root: "~/Projects/foo-www"
|
||||
filters:
|
||||
before:
|
||||
- "echo 'Let’s use ruby-1.9.2 for each split in this window.'"
|
||||
- "rvm use 1.9.2"
|
||||
splits:
|
||||
[splits list]
|
||||
- name: "my-second-window"
|
||||
root: "~/Projects/foo-api"
|
||||
splits:
|
||||
[splits list]
|
||||
- name: "my-third-window"
|
||||
root: "~/Projects/foo-daemons"
|
||||
splits:
|
||||
[splits list]
|
||||
```
|
||||
|
||||
### Splits
|
||||
|
||||
Every window must define an array of splits that will be created within it. A vertical or horizontal split will be created, depending on whether the `width` or `height` parameter is used.
|
||||
|
||||
#### Item keys
|
||||
|
||||
* `cmd` (the commands to initially execute in the split)
|
||||
* `width` (the split width, in percentage)
|
||||
* `height` (the split width, in percentage)
|
||||
* `target` (the split to set focus on, before creating the current one)
|
||||
|
||||
#### Example
|
||||
|
||||
```yaml
|
||||
windows:
|
||||
- name: "my-first-window"
|
||||
root: "~/Projects/foo-www"
|
||||
filters:
|
||||
before: "rvm use 1.9.2"
|
||||
after: "echo 'I am done initializing this split.'"
|
||||
splits:
|
||||
- cmd: "git status"
|
||||
- cmd: "bundle exec rails server --port 4000"
|
||||
width: 50
|
||||
- cmd:
|
||||
- "sudo service memcached start"
|
||||
- "sudo service mongodb start"
|
||||
height: 50
|
||||
```
|
||||
|
||||
## Layout examples
|
||||
|
||||
See more example files in the `examples` directory.
|
||||
|
||||
### Simple two splits window
|
||||
|
||||
#### Content of `~/.teamocil/sample-1.yml`
|
||||
|
||||
```yaml
|
||||
windows:
|
||||
- name: "sample-two-splits"
|
||||
root: "~/Code/sample/www"
|
||||
splits:
|
||||
- cmd: ["pwd", "ls -la"]
|
||||
- cmd: "rails server --port 3000"
|
||||
width: 50
|
||||
```
|
||||
|
||||
|
||||
#### Result of `$ teamocil sample-1`
|
||||
|
||||
.------------------.------------------.
|
||||
| (0) | (1) |
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
'------------------'------------------'
|
||||
|
||||
### Four tiled splits window
|
||||
|
||||
#### Content of `~/.teamocil/sample-2.yml`
|
||||
|
||||
```yaml
|
||||
windows:
|
||||
- name: "sample-four-splits"
|
||||
root: "~/Code/sample/www"
|
||||
splits:
|
||||
- cmd: "pwd"
|
||||
- cmd: "pwd"
|
||||
width: 50
|
||||
- cmd: "pwd"
|
||||
height: 50
|
||||
target: "bottom-right"
|
||||
- cmd: "pwd"
|
||||
height: 50
|
||||
target: "bottom-left"
|
||||
```
|
||||
|
||||
#### Result of `$ teamocil sample-2`
|
||||
|
||||
.------------------.------------------.
|
||||
| (0) | (1) |
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
|------------------|------------------|
|
||||
| (3) | (2) |
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
'------------------'------------------'
|
||||
|
||||
## Extras
|
||||
|
||||
### Zsh autocompletion
|
||||
|
||||
To get autocompletion when typing `teamocil <Tab>` in a zsh session, add this line to your `~/.zshrc` file:
|
||||
|
||||
```zsh
|
||||
compctl -g '~/.teamocil/*(:t:r)' teamocil
|
||||
```
|
||||
|
||||
## Todo list
|
||||
|
||||
* Making sure the layout is valid before executing it (ie. throw exceptions).
|
||||
* Add more specs.
|
||||
|
||||
## Contributors
|
||||
|
||||
Feel free to contribute and submit issues/pull requests [on GitHub](https://github.com/remiprev/teamocil/issues), just like these fine folks did:
|
||||
|
||||
* Samuel Garneau ([garno](https://github.com/garno))
|
||||
* Jimmy Bourassa ([jbourassa](https://github.com/jbourassa))
|
||||
|
||||
Take a look at the `spec` folder before you do, and make sure `bundle exec rake spec` passes after your modifications :)
|
||||
|
||||
## License
|
||||
|
||||
Teamocil is © 2011-2012 [Rémi Prévost](http://exomel.com) and may be freely distributed under the [LITL license](http://litl.info/). See the `LICENSE` file.
|
28
Rakefile
28
Rakefile
@ -1,28 +0,0 @@
|
||||
require "bundler"
|
||||
Bundler.require(:development)
|
||||
|
||||
require "bundler/gem_tasks"
|
||||
require "rspec/core/rake_task"
|
||||
|
||||
task :default => :spec
|
||||
|
||||
desc "Run all specs"
|
||||
RSpec::Core::RakeTask.new(:spec) do |task| # {{{
|
||||
task.pattern = "spec/**/*_spec.rb"
|
||||
task.rspec_opts = "--colour --format=documentation"
|
||||
end # }}}
|
||||
|
||||
desc "Generate YARD Documentation"
|
||||
YARD::Rake::YardocTask.new do |task| # {{{
|
||||
task.options = [
|
||||
"-o", File.expand_path("../doc", __FILE__),
|
||||
"--readme=README.md",
|
||||
"--markup=markdown",
|
||||
"--markup-provider=maruku",
|
||||
"--no-private",
|
||||
"--no-cache",
|
||||
"--protected",
|
||||
"--title=Teamocil",
|
||||
]
|
||||
task.files = ["lib/**/*.rb"]
|
||||
end # }}}
|
@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
||||
|
||||
require 'yaml'
|
||||
require 'teamocil'
|
||||
|
||||
Teamocil::CLI.new(ARGV, ENV)
|
@ -1,12 +0,0 @@
|
||||
windows:
|
||||
- name: simple-four-splits
|
||||
splits:
|
||||
- cmd: "echo 'first split'"
|
||||
- cmd: "echo 'second split'"
|
||||
width: 50
|
||||
- cmd: "echo 'fourth split'"
|
||||
height: 50
|
||||
target: bottom-right
|
||||
- cmd: "echo 'third split'"
|
||||
height: 50
|
||||
target: bottom-left
|
@ -1,12 +0,0 @@
|
||||
windows:
|
||||
- name: simple-one-and-three-splits
|
||||
splits:
|
||||
- cmd: "echo 'first split'"
|
||||
- cmd: "echo 'second split'"
|
||||
width: 50
|
||||
- cmd: "echo 'third split'"
|
||||
height: 66
|
||||
target: bottom-right
|
||||
- cmd: "echo 'fourth split'"
|
||||
height: 50
|
||||
target: bottom-right
|
@ -1,18 +0,0 @@
|
||||
windows:
|
||||
- name: simple-six-splits
|
||||
splits:
|
||||
- cmd: "echo 'first split'"
|
||||
- cmd: "echo 'second split'"
|
||||
width: 50
|
||||
- cmd: "echo 'fourth split'"
|
||||
height: 66
|
||||
target: bottom-right
|
||||
- cmd: "echo 'third split'"
|
||||
height: 66
|
||||
target: bottom-left
|
||||
- cmd: "echo 'sixth split'"
|
||||
height: 50
|
||||
target: bottom-right
|
||||
- cmd: "echo 'fifth split'"
|
||||
height: 50
|
||||
target: bottom-left
|
@ -1,6 +0,0 @@
|
||||
windows:
|
||||
- name: simple-two-horizontal-splits
|
||||
splits:
|
||||
- cmd: "echo 'first split'"
|
||||
- cmd: "echo 'second split'"
|
||||
height: 50
|
@ -1,6 +0,0 @@
|
||||
windows:
|
||||
- name: simple-two-vertical-splits
|
||||
splits:
|
||||
- cmd: "echo 'first split'"
|
||||
- cmd: "echo 'second split'"
|
||||
width: 50
|
15
index.html
Normal file
15
index.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title></title>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/documentup/latest.min.js"></script>
|
||||
<script>
|
||||
DocumentUp.document({
|
||||
repo: "remiprev/teamocil",
|
||||
travis: true
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
@ -1,5 +0,0 @@
|
||||
module Teamocil
|
||||
VERSION = "0.3.2"
|
||||
autoload :Layout, "teamocil/layout"
|
||||
autoload :CLI, "teamocil/cli"
|
||||
end
|
@ -1,94 +0,0 @@
|
||||
require 'optparse'
|
||||
require 'fileutils'
|
||||
|
||||
module Teamocil
|
||||
# This class handles interaction with the `tmux` utility.
|
||||
class CLI
|
||||
|
||||
attr_accessor :layout, :layouts
|
||||
|
||||
# Initialize a new run of `tmux`
|
||||
#
|
||||
# @param argv [Hash] the command line parameters hash (usually `ARGV`).
|
||||
# @param env [Hash] the environment variables hash (usually `ENV`).
|
||||
def initialize(argv, env) # {{{
|
||||
parse_options! argv
|
||||
layout_path = File.join("#{env["HOME"]}", ".teamocil")
|
||||
|
||||
if @options.include?(:list)
|
||||
@layouts = get_layouts(layout_path)
|
||||
return print_layouts
|
||||
end
|
||||
|
||||
if @options.include?(:layout)
|
||||
file = @options[:layout]
|
||||
else
|
||||
file = ::File.join(layout_path, "#{argv[0]}.yml")
|
||||
end
|
||||
|
||||
if @options[:edit]
|
||||
::FileUtils.touch file unless File.exists?(file)
|
||||
|
||||
Kernel.system("$EDITOR \"#{file}\"")
|
||||
else
|
||||
bail "There is no file \"#{file}\"" unless File.exists?(file)
|
||||
bail "You must be in a tmux session to use teamocil" unless env["TMUX"]
|
||||
|
||||
parsed_layout = YAML.load_file(file)
|
||||
@layout = Teamocil::Layout.new(parsed_layout, @options)
|
||||
@layout.compile!
|
||||
@layout.execute_commands(@layout.generate_commands)
|
||||
end
|
||||
end # }}}
|
||||
|
||||
# Parse the command line options
|
||||
def parse_options!(args) # {{{
|
||||
@options = {}
|
||||
opts = ::OptionParser.new do |opts|
|
||||
opts.banner = "Usage: teamocil [options] <layout>
|
||||
|
||||
Options:
|
||||
"
|
||||
opts.on("--here", "Set up the first window in the current window") do
|
||||
@options[:here] = true
|
||||
end
|
||||
|
||||
opts.on("--edit", "Edit the YAML layout file instead of using it") do
|
||||
@options[:edit] = true
|
||||
end
|
||||
|
||||
opts.on("--layout [LAYOUT]", "Use a specific layout file, instead of `~/.teamocil/<layout>.yml`") do |layout|
|
||||
@options[:layout] = layout
|
||||
end
|
||||
|
||||
opts.on("--list", "List all available layouts in `~/.teamocil/`") do
|
||||
@options[:list] = true
|
||||
end
|
||||
|
||||
end
|
||||
opts.parse! args
|
||||
end # }}}
|
||||
|
||||
# Return an array of available layouts
|
||||
#
|
||||
# @param path [String] the path used to look for layouts
|
||||
def get_layouts(path) # {{{
|
||||
Dir.glob(File.join(path, "*.yml")).map { |file| File.basename(file).gsub(/\..+$/, "") }.sort
|
||||
end # }}}
|
||||
|
||||
# Print each layout on a single line
|
||||
def print_layouts # {{{
|
||||
STDOUT.puts @layouts.join("\n")
|
||||
exit 0
|
||||
end # }}}
|
||||
|
||||
# Print an error message and exit the utility
|
||||
#
|
||||
# @param msg [Mixed] something to print before exiting.
|
||||
def bail(msg) # {{{
|
||||
STDERR.puts "[teamocil] #{msg}"
|
||||
exit 1
|
||||
end # }}}
|
||||
|
||||
end
|
||||
end
|
@ -1,46 +0,0 @@
|
||||
module Teamocil
|
||||
|
||||
# This class act as a wrapper around a tmux YAML layout file
|
||||
class Layout
|
||||
autoload :Session, "teamocil/layout/session"
|
||||
autoload :Window, "teamocil/layout/window"
|
||||
autoload :Split, "teamocil/layout/split"
|
||||
|
||||
attr_reader :session
|
||||
|
||||
# Initialize a new layout from a hash
|
||||
#
|
||||
# @param layout [Hash] the parsed layout
|
||||
# @param options [Hash] some options
|
||||
def initialize(layout, options={}) # {{{
|
||||
@layout = layout
|
||||
@options = options
|
||||
end # }}}
|
||||
|
||||
# Generate tmux commands based on the data found in the layout file
|
||||
#
|
||||
# @return [Array] an array of shell commands to send
|
||||
def generate_commands # {{{
|
||||
@session.generate_commands
|
||||
end # }}}
|
||||
|
||||
# Compile the layout into objects
|
||||
#
|
||||
# @return [Session]
|
||||
def compile! # {{{
|
||||
if @layout["session"].nil?
|
||||
@session = Session.new @options, "windows" => @layout["windows"]
|
||||
else
|
||||
@session = Session.new @options, @layout["session"]
|
||||
end
|
||||
end # }}}
|
||||
|
||||
# Execute each command in the shell
|
||||
#
|
||||
# @param commands [Array] an array of complete commands to send to the shell
|
||||
def execute_commands(commands) # {{{
|
||||
`#{commands.join("; ")}`
|
||||
end # }}}
|
||||
|
||||
end
|
||||
end
|
@ -1,31 +0,0 @@
|
||||
module Teamocil
|
||||
class Layout
|
||||
|
||||
# This class represents a session within tmux
|
||||
class Session
|
||||
attr_reader :options, :windows, :name
|
||||
|
||||
# Initialize a new tmux session
|
||||
#
|
||||
# @param options [Hash] the options, mostly passed by the CLI
|
||||
# @param attrs [Hash] the session data from the layout file
|
||||
def initialize(options, attrs={}) # {{{
|
||||
@name = attrs["name"]
|
||||
@windows = attrs["windows"].each_with_index.map { |window, window_index| Window.new(self, window_index, window) }
|
||||
@options = options
|
||||
end # }}}
|
||||
|
||||
# Generate commands to send to tmux
|
||||
#
|
||||
# @return [Array]
|
||||
def generate_commands # {{{
|
||||
commands = []
|
||||
commands << "tmux rename-session \"#{@name}\"" unless @name.nil?
|
||||
commands << @windows.map(&:generate_commands)
|
||||
commands << "tmux select-pane -t 0"
|
||||
commands
|
||||
end # }}}
|
||||
|
||||
end
|
||||
end
|
||||
end
|
@ -1,64 +0,0 @@
|
||||
module Teamocil
|
||||
class Layout
|
||||
|
||||
# This class represents a split within a tmux window
|
||||
class Split
|
||||
attr_reader :width, :height, :cmd, :index, :target
|
||||
|
||||
# Initialize a new tmux split
|
||||
#
|
||||
# @param session [Session] the window where the split is initialized
|
||||
# @param index [Fixnnum] the split index
|
||||
# @param attrs [Hash] the split data from the layout file
|
||||
def initialize(window, index, attrs={}) # {{{
|
||||
@height = attrs["height"]
|
||||
@width = attrs["width"]
|
||||
@cmd = attrs["cmd"]
|
||||
@target = attrs["target"]
|
||||
|
||||
@window = window
|
||||
@index = index
|
||||
end # }}}
|
||||
|
||||
# Generate commands to send to tmux
|
||||
#
|
||||
# @return [Array]
|
||||
def generate_commands # {{{
|
||||
commands = []
|
||||
|
||||
# Is it a vertical or horizontal split?
|
||||
init_command = ""
|
||||
unless @index == 0
|
||||
if !@width.nil?
|
||||
init_command = "tmux split-window -h -p #{@width}"
|
||||
elsif !@height.nil?
|
||||
init_command = "tmux split-window -p #{@height}"
|
||||
else
|
||||
init_command = "tmux split-window"
|
||||
end
|
||||
init_command << " -t #{@target}" unless @target.nil?
|
||||
commands << init_command
|
||||
end
|
||||
|
||||
# Wrap all commands around filters
|
||||
@cmd = [@window.filters["before"]] + [@cmd] + [@window.filters["after"]]
|
||||
|
||||
# If a `root` key exist, start each split in this directory
|
||||
@cmd.unshift "cd \"#{@window.root}\"" unless @window.root.nil?
|
||||
|
||||
# Set the TEAMOCIL environment variable
|
||||
@cmd.unshift "export TEAMOCIL=1"
|
||||
|
||||
# Execute each split command
|
||||
@cmd.flatten.compact.each do |command|
|
||||
commands << "tmux send-keys -t #{@index} \"#{command}\""
|
||||
commands << "tmux send-keys -t #{@index} Enter"
|
||||
end
|
||||
|
||||
commands
|
||||
end # }}}
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
@ -1,55 +0,0 @@
|
||||
module Teamocil
|
||||
class Layout
|
||||
|
||||
# This class represents a window within tmux
|
||||
class Window
|
||||
attr_reader :filters, :root, :splits, :options, :index, :name
|
||||
|
||||
# Initialize a new tmux window
|
||||
#
|
||||
# @param session [Session] the session where the window is initialized
|
||||
# @param index [Fixnnum] the window index
|
||||
# @param attrs [Hash] the window data from the layout file
|
||||
def initialize(session, index, attrs={}) # {{{
|
||||
@name = attrs["name"]
|
||||
@root = attrs["root"]
|
||||
@options = attrs["options"] || {}
|
||||
|
||||
@splits = attrs["splits"] || []
|
||||
@splits = @splits.each_with_index.map { |split, split_index| Split.new(self, split_index, split) }
|
||||
|
||||
@filters = attrs["filters"] || {}
|
||||
@filters["before"] ||= []
|
||||
@filters["after"] ||= []
|
||||
|
||||
@index = index
|
||||
@session = session
|
||||
end # }}}
|
||||
|
||||
# Generate commands to send to tmux
|
||||
#
|
||||
# @return [Array]
|
||||
def generate_commands # {{{
|
||||
commands = []
|
||||
|
||||
if @session.options.include?(:here) and @index == 0
|
||||
commands << "tmux rename-window \"#{@name}\""
|
||||
else
|
||||
commands << "tmux new-window -n \"#{@name}\""
|
||||
end
|
||||
|
||||
commands << @splits.map(&:generate_commands)
|
||||
|
||||
@options.each_pair do |option, value|
|
||||
value = "on" if value === true
|
||||
value = "off" if value === false
|
||||
commands << "tmux set-window-option #{option} #{value}"
|
||||
end
|
||||
|
||||
commands
|
||||
end # }}}
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
@ -1,43 +0,0 @@
|
||||
require File.join(File.dirname(__FILE__), "spec_helper.rb")
|
||||
|
||||
describe Teamocil::CLI do
|
||||
|
||||
context "executing" do
|
||||
|
||||
context "not in tmux" do
|
||||
|
||||
before do # {{{
|
||||
@fake_env = { "TMUX" => 1, "HOME" => File.join(File.dirname(__FILE__), "fixtures") }
|
||||
end # }}}
|
||||
|
||||
it "should allow editing" do # {{{
|
||||
FileUtils.stub(:touch)
|
||||
Kernel.should_receive(:system).with(any_args())
|
||||
|
||||
@cli = Teamocil::CLI.new(["--edit", "my-layout"], @fake_env)
|
||||
end # }}}
|
||||
end
|
||||
|
||||
context "in tmux" do
|
||||
|
||||
before do # {{{
|
||||
@fake_env = { "TMUX" => 1, "HOME" => File.join(File.dirname(__FILE__), "fixtures") }
|
||||
end # }}}
|
||||
|
||||
it "creates a layout" do # {{{
|
||||
@cli = Teamocil::CLI.new(["sample"], @fake_env)
|
||||
@cli.layout.session.name.should == "sample"
|
||||
@cli.layout.session.windows.length.should == 2
|
||||
@cli.layout.session.windows.first.name.should == "foo"
|
||||
@cli.layout.session.windows.last.name.should == "bar"
|
||||
end # }}}
|
||||
|
||||
it "lists available layouts" do # {{{
|
||||
@cli = Teamocil::CLI.new(["--list"], @fake_env)
|
||||
@cli.layouts.should == ["sample", "sample-2"]
|
||||
end # }}}
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
10
spec/fixtures/.teamocil/sample-2.yml
vendored
10
spec/fixtures/.teamocil/sample-2.yml
vendored
@ -1,10 +0,0 @@
|
||||
session:
|
||||
name: sample-2
|
||||
root: ~
|
||||
windows:
|
||||
- name: "foo"
|
||||
splits:
|
||||
- cmd: "pwd"
|
||||
- name: "bar"
|
||||
splits:
|
||||
- cmd: "pwd"
|
10
spec/fixtures/.teamocil/sample.yml
vendored
10
spec/fixtures/.teamocil/sample.yml
vendored
@ -1,10 +0,0 @@
|
||||
session:
|
||||
name: sample
|
||||
root: ~
|
||||
windows:
|
||||
- name: "foo"
|
||||
splits:
|
||||
- cmd: "pwd"
|
||||
- name: "bar"
|
||||
splits:
|
||||
- cmd: "pwd"
|
43
spec/fixtures/layouts.yml
vendored
43
spec/fixtures/layouts.yml
vendored
@ -1,43 +0,0 @@
|
||||
# Simple two windows layout
|
||||
two-windows:
|
||||
windows:
|
||||
- name: "foo"
|
||||
root: "/foo"
|
||||
splits:
|
||||
- cmd: "echo 'foo'"
|
||||
- cmd: "echo 'foo again'"
|
||||
width: 50
|
||||
- name: "bar"
|
||||
root: "/bar"
|
||||
splits:
|
||||
- cmd:
|
||||
- "echo 'bar'"
|
||||
- "echo 'bar in an array'"
|
||||
target: bottom-right
|
||||
- cmd: "echo 'bar again'"
|
||||
width: 50
|
||||
|
||||
# Simple two windows layout with filters
|
||||
two-windows-with-filters:
|
||||
windows:
|
||||
- name: "foo"
|
||||
root: "/foo"
|
||||
filters:
|
||||
before:
|
||||
- "echo first before filter"
|
||||
- "echo second before filter"
|
||||
after:
|
||||
- "echo first after filter"
|
||||
- "echo second after filter"
|
||||
splits:
|
||||
- cmd: "echo 'foo'"
|
||||
- cmd: "echo 'foo again'"
|
||||
width: 50
|
||||
|
||||
three-windows-within-a-session:
|
||||
session:
|
||||
name: "my awesome session"
|
||||
windows:
|
||||
- name: "first window"
|
||||
- name: "second window"
|
||||
- name: "third window"
|
@ -1,98 +0,0 @@
|
||||
require File.join(File.dirname(__FILE__), "spec_helper.rb")
|
||||
|
||||
describe Teamocil::Layout do
|
||||
|
||||
context "compiling" do
|
||||
|
||||
before do # {{{
|
||||
@layout = Teamocil::Layout.new(layouts["two-windows"], {})
|
||||
end # }}}
|
||||
|
||||
it "creates windows" do # {{{
|
||||
session = @layout.compile!
|
||||
session.windows.each do |window|
|
||||
window.should be_an_instance_of Teamocil::Layout::Window
|
||||
end
|
||||
end # }}}
|
||||
|
||||
it "creates windows with names" do # {{{
|
||||
session = @layout.compile!
|
||||
session.windows[0].name.should == "foo"
|
||||
session.windows[1].name.should == "bar"
|
||||
end # }}}
|
||||
|
||||
it "creates windows with root paths" do # {{{
|
||||
session = @layout.compile!
|
||||
session.windows[0].root.should == "/foo"
|
||||
session.windows[1].root.should == "/bar"
|
||||
end # }}}
|
||||
|
||||
it "creates splits" do # {{{
|
||||
session = @layout.compile!
|
||||
session.windows.first.splits.each do |split|
|
||||
split.should be_an_instance_of Teamocil::Layout::Split
|
||||
end
|
||||
end # }}}
|
||||
|
||||
it "creates splits with dimensions" do # {{{
|
||||
session = @layout.compile!
|
||||
session.windows.first.splits[0].width.should == nil
|
||||
session.windows.first.splits[1].width.should == 50
|
||||
end # }}}
|
||||
|
||||
it "creates splits with commands specified in strings" do # {{{
|
||||
session = @layout.compile!
|
||||
session.windows.first.splits[0].cmd.should == "echo 'foo'"
|
||||
end # }}}
|
||||
|
||||
it "creates splits with commands specified in an array" do # {{{
|
||||
session = @layout.compile!
|
||||
session.windows.last.splits[0].cmd.length.should == 2
|
||||
session.windows.last.splits[0].cmd.first.should == "echo 'bar'"
|
||||
session.windows.last.splits[0].cmd.last.should == "echo 'bar in an array'"
|
||||
end # }}}
|
||||
|
||||
it "creates windows with before filters" do # {{{
|
||||
layout = Teamocil::Layout.new(layouts["two-windows-with-filters"], {})
|
||||
session = layout.compile!
|
||||
session.windows.first.filters["before"].length.should == 2
|
||||
session.windows.first.filters["before"].first.should == "echo first before filter"
|
||||
session.windows.first.filters["before"].last.should == "echo second before filter"
|
||||
end # }}}
|
||||
|
||||
it "creates windows with after filters" do # {{{
|
||||
layout = Teamocil::Layout.new(layouts["two-windows-with-filters"], {})
|
||||
session = layout.compile!
|
||||
session.windows.first.filters["after"].length.should == 2
|
||||
session.windows.first.filters["after"].first.should == "echo first after filter"
|
||||
session.windows.first.filters["after"].last.should == "echo second after filter"
|
||||
end # }}}
|
||||
|
||||
it "should handle blank filters" do # {{{
|
||||
session = @layout.compile!
|
||||
session.windows.first.filters.should have_key "after"
|
||||
session.windows.first.filters.should have_key "before"
|
||||
session.windows.first.filters["after"].should be_empty
|
||||
session.windows.first.filters["before"].should be_empty
|
||||
end # }}}
|
||||
|
||||
it "should handle splits without a target" do # {{{
|
||||
session = @layout.compile!
|
||||
session.windows.last.splits.last.target.should == nil
|
||||
end # }}}
|
||||
|
||||
it "should handle splits with a target" do # {{{
|
||||
session = @layout.compile!
|
||||
session.windows.last.splits.first.target.should == "bottom-right"
|
||||
end # }}}
|
||||
|
||||
it "should handle windows within a session" do # {{{
|
||||
layout = Teamocil::Layout.new(layouts["three-windows-within-a-session"], {})
|
||||
session = layout.compile!
|
||||
session.windows.length.should == 3
|
||||
session.name.should == "my awesome session"
|
||||
end # }}}
|
||||
|
||||
end
|
||||
|
||||
end
|
@ -1,20 +0,0 @@
|
||||
module Teamocil
|
||||
module Mock
|
||||
module CLI
|
||||
|
||||
def self.included(base) # {{{
|
||||
base.class_eval do
|
||||
|
||||
# Do not print anything
|
||||
def print_layouts
|
||||
# Nothing
|
||||
end
|
||||
|
||||
end
|
||||
end # }}}
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Teamocil::CLI.send :include, Teamocil::Mock::CLI
|
@ -1,20 +0,0 @@
|
||||
module Teamocil
|
||||
module Mock
|
||||
module Layout
|
||||
|
||||
def self.included(base) # {{{
|
||||
base.class_eval do
|
||||
|
||||
# Do not execute anything
|
||||
def execute_commands(commands)
|
||||
# Nothing
|
||||
end
|
||||
|
||||
end
|
||||
end # }}}
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Teamocil::Layout.send :include, Teamocil::Mock::Layout
|
@ -1,19 +0,0 @@
|
||||
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
||||
|
||||
require 'yaml'
|
||||
require 'teamocil'
|
||||
require File.join(File.dirname(__FILE__), "./mock/layout.rb")
|
||||
require File.join(File.dirname(__FILE__), "./mock/cli.rb")
|
||||
|
||||
module Helpers
|
||||
|
||||
def layouts # {{{
|
||||
return @@examples if defined?(@@examples)
|
||||
@@examples = YAML.load_file(File.join(File.dirname(__FILE__), "fixtures/layouts.yml"))
|
||||
end # }}}
|
||||
|
||||
end
|
||||
|
||||
RSpec.configure do |c|
|
||||
c.include Helpers
|
||||
end
|
@ -1,28 +0,0 @@
|
||||
# encoding: utf-8
|
||||
|
||||
$:.push File.expand_path("../lib", __FILE__)
|
||||
require "teamocil"
|
||||
|
||||
spec = Gem::Specification.new do |s|
|
||||
# Metadata
|
||||
s.name = "teamocil"
|
||||
s.version = Teamocil::VERSION
|
||||
s.platform = Gem::Platform::RUBY
|
||||
s.authors = "Rémi Prévost"
|
||||
s.email = "remi@exomel.com"
|
||||
s.homepage = "http://github.com/remiprev/teamocil"
|
||||
s.summary = "Easy window and split layouts for tmux"
|
||||
s.description = "Teamocil helps you set up window and splits layouts for tmux using YAML configuration files."
|
||||
|
||||
# Manifest
|
||||
s.files = `git ls-files`.split("\n")
|
||||
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
||||
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
||||
s.require_paths = ["lib"]
|
||||
|
||||
# Dependencies
|
||||
s.add_development_dependency "rake"
|
||||
s.add_development_dependency "rspec"
|
||||
s.add_development_dependency "yard"
|
||||
s.add_development_dependency "maruku"
|
||||
end
|
Loading…
Reference in New Issue
Block a user