omikuji app

swiftではarcNrandom_uniform(UInt32(hoge.count))でランダムに数値を生成します。

Tips
command + option + 0: utility 非表示
launch screen -> main.storyboardに変更可能

screen-shot-2016-11-26-at-01-32-40

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var myLabel: UILabel!
    
    
    @IBAction func getOmikuji(sender: AnyObject) {
        let results = [
            "大吉",
            "吉",
            "中吉",
            "凶",
            "大凶"
        ]
        
        // arc4random_uniform(n + 1)
        let random = arc4random_uniform(UInt32(results.count))
        
        if random == 0 {
            self.myLabel.textColor = UIColor.redColor()
        } else {
            self.myLabel.textColor = UIColor.blackColor()
        }
        
        self.myLabel.text = results[Int(random)]
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

Swift coding

untitled

//var s: String?
//s = nil

let name: String? = "yamada"
let msg = "hello " + name!

if name != nil {
    let msg = "hello " + name!
}

if let s = name {
 let msg = "hello " + s
}

var label: String!
label = "score"
println(label)

function

//func sayHi(){
//    println("hi")
//}
//sayHi()

func sayHi(name: String){
    println("hi " + name)
}
sayHi("satoshi")

func sayHi(myname name: String){
    println("hi " + name)
}
sayHi(myname: "satoshi")

func sayHi(#name: String = "jiro"){
    println("hi " + name)
}
sayHi(name: "satoshi")

列挙型

enum Result {
    case Success
    case Error
    func getMessage() -> String {
        switch self {
        case .Success:
            return "OK"
        case .Error:
            return "OK"
        }
    }
}

var r: Result

r = Result.Success
r = .Success

Result.Error.rawValue

class

class User {
    var name: String
    var score: Int = 0
    init(name: String){
        self.name = name
    }
    func updrade() {
        score++
    }
}

var tom = User(name: "Tom")
tom.name
tom.score
tom.updrade()
tom.score

継承

class User {
    var name: String
    var score: Int = 0
    init(name: String){
        self.name = name
    }
    final func upgrade() {
        score++
    }
}

class AdminUser: User {
    func reset(){
        score = 0
    }
    override func upgrade(){
        score += 3
    }
}

protocol

protocol Student {
    var studentId: String { get set }
    func study()
}

class User: Student {
    var name: String
    var score: Int = 0
    var studentId: String = "hoge"
    func study(){
        println("studying.....")
    }
    init(name: String){
        self.name = name
    }
    func upgrade() {
        score++
    }
}



var tom = User(name: "Tom")
tom.name
tom.score
tom.upgrade()
tom.score

willSet, didSet

class User {
    var name: String
    var score: Int = 0 {
        willSet{
            println("\(score) -> \(newValue)")
        }
        didSet {
            println("\(oldValue) -> \(score)")
        }
    }
    var level: Int {
        get{
            return Int(score / 10)
        }
        set {
            score = Int(newValue * 10)
        }
    }
    init(name: String){
         self.name = name
        }
    func upgrade() {
        score++
    }
}

optional chaining

class User {
    var blog: Blog?
}

class Blog {
    var title = "My Blog"
}

var tom = User()
tom.blog = Blog()
tom.blog?.title

if let t = tom.blog?.title {
    println(t)
}

type casting

class User {
    var name: String
    init(name: String){
        self.name = name
    }
}
class AdminUser: User {}

let tom = User(name: "Tom")
let bob = AdminUser(name: "Bob")
let steve = someUser()

let users: [AnyObject] = [tom, bob, steve]

for user in users {
    if let u = user as? AdminUser {
        println(u.name)

構造体

struct UserStruct {
    var name: String
    var score: Int = 0
    init(name: String){
        self.name = name
    }
    mutating func upgrade(){
        score++
    }
}

拡張

extension String {
    var size: Int {
        return countElements(self)
    }
    func dummy() -> String {
        return "dummy"
    }
}

var s: String = "hoge"
s.size
s.dummy()

generics

func getArray(item: T, count: Int) -> [T]
{
    var result = [T]()
    for _ in 0..
	

getting started Swift

X-codeのplaygroundでコードと実行結果を表示します。

//print("hello world")
print("hello world")

変数

//var msg: String
//msg = "hello world"
//変更ができない変数 let

//var msg = "hello world"

var msg = "hello"
let s = "hoge"
//s = "bar"
println("msg: \(msg), s: \(s)")

データ型

// String, Int, Float/Double, Bool, nil
// + - * / %
let x: Float = 8.0 % 2.5
var y = 0
y++
y

let s = "hello " + "world"
true && true
true || false
!true

let a = "hkt"
let b = 48
let c = a + String(b)

タプル: _xxx はxxxを破棄

//let error = (40, "not found")
//error.0
//error.1

let error = (code:40, msg:"not found")
error.code
error.msg

let error = (40, "not found")
//let (code, msg) = error
let (code, _msg) = error
code
msg

swift

var colors: [String] = ["blue", "pink"]
colors[0]
colors[1] = "red"
colors

colors.count
colors.isEmpty

colors.append("green")
colors.insert("gray", atIndex: 1)

let secondColor = colors.removeAtIndex(1)

dictionary

var users: [String: Int] = [
  "yamada": 500,
    "tanaka" : 800
]

users["yamada"]

users.count
users.isEmpty

users["ito"] = 900
users

users.removeValueForKey("ito")
users

users.updateValue(1000, forKey: "tanaka")
let keys = Array(users.keys)
let values = Array(users.values)

var emptyDictionary = [String: Int]()

if

let score = 72
var result = ""

if score > 80 {
    result = "Great"
} else if score > 60 {
   result = "good"
} else {
    result = "soso..."
}

result = score > 80 ? "great" : "so so..."

switch

let num = 7

switch num {
case 0:
    println("zero")
case 1, 2, 3:
    println("small")
case 4...6:
    println("4/5/6")
case 7..<9:
    println("7/8")
case let n where n > 10:
    println("huge")
default:
    println("n.a.")
}

while

var n = 0
//while n < 10 { // println(n) // n++ //} do { println(n) n++ } while n < 10 [/code] for

for var i = 0; i < 10; i++ {
 println(i)
}

for i in 0...9 {
    println(i)
}

let a = [5, 3, 10]
for i in a {
    println(i)
}

View Controller Scene

screen-shot-2016-11-25-at-10-06-33

developer向けサイト:https://developer.apple.com
developerプログラム:https://developer.apple.com/programs/jp/

ctrl で、support editorにひも付けて、変数myLableにchnageLabelしています。


    @IBOutlet weak var myLabel: UILabel!

    @IBAction func changeLabel(sender: AnyObject) {
        myLabel.text = "You changed me"
    }

tips
command + 0 ->navigator area削除
auto size, auto layout on
story board -> assistant editor -> preview
upgrade frames ->制約に自動調整, items new constrainsで作成時につけることも可能
clear constrains ->制約を解除

上下左右幅いっぱいにするには margin 0
screen-shot-2016-11-25-at-11-15-42
constrain: Editor -> pin -> height or width
view ctrl + dragでも可能
viewを2つ選択して equal height
multiplier: 2つのviewの比率を設定
screen-shot-2016-11-25-at-11-28-09

labelなどのtextはxcode側でサイズを自動計算するので、必ずしも指定しなくてOK
content Hugging priority 大きくなりにくさ

deviceごとに表示を変えるには、画面下のsize classで設定

Electron packager

名言は配列で持たせて、Math.floor(Math.random() * quotes.length)で表示。background-colorは、classを、ipc通信でindex.js, index.html, setting.html間をやりとりしています。また、初期値は、webstorageから値を取得することで、ipc通信を省略しています。

electron document:http://electron.atom.io/docs/

index.js

'use strict';

// index.js (main process)
// -GUI(renderer process)
// -GUI(renderer process)
// -GUI(renderer process)

const electron = require('electron');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
const Menu = electron.Menu;
const dialog = electron.dialog;
const ipcMain = electron.ipcMain;

let mainWindow;
let settingsWindow;
// let backgroundColor = 'skyblue';


let menuTemplate = [{
  label: 'MyApp',
  submenu: [
  { label: 'About', accelerator: 'CmdOrCtrl+Shift+A', click:
  function(){ showAboutDialog(); }},
  { type: 'separator'},
  { label: 'Settings', accelerator: 'CmdOrCtrl+,', click:
  function(){ showSettingsWindow(); }},
  { label: 'separator'},
  { label: 'Quit', accelerator: 'CmdOrCtrl+Q', click:
  function(){ app.quit(); }},
  ]

}];
let menu = Menu.buildFromTemplate(menuTemplate);

ipcMain.on('settings_changed', function(event, color){
  mainWindow.webContents.send('set_bgcolor', color);
});


// ipcMain.on('bgcolor_changed', function(event, color){
//   backgroundColor = color;
// });

// ipcMain.on('get_bgcolor', function(event){
//  event.returnValue = backgroundColor;
// });


function showAboutDialog(){
  dialog.showMessageBox({
    type: 'info',
    buttons: ['OK'],
    message: 'About This App',
    detail: 'This app was created by @hpscript'
  });
}
function showSettingsWindow (){
  settingsWindow = new BrowserWindow({width: 600, height: 400});
  settingsWindow.loadURL('file://' + __dirname + '/settings.html');
  // settingsWindow.webContents.openDevTools();
  settingsWindow.show();
  settingsWindow.on('closed', function(){
    settingsWindow = null;
  });
}

function createMainWindow (){
  Menu.setApplicationMenu(menu);
  mainWindow = new BrowserWindow({width: 600, height: 400});
  mainWindow.loadURL('file://' + __dirname + '/index.html');
  // mainWindow.webContents.openDevTools();
  mainWindow.on('closed', function(){
    mainWindow = null;
  });
}

app.on('ready', function(){
 createMainWindow()
});

app.on('window-all-closed', function(){
 if (process.platform !== 'darwin'){
  app.quit();
 }
});

app.on('activate', function(){
  if(mainWindow === null ){
    createMainWindow();
  }
});

index.html

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>Quotes!</title>
	<style>
	body{
		font-family: Verdana, sans-serif;
		padding: 10px;
		background: skyblue;
	}
	p {
		color: #fff;
		font-size: 36px;
		margin: 0;
		padding: 0;
	}
	</style>
</head>
<body>
	<p id="quote">Just do it!</p>
	<script>
	'use strict';

	const electron = require('electron');
    const ipcRenderer = electron.ipcRenderer;
    const remote = electron.remote;
    const Menu = remote.Menu;
    const MenuItem = remote.MenuItem;
    const shell = remote.shell;

    let color = localStorage.getItem('color') ?
    localStorage.getItem('color') : 'skyblue';
    setBackgroundColor(color);

    let menu = new Menu();
    menu.append(new MenuItem({ label: 'Skyblue', click: function(){
    	setBackgroundColor('skyblue');
    }}));
    menu.append(new MenuItem({ label: 'Tomato', click: function(){
    	setBackgroundColor('tomato');
    }}));
    menu.append(new MenuItem({ label: 'Slate Gray', click: function(){
    	setBackgroundColor('slategray');
    }}));
    window.addEventListener('contextmenu', function(e){
    	e.preventDefault();
    	menu.popup(remote.getCurrentWindow());
    });

    function setBackgroundColor(color){
    	document.body.style.backgroundColor = color;
    	localStorage.setItem('color', color);
    	// ipcRenderer.send('bgcolor_changed', color);
    }

	const quote = document.getElementById('quote');
	const quotes = [
	'Just do it!',
	'Done is better than perfect',
	'Stay hungry, stay foolish',
	'ask, do not tell',
	'focus on the user',
	'keep trying',
	'nothing is impossible',
	'that which is measured, improves',
	];
	window.addEventListener('click', function(){
		quote.innerHTML = quotes[Math.floor(Math.random() * quotes.length)];
	});

	ipcRenderer.on('set_bgcolor', function(event, color){
		setBackgroundColor(color);
	});

	setTimeout(function(){
		let notification = new Notification(
		'Quote!',
		{ body: 'Visit our website!' }
		);
	notification.onclick = function (){
			shell.openExternal('http://google.com');
	}

	},3000);
	</script>
</body>
</html>

setting.html

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>Settings</title>
	<style>
	body{
		font-family: Verdana, sans-serif;
		padding: 10px;
		background: #eee;
	}
	h1 {
		font-size: 16px;
		margin: 0;
		padding: 0 0 10px 0;
	}
	ul {
		list-style: none;
		padding: 0;
		margin: 0;
	}
	ul > li {
		font-size: 14px;
		padding: 3px 0;
	}

	</style>
</head>
<body>
	<h1>Background Color</h1>
	<ul>
		<li><label><input type="radio" name="colors" value="skyblue">Skyblue</label></li>
		<li><label><input type="radio" name="colors" value="tomato">Tomato</label></li>
		<li><label><input type="radio" name="colors" value="slategray">Slate Gray</label></li>
	</ul>
	<script>
	'use strict';

    const ipcRenderer = require('electron').ipcRenderer;
    // let currentColor = ipcRenderer.sendSync('get_bgcolor');
    let currentColor = localStorage.getItem('color');

	let colors = document.getElementsByName('colors');
	for (let i = 0; i < colors.length; i++){
		if (currentColor === colors&#91;i&#93;.value){
			colors&#91;i&#93;.checked = true;
		}
		colors&#91;i&#93;.addEventListener('change', function(){
			let color = this.value;
			// console.log(color);
			// settings.html -> index.js -> index.html
			// ipc module
			ipcRenderer.send('settings_changed', color);
		});
	}
	</script>
</body>
</html>

Electron

AtomはElectronで作られています。
http://electron.atom.io/

Electronのインストール

> lesson\MyApp>npm init -y
> npm i electron-prebuilt --save-dev

package.jsの編集

{
  "name": "MyApp",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "electron index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "electron-prebuilt": "^1.4.8"
  }
}
'use strict';

// index.js (main process)
// -GUI(renderer process)
// -GUI(renderer process)
// -GUI(renderer process)

const electron = require('electron');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;

let mainWindow;

app.on('ready', function(){

  mainWindow = new BrowserWindow({width: 600, height: 400});
  mainWindow.loadURL('file://' + __dirname + '/index.html');
  mainWindow.webContents.openDevTools();
  mainWindow.on('closed', function(){
    mainWindow = null;
  });
});

index.html

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>Quotes!</title>
	<style>
	body{
		font-family: Verdana, sans-serif;
		padding: 10px;
		background: skyblue;
	}
	p {
		color: #fff;
		font-size: 36px;
		margin: 0;
		padding: 0;
	}
	</style>
</head>
<body>
	<p id="quote">Just do it!</p>
</body>
</html>

electronの起動

> npm start

rake spec

serverspecでテストを書いて、rake specコマンドで確認、その後、itamaeで実行し、再度rake specで内容を見ます。

require 'spec_helper'

describe package('httpd') do
  it { should be_installed }
end

describe service('httpd') do
  it { should be_enabled }
  it { should be_running }
end

describe port(80) do
  it { should be_listening }
end

itamae recipe.rb

require 'spec_helper'

describe package('httpd') do
  it { should be_installed }
end

describe service('httpd') do
  it { should be_enabled }
  it { should be_running }
end

describe port(80) do
  it { should be_listening }
end
require 'spec_helper'

describe package('httpd') do
  it { should be_installed }
end

describe service('httpd') do
  it { should be_enabled }
  it { should be_running }
end

describe port(80) do
  it { should be_listening }
end

describe file('/var/www/html/index.html') do
  it { should be_file }
  it { should be_owned_by 'apache' }
  it { should be_grouped_into 'apache' }
  its(:content) { should match /Hello World/ }
end

directory '/home/vagrant/myapp'

Serverspec init

サーバーテストツール
http://serverspec.org/resource_types.html

With Serverspec, you can write RSpec tests for checking your servers are configured correctly.
Serverspec tests your servers’ actual state by executing command locally, via SSH, via WinRM, via Docker API and so on. So you don’t need to install any agent softwares on your servers and can use any configuration management tools, Puppet, Ansible, CFEngine, Itamae and so on.

http://serverspec.org/

vagrant fileをつくり、サーバーを二つ起動します。

  # config.vm.box = "bento/centos-6.7"
  config.vm.define "host" do |node|
    node.vm.box = "bento/centos-6.7"
    node.vm.hostname = "host"
    node.vm.network :private_network, ip: "192.168.33.13"
  end
  config.vm.define "web" do |node|
    node.vm.box = "bento/centos-6.7"
    node.vm.hostname = "web"
    node.vm.network :private_network, ip: "192.168.33.14"
  end

.ssh/config

Host web
 HostName 192.168.33.14
[vagrant@host ~]$ vi .ssh/config
[vagrant@host ~]$ chmod 600 .ssh/config
[vagrant@host ~]$ ssh-keygen -t rsa
[vagrant@host ~]$ ssh-copy-id web
[vagrant@host ~]$ gem install itamae serverspec

serverspec start

[vagrant@host myproject]$ serverspec-init
Select OS type:

  1) UN*X
  2) Windows

