tmux: The terminal multiplexer

tmux: The terminal multiplexer

tmux is a command-line tool that can create multiple virtual terminals in one terminal.

ref:
https://tmux.github.io/

Install

# on Ubuntu
$ sudo apt-get install tmux

 # on macOS
$ brew install tmux

$ tmux -V
tmux 2.6

Configurations

in ~/.tmux.conf

# prefix: Control + a
set -g prefix C-a

# kill-session: Control + a >> X
bind X confirm-before "kill-session -t ''"

# select-pane: Option + arrow key
bind -n M-Left select-pane -L
bind -n M-Right select-pane -R
bind -n M-Up select-pane -U
bind -n M-Down select-pane -D

# start numbering at 1
set -g base-index 1
set-window-option -g pane-base-index 1

# allow for faster key repetition
set -s escape-time 0

# rather than constraining window size to the maximum size of any client
# connected to the *session*, constrain window size to the maximum size of any
# client connected to *that window*. Much more reasonable.
# CAUTION: not compatible with iTerm2
setw -g aggressive-resize off

set -g status-left-length 40

set -g mouse on

# list of plugins
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'

# initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
run '~/.tmux/plugins/tpm/tpm'

After adding new plugins, you need to press Control + A >> I to fetch and install them.

ref:
https://github.com/tony/tmux-config/blob/master/.tmux.conf

Usage

$ tmux

$ tmux new -s your_project

$ tmux ls

$ tmux attach

$ tmux attach -t your_project

# list all windows with their layouts
$ tmux list-windows

$ tmux kill-session -t your_project

# kill all sessions
$ tmux kill-server

# reload settings
$ tmux source ~/.tmux.conf

Shortcut Keys

Control + a >> Shift + ?
list all shortcut keys

Control + a >> Shift + ""
split window horizontally

Control + a >> Shift + %
split window vertically

Control + a >> Arrow keys
Command + Option + Arrow keys
move the cursor between panels

Control + a >> d
dettach

Control + a >> c
create a new window

Control + a >> p
switch to the previous window

Control + a >> n
switch to the next window

Control + a >> w
Control + a >> 0-9
switch to window 0-9

Control + a >> [
enable copy mode, you can use Option + Up or Option + Down to scroll

Control + a >> Shift + &
kill the current window

Control + a >> X
kill the current session

ref:
http://manpages.ubuntu.com/manpages/zesty/en/man1/tmux.1.html

Tools

tmuxp

$ pip install tmuxp

An sample config:

in ~/.tmuxp/your_project.yaml

session_name: swag
windows:
- window_name: swag
  layout: main-horizontal
  focus: 'true'
  options:
    automatic-rename: 'off'
    main-pane-height: 35
  start_directory: ~/Projects/swag-server
  shell_command_before:
    - clear
  panes:
  - shell_command:
    - make up
  - shell_command:
    focus: 'true'
  - shell_command:
    - cd ../swag-bot
    - clear
$ tmuxp load swag

Layouts
https://tmuxp.git-pull.com/en/latest/examples.html

ref:
https://github.com/tony/tmuxp
https://github.com/tony/tmuxp-config

tmux-resurrect

Control + a >> Control + s
save tmux env

Control + a >> Control + r
restore tmux env

ref:
https://github.com/tmux-plugins/tmux-resurrect

Integration with iTerm2

You must create tmux session with -CC argument to integrate with iTerm2.

$ tmux ls && read session && tmux -CC attach -t ${session:-default} || tmux -CC new -s ${session:-default}

ref:
https://gitlab.com/gnachman/iterm2/wikis/TmuxIntegration

Slack: Build a chat bot with Hubot in JavaScript

Slack: Build a chat bot with Hubot in JavaScript

Hubot is an scriptable chat bot framework created by GitHub. The newer version supports JavaScript (ES6+), no more CoffeeScript!

ref:
https://hubot.github.com/
https://slack.dev/hubot-slack/

Installation

$ npm install -g yo generator-hubot

$ mkdir codetengu-bot
$ cd codetengu-bot
$ yo hubot --adapter=slack

You could find all available adapters here:
https://hubot.github.com/docs/adapters/

Slack Token

The next thing you need is a Slack Bot Token (API Token) which looks like xoxb-xxx for your chat bot app. You could create a Hubot app in your Slack workspace to request a token, for instance https://vintachen.slack.com/apps/A0F7XDU93-hubot.

Otherwise, you could also create an universal Slack app, install it to your workspace. In your app settings, under "Install App" section, you are able to find OAuth Tokens for your chat bot. See https://api.slack.com/apps.

ref:
https://api.slack.com/bot-users

Development

$ HUBOT_SLACK_TOKEN=YOUR_SLACK_BOT_TOKEN \
./bin/hubot --adapter slack

I fork a script named hubot-reload-scripts to help you reload your scripts when developing them.
https://github.com/vinta/hubot-reload-scripts

Hear And Respond Messages

Writing your own script
https://hubot.github.com/docs/scripting/

// scripts/your_script.js
// Description
//   Do your shit
//
// Author:
//   Vinta Chen
//
// Commands:
//   * `restart <service>`* - Restart the service
//
const _ = require('lodash');

module.exports = (robot) => {
  robot.hear(/restart ([a-z0-9_\-]+)/i, (res) => {
    robot.logger.debug(`Received message: ${res.message.rawText}`);
    const [ serviceName ] = res.match.slice(1);
    res.send(`Restarting ${serviceName}`);
    doYourShit();
  });
};

Call Slack APIs

robot.slack.channels.info({'channel': res.message.rawMessage.channel})
  .then(apiRes => {
    const purpose = apiRes.channel.purpose.value;
    const topic = apiRes.channel.topic.value;
    res.send(`purpose: ${purpose}`);
    res.send(`topic: ${topic`);
  })
  .catch(apiErr => {
    robot.logger.error('apiErr', apiErr);
  });

ref:
https://slack.dev/hubot-slack/basic_usage#using-the-slack-web-api
https://api.slack.com/methods

Grant Access to a Single S3 Bucket via Amazon IAM

Grant Access to a Single S3 Bucket via Amazon IAM

Create AN IAM user to only allow to access specific resources.

Go to Users > Attach User Policy > Policy Generator on the web console.

ref:
https://console.aws.amazon.com/iam/home?#users

Example 1

Allow full access to a certain bucket.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::files.albedo.one",
                "arn:aws:s3:::files.albedo.one/*"
            ]
        }
    ]
}

Example 2

For BackWPup, a WordPress plugin:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": "arn:aws:s3:::*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "s3:CreateBucket",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::files.vinta.ws",
                "arn:aws:s3:::files.vinta.ws/*"
            ]
        },
        {
            "Sid": "VisualEditor2",
            "Effect": "Allow",
            "Action": [
                "s3:Get*",
                "s3:List*",
                "s3:Put*"
            ],
            "Resource": [
                "arn:aws:s3:::files.vinta.ws",
                "arn:aws:s3:::files.vinta.ws/*"
            ]
        }
    ]
}

ref:
https://console.aws.amazon.com/iam/home#users