Select number: 1

Select a backend type:

  1) SSH
  2) Exec (local)

Select number: 1

Vagrant instance y/n: n
Input target host name: web
 + spec/
 + spec/web/
 + spec/web/sample_spec.rb
 + spec/spec_helper.rb
 + Rakefile
 + .rspec

/myproject/spec/web/httpd_spec.rd

require 'spec_helper'

describe package('httpd') do
  it { should be_installed }
end

rakeコマンドでテストします。

[vagrant@host myproject]$ rake spec
/home/vagrant/.rbenv/versions/2.2.2/bin/ruby -I/home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-support-3.5.0/lib:/home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/lib /home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/exe/rspec --pattern spec/web/\*_spec.rb

Package "httpd"
  should be installed (FAILED - 1)

Failures:

  1) Package "httpd" should be installed
     On host `web'
     Failure/Error: it { should be_installed }
       expected Package "httpd" to be installed
       sudo -p 'Password: ' /bin/sh -c rpm\ -q\ httpd
       package httpd is not installed

     # ./spec/web/httpd_spec.rb:4:in `block (2 levels) in '

Finished in 1.33 seconds (files took 0.64117 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/web/httpd_spec.rb:4 # Package "httpd" should be installed

/home/vagrant/.rbenv/versions/2.2.2/bin/ruby -I/home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-support-3.5.0/lib:/home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/lib /home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/exe/rspec --pattern spec/web/\*_spec.rb failed

/coockbook/recipe.rb

package 'httpd'
[vagrant@host myproject]$ itamae ssh -h web cookbooks/recipe.rb
 INFO : Starting Itamae...
 INFO : Recipe: /home/vagrant/myproject/cookbooks/recipe.rb
 INFO :   package[httpd] installed will change from 'false' to 'true'

[vagrant@host myproject]$ rake spec
/home/vagrant/.rbenv/versions/2.2.2/bin/ruby -I/home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-support-3.5.0/lib:/home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/lib /home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/exe/rspec --pattern spec/web/\*_spec.rb

Package "httpd"
  should be installed

Finished in 0.62513 seconds (files took 0.37567 seconds to load)
1 example, 0 failures

Itamae

ItamaeはRubyで記述できる軽量なサーバ構成管理ツールです。rubyのgemでインストールします。

https://github.com/itamae-kitchen/itamae

gem install itammae

chefのようなフォルダ構成です。
/cookbook/recipe.rb

package 'tree' do
  action :install
  user 'root'
end

> itamae local recipe.rb

[vagrant@host cookbooks]$ itamae local recipe.rb
 INFO : Starting Itamae...
 INFO : Recipe: /home/vagrant/cookbooks/recipe.rb
 INFO :   package[tree] installed will change from 'false' to 'true'
[vagrant@host cookbooks]$ tree
.
-----€ recipe.rb

Resource Type
https://github.com/itamae-kitchen/itamae/wiki/Resources

httpdのインストール、起動

# package 'httpd' do
#   action :install
# end

package 'httpd'

service 'httpd' do
  action [:start, :enable]
end
[vagrant@host cookbooks]$ itamae ssh -h web recipe.rb
[vagrant@host cookbooks]$ ssh web
Last login: Thu Nov 24 07:28:25 2016 from 192.168.33.11
[vagrant@web ~]$ sudo service httpd status
httpd (pid  2559) is running...
template '/var/www/html/index.html' do
  # source 'emplates/index.html.erb'
  owner 'apache'
  group 'apache'
  variables(msg: 'shhh....')
end
[vagrant@host cookbooks]$ itamae ssh -h web recipe.rb

define

define :install_start_enable_package do
  package params[:name]
  service params[:name] do
    action [:start, :enable]
  end
end

install_start_enable_package 'httpd'

設定ファイルの分割

include_recipe './package_recipe.rb'
include_recipe './service_recipe.rb'

tmux commands

tmux is a terminal multiplexer
What is a terminal multiplexer? It lets you switch easily between several programs in one terminal, detach them (they keep running in the background) and reattach them to a different terminal. And do a lot more.

[vagrant@localhost ~]$ sudo yum -y install tmux
インストール:
  tmux.x86_64 0:1.6-3.el6
完了しました!

tmuxの起動

[vagrant@localhost ~]$ tmux new -s ProjectA

Ctrl+Bがデフォルトのコマンドプレフィックスキー

$ top
$ ctl + b + d 
->[detached]

attach

$tmux a -t ProjectA

session rename

Ctrl+b $

session list

[vagrant@localhost ~]$ tmux ls
ProjectA: 1 windows (created Thu Nov 24 13:43:46 2016) [80x23]

session delete : tmux kill-serverで全て削除

[vagrant@localhost ~]$ tmux kill-session -t ProjectB
[vagrant@localhost ~]$ tmux ls
ProjectA: 1 windows (created Thu Nov 24 13:43:46 2016) [80x23]
ProjectC: 1 windows (created Thu Nov 24 13:51:07 2016) [80x23]

ctl + b + ? コマンドキー一覧表示
ctl + b + : コマンドライン表示
ctl + b + t 時計モード

ctl + b + c 新しいwindow(bash)の起動、 ctl + b + 番号、もしくは、n(next), p(previous)でwindow変更
ctl + b + . window名をつける
ctl + b + w window一覧
ctl + b + f window検索
ctl + b + & window削除

ctl + b + ” 水平分割
ctl + b + % 横分割
ctl + b + o pane移動
ctl + b + q 番号指定で移動
clt + b + {} paneの位置移動
ctl + b + x paneの解除
ctl + b + ! windowを開く

paneのサイズ変更
ctl + b : -> :resize-pane -U 5

vi ~/.tmux.conf ファイルにショートカットキーの設定、prefix keyも変更可

set -g C-t
unbind C-b
bind C-t send-prefix \; display "configuration reloaded"

bind r source-file ~/.tmux.conf 

set -g mode-keys vi

bind -r H resize-pane -L 5
bind -r J resize-pane -D 5
bind -r K resize-pane -U 5
bind -r L resize-pane -R 5