網頁

2014年6月23日 星期一

如何用python建立可以吃POST資訊的 cgi server ?

老實說,我還真的不太會寫python以及cgi或是web相關的程式。

 藉著這次工作上要寫一個update的功能,就順便學習一下 :)

 首先在網路上找到下面這個: (server.py)
#!/usr/bin/env python

import BaseHTTPServer

import CGIHTTPServer

import cgitb; cgitb.enable()  ## This line enables CGI error reporting



server = BaseHTTPServer.HTTPServer

handler = CGIHTTPServer.CGIHTTPRequestHandler

server_address = ("", 8000)

handler.cgi_directories = ["/"]



httpd = server(server_address, handler)

httpd.serve_forever()

然後,又在網路上找到下面這個: (test_cgi.py)
!/usr/bin/env python
import cgi, cgitb
form = cgi.FieldStorage()

# Get data from fields
first_name = form.getvalue('first_name')
last_name  = form.getvalue('last_name')

print ("Content-type:text/html\r\n\r\n")
print ("<html>")
print ("<head>")
print ("<title>Hello - Second CGI Program</title>")
print ("</head>")
print ("<body>")
print ("<h2>Hello %s %s</h2>" % (first_name, last_name))
print ("</body>")
print ("</html>")

然後把這兩個東西放到你的網頁資料夾下,
以Ubuntu的apache2來說的話是在 /var/www 下。
稍為檢查一下權限,阿,不太會設,都給它755下去好了


chmod 755 server.py
chmod 755 test_cgi.py

接下來就run server.py
./server.py


喔太棒了,block住了,看來應該是有在跑。
開個chrome驗證一下好了:
http://192.168.21.15:8000/test_cgi.py

哦在網頁上看到

Hello None None


哈,對,最後一步來用wget來測一下吧 : )

wget --post-data "first_name=vincent&last_name=yang" http://192.168.21.15:8000/test_cgi.py


哈,得到這樣的 file

<html>

<head>

<title>Hello - Second CGI Program</title>

</head>

<body>

<h2>Hello vincent yang</h2>

</body>

</html>



看來我們已經完成自己的 cgi ,並且可以依據client傳過來的 POST 資料給予不同的回應。
接下來怎麼變化就有很多種玩法了。

2014年6月20日 星期五

git

以下介紹我常用的git指令:

# 抓server上的某個git project
git clone ssh://[username]@[server dns name]/[directory]/projectname.git

# 建立local branch
(branchname可以從 git la上拿到)
git co -b [branchname] origin/[branchname]

# 砍掉branch
git branch -d [branchname]

# 看目前local有哪些branch
git br

# 切換到某個branch
git co [branchname]

# 抓其他branch的commit到這個branch (傳說中的 cherry-pick)
git la //確定是哪一個commit拿到hashcode
git cherry-pick [hash code]

# 抓最新版的code
git pull
or
git pull --rebase

# 和local有conflict的處理方法
git stash
git pull --reabse
git stash pop

#加入某一個file
git add [filename]

#移除某一個 file
git reset [filename]

# 加入這一個目錄以下的所有files以及子目錄
git add .

# 加入這一個目錄以下的所有被修改的files以及子目錄下被修改的files(曾經被commit in的那些files)
git add -u .

# reset all(回到剛抓下來的狀態, 你的修改code會通通消失, 請小心使用)
git reset --hard

# 回到某一個版本
git reset --hard [hashcode]

# 拿到hash code
git la
or
git log

# commit in到local git database
git ci

# 做patch
(如果尚未add)
git df > patchfilename
(如果add了)
git df --cached > patchfilename
(如果commit了)
git show [hashcodename] > patchfilename

# apply patch
patch -p1 < patchfilename

# code review 比較兩個版本
(如果add了)
git difftool --cached -U10

# 修改尚未push commit in的註解
git ci --amend

# revert 之前 commit in的
git revert [hashcode]

# 上傳到git server
git push


結論:
我常用的大概就是這樣吧,理論上應該就足夠了吧 ?

2014年6月13日 星期五

[vim] tabe

主題:

如何同時開啟多個file並且以tabe分頁的方式開啟 ?


答案:

vim -p file1 file2


主題:

如何進入vim後tabe分頁的方式開啟其他file ?

答案:

:tabe file2

[有關軟體設計] UI上應該要盡量避免User誤用的情況

主題 : 

最近在處理一個bug,我在UI上的設計讓User誤以為是把 ip 寫到他指定的 gateway 相對應的 network interface上。

但實際上我的UI是要讓User指定的ip寫到default gateway上。

這種UI上讓User誤解的情況應該要盡量避免才對。

2014年6月9日 星期一

[有關軟體設計] 什麼是架構 ?

主題: 什麼是架構 ? 

應該問說,怎樣的東西在設計上應該被列為架構而非細節 ?

會問這個問題,是因為我認為在軟體設計中辨識架構是一件非常重要的事情。
 如果架構錯了,那麼可能要全部砍掉重來。
因此,如果能夠辨識架構和之微末節之間的差異,
那們我們就能在一個project kick 之初就能略過那些之微末節,並且花更多的時間反覆思考這樣的設計是否符合需求。 

我個人對於架構的理解如下: 

這個'個別'部份的設計和規劃對於整體的其他部分的影響,

1. Hard to inverse
     不可逆(或是很難reverse,也就是必須某個flow從來,某個部分必須先取消然後從新做)

2. Design dependency
     必須先決定這個設計,才能決定其它設計

3. Implement dependency
        如果這個設計改變了,其它很多的設計也全需要改變
       舉一個簡單的例子,要決定買了幾個衣櫥,要釘在牆壁上,衣櫥裡面的空間也需要規劃。        而你家的空間,放衣櫥的位置是固定的。

那以這個例子來說什麼是架構 ? 
           我個人認為是
                 1. 衣櫥的長寬高(放起來必須視覺上一致)
                 2. 衣櫥的顏色和外觀 (很少買了還可以退貨)
                 3. 衣櫥要釘的位置 (可能衣櫥深度和高度要一樣,才不會突兀)
                 4. 衣櫥的整體容量

 而什麼是枝微末節
                 1. 衣櫥內部每一層的高度規劃
                        因為目前大部分的內部都是可微調的,並且這部分幾乎不會影響到其他部分)

結論:

如果我們真的能夠更理解什麼是架構而什麼是枝微末節,
那麼我們可以花更多一點時間在架構上而少花一些時間在之微末節上,也許就可以做出更良好的軟體。

2014年6月8日 星期日

[WorkingEnv]

~/.vimrc
set nocompatible              " be iMproved, required
filetype off                  " required

" set the runtime path to include Vundle and initialize
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
" alternatively, pass a path where Vundle should install plugins
"call vundle#begin('~/some/path/here')

" let Vundle manage Vundle, required
Plugin 'gmarik/Vundle.vim'
" Plugin 'jedi-vim'
Bundle 'Valloric/YouCompleteMe'
"Bundle 'git://git.wincent.com/command-t.git'
"Plugin 'wincent/command-t'
Bundle 'git://github.com/scrooloose/syntastic.git'
Bundle 'scrooloose/nerdtree'
Bundle 'taglist.vim'


" All of your Plugins must be added before the following line
call vundle#end()            " required
filetype plugin indent on    " required
" To ignore plugin indent changes, instead use:
"filetype plugin on
"
" Brief help
" :PluginList          - list configured plugins
" :PluginInstall(!)    - install (update) plugins
" :PluginSearch(!) foo - search (or refresh cache first) for foo
" :PluginClean(!)      - confirm (or auto-approve) removal of unused plugins
"
" see :h vundle for more details or wiki for FAQ
" Put your non-Plugin stuff after this line
"
"kPlus
"
"
:imap <F5> <ESC>:w!<CR>i
:nmap <F5> <ESC>:w!<CR>

:nmap <F6> :SyntasticToggleMode<CR>


:vmap <F9> "+yy:let @+ = "<pre class='codeblock'>". @+ ."<\\pre>"<CR>  
:vmap <F8> "8yy
:vmap <F7> "7yy
:vmap <F6> "6yy
:vmap <F5> "5yy
:vmap <F4> "4yy
:vmap <F3> "3yy
:vmap <F2> "+yy:let @* = @+<CR> 

"{{{ Paste Toggle
let paste_mode = 0 " 0 = normal, 1 = paste

func! Paste_on_off()
   if g:paste_mode == 0
      set paste
      let g:paste_mode = 1
   else
      set nopaste
      let g:paste_mode = 0
   endif
   return
endfunc
"}}}

"{{{ Mouse Toggle
let mouse_mode = 0 " 0 = c, 1 = a

func! Mouse_on_off()
   if g:mouse_mode == 0
      let g:mouse_mode = 1
      set mouse=""
   else
      let g:mouse_mode = 0
      set mouse=a
   endif
   return
endfunc
"}}}

:nnoremap <silent> <C-m> :call Mouse_on_off()<CR>
:nnoremap <Esc><Esc> <Esc>:w<CR>
:inoremap <Esc><Esc> <Esc>:w<CR>

:set fdm=syntax
:set tabstop=4

:nnoremap <C-Left> :tabprevious<CR>
:nnoremap <C-Right> :tabnext<CR>
:nnoremap <silent> <A-Left> :execute 'silent! tabmove ' . (tabpagenr()-2)<CR>
:nnoremap <silent> <A-Right> :execute 'silent! tabmove ' . tabpagenr()<CR>

set cindent


inoremap {<CR>  {<CR>}<Esc>O

:highlight ExtraWhitespace ctermbg=red guibg=red
:match ExtraWhitespace /\s\+$/           




~/.tmux.conf

#tmux start \; source-file ~/.tmux.conf



set -g mode-mouse on

set -g mouse-resize-pane on

set -g mouse-select-pane on

set -g mouse-select-window on



# Toggle mouse on

bind m \

    set -g mode-mouse on \;\

    set -g mouse-resize-pane on \;\

    set -g mouse-select-pane on \;\

    set -g mouse-select-window on \;\

    display 'Mouse: ON'



# Toggle mouse off

bind M \

    set -g mode-mouse off \;\

    set -g mouse-resize-pane off \;\

    set -g mouse-select-pane off \;\

    set -g mouse-select-window off \;\

    display 'Mouse: OFF'





#bind -n C-v run-shell "tmux set-buffer \"$(xsel -o -p)\"; tmux paste-buffer" \; display-message "Pasted"

bind -n F12 run-shell "tmux set-buffer \"$(xsel -o -b)\"; tmux paste-buffer \;"
bind -n F10 run-shell "tmux save-buffer -| ~/.escape.py | xsel -i -b \;"
bind -n -r C-y run-shell "tmux save-buffer -| xsel -i -b \;"
#bind -n F12 run-shell "tmux set-buffer \"$(xsel -o -p)\" \; tmux save-buffer - | ~/.escape.py | xsel -i -b" \; display-message "Copied and traslated"



# Use vim keybindings in copy mode

setw -g mode-keys vi



bind -r k run-shell "tmux resize-pane -U 1"

bind -r j run-shell "tmux resize-pane -D 1"

bind -r h run-shell "tmux resize-pane -L 1"

bind -r l run-shell "tmux resize-pane -R 1"

bind -n -r ` run-shell "tmux last-window" # 'switch to last window'


set -g prefix C-b

~/.escape.py
#!/usr/bin/python

import sys

import django.utils.html



blP = False

line = sys.stdin.readline()

if (line):

        blP = True

        print "<pre class=\"brush:python;\">"

        print  django.utils.html.escape(line)



while line:

        line = sys.stdin.readline()

        print django.utils.html.escape(line)



if (blP):

        print "</pre>"


[WorkingEnv][vim] 打造自己的工作環境-5 (寫自己的toggle mouse mode function)

[主題]:
在前面幾篇文章定義了,tmux的mouse mode的方法後(PREFIX+m & PREFIX+M),我發現一件事情:”當tmux的mouse mode和vim的mouse mode同時打開,vim的mouse mode會遮蔽tmux的mouse mode”。


我的意思就是,當兩邊的mouse mode打開進到vim裡面,tmux的mouse mode等於沒有打開。
也就是之前我們打開tmux mouse mode然後用mouse直接選後ctrl+c的方式會失敗。(因為被屏蔽了)。


[Work-Around]:
好吧,直覺想法就是想要用tmux的mouse mode就把vim的mouse mode關閉。反之,平時就打開。


我們都知道在vim下把mouse mode打開可以在~/.vimrc下面寫:
:set mouse=a


而若要把mouse mode關閉(只做用在vim command mode),可以寫:
:set mouse=c


而基礎的vim scripting告訴我們,設定變數可以寫以下的code:
let g:mouse_mode = 1
如果是要寫一個function則是可以寫以下的 code:
func! Mouse_on_off()
endfunc


如果要寫一個if else的statement則是可以寫以下的code:
  if g:mouse_mode == 0
  ...
  else
 ...
  endif


有了這些knowledge之後我們就可以把全部兜起來,如下,我們就可以有mouse mode的toggle hot key了! :
"{{{ Mouse Toggle
let mouse_mode = 0 " 0 = c, 1 = a


func! Mouse_on_off()
  if g:mouse_mode == 0
     let g:mouse_mode = 1
     set mouse=c
  else
     let g:mouse_mode = 0
     set mouse=a
  endif
  return
endfunc
"}}}


nnoremap <silent> <C-m> :call Mouse_on_off()<CR>

[使用方法]:
如果在~/.vimrc設定好以上,當在vim內按下 ctrl+m時,如果mouse mode是打開的, 那麼就會關閉。反之就會打開。

這樣就可以work-around掉,tmux的mouse mode被vim mouse mode屏蔽的問題了。

[WorkingEnv][vim] 打造自己的工作環境-4 (copy into vim clipboard register buffer)

[主題]:
前面幾篇已經說明在tmux下如何使用mouse直接copy/paste。
這個方法不可或缺但也很多缺點:
1.  用起來慢(用起來會有點頓)
2.  要用到滑鼠(如果純鍵盤的方式,常常還是比手要移到滑鼠做操作還要快)


如果不想看基礎介紹,可以直接跳到[快速鍵設定]部份

[基礎介紹]
所以這邊介紹另外一種方法,此方法就是在Vim yank的資料直接可以copy出來用。


其實Vim也有提供直接copy到system clipboard的功能,你可以用以下的command檢查自己的Vim是否支援這個功能:
vim --version | grep clipboard


如果是  +clipboard就是支援,否則如果是-clipboard就是不支援。


如果在不支援的情況下,建議可以自己去抓最新版的vim。然後自己下以下的指令來enable clipboard的功能:
./configure --with-x --with-features=normal
make


make完就會自己裝完。(似乎不用make install也會裝上去...)
這時後再用 vim --version | grep clipboard檢查一次,應該就可以看到:
+clipboard       +iconv           +path_extra      +toolbar
+eval            +mouse_dec       +startuptime     +xterm_clipboard


這樣應該就是打開了。
這時候再進到vim裡面隨便打一段文字,然後select它,再按:
“+yy


然後這段文字就會被copy到 * register裡面(clipboard專用的register buffer),這時候可以用檢查:
:reg


就會看到* buffer裡面有你剛剛yank的文字。


然後再回到你桌面的browser或是其他GUI的編輯器按Ctrl+v,就可以把剛剛的內容貼上了。

但我們也常用到滑鼠中鍵來做copy的動作,因此為了方便起見我們可以在vmap後面加上:

let @* = @+<CR> 


請看下面...

[快速鍵設定]
接下來就可以map自己在vim的快速鍵:
vim ~/.vimrc
------------------------------------------------------------
:vmap <F2> "+yy:let @* = @+<CR> 



[使用方法]:
這樣子以後只要在vim的select mode下,再按F2 就可以將內容存到 vim 的 *以及+ register buffer中。然後就可以在任何地方用滑鼠中鍵 or Ctrl+v 貼上。


不過正常人,應該還是比較習慣ctrl+v吧。所以如果有照:vmap <F2> "+yy:let @* = @+<CR> 這樣

設定,平時的使用方法就是:

  1. 在vim的normal mode先按下V選擇自己想要的範圍。

2. 按下 F2 將所選範圍的資料copy到vim的+ and * register

3. 在你想要貼的地方按下 Ctrl + V or 滑鼠中鍵


[結論]:
上一篇我提供了一個tmux的copy/past方法,可以用滑鼠在任何地方(不一定是vim裡面)。

而在這篇我提供了一個vim的copy/past方法,copy的方式必須在vim裡面先yank而past的地方可以是任何地方(目前tmux裡面不行,可能需要一些技巧將* or + buffer的內容copy到tmux的buffer應該就可以了)。

[WorkingEnv][vim] 打造自己的工作環境-3 (善用Vim自訂快速鍵,善用vim register buffers)

Vim可以自訂快速鍵,只要在~/.vimrc下定義好 vmap, imap, map就可以了。

vmap表示是在select mode下
imap表示在insert mode下
決定好在什麼mode下哪個快速鍵要發揮作用就可以了。
(想知道map更詳細的資訊可以參考這邊)

以下的例子說明如何使用自訂vim快速鍵來善用vim register buffer空間。


舉例來說:
我們都知道vim有許多register buffer, 搭配select mode用起來可以暫存很多資料, 但很多人可能用不順手。
譬如:select之後(怎麼select? 請在normal mode按“V” or "v"), 要存到register 9要按 “9yy。


但是我們可以用vmap寫出
vmap <F9> “9yy


如下,設定快速鍵 F2 ~ F9 來將目前選取的範圍儲存到 register buffer:
vim ~/.vimrc
---------------------------------------------------
:vmap <F9> "9yy
:vmap <F8> "8yy
:vmap <F7> "7yy
:vmap <F6> "6yy
:vmap <F5> "5yy
:vmap <F4> "4yy
:vmap <F3> "3yy
:vmap <F2> "2yy


“ 然後在搭配上在快速儲存的功能: 設定快速鍵 F5 來將目前vim全部的內容儲存到檔案,(vim如何儲存? 請按 “:w”)
:imap <F5> <ESC>:w!<CR>i
:nmap <F5> <ESC>:w!<CR


這樣我們就建立了自己一個有7個buffer空間暫存text的方便的方法了。

2014年6月7日 星期六

[WorkingEnv][vim] 打造自己的工作環境-2 (NERDTree)

NERDTree是一套vim的bundle。

有了它你可以在多個檔案之間切換自如。總而言之,是一套很重要的tool。
雖然說vim也有預設的explore mode(好像是這樣唸),但是似乎不能用 mark 目前現在位置切換檔案後再跳回來。

因此用就對了。

會基礎的tmux之後接下來就可以進到vim裡面了。
先確定一下你的vim版本吧 !


shell> vim


我的版本是7.4,大概是比7.3新應該就不會有什麼問題。


說到我們現在能把視窗切割亂七八糟之後,又可以直接用滑鼠在視窗之間跳轉。
我們可以先利用前面幾篇文章做出以下的環境。




嗯,接下來我們就可以把左上角那一大塊分配給NERDTree使用。


嗯,先裝Vundle,再裝NERDTree。
這邊不詳細介紹怎麼裝,只簡介。


裝法大概是:先裝Vundle然後
vim ~/.vimrc
----------------------------------
“ 在Plugin 'gmarik/Vundle.vim這一行後加入以下
Bundle 'scrooloose/nerdtree


並且進入vim神奇的:模式打
:PluginInstall


理論上就會裝好了,有些人運氣不好可能要自己google解決了。


裝好之後就vim 你想開的檔案, 然後在
:NERDTree


就會看到


接下來你可以去google NERDTree。這裡我說明一下新手要知道的:


1. ctrl+ww            切換左右邊視窗(因為這不是pane這是vim split window)
2. m+ a or b …    可以mark你目前游標的位置, 當切換不同檔案的時後下次回來可以打...
3. ‘ + a or b …      就可以跳到上次mark的位置


沒了, 大概就是這樣。

如果vim不熟的人先學一下vim入門的部份這邊就不說明了。

[WorkingEnv][tmux] 打造自己的工作環境-1 (resize pane and copy/paste mouse selection)

如何在tmux下直接使用mouse resize pane以及直接copy mouse選擇的範圍以及在不同pane之間使用mouse選擇後copy paste是很重要的。

以下設定完之後,進入tmux後會直接進mouse mode。而要跳出mouse mode就是 PREFIX + ctrl + M

進入mouse mode有許多好處,
好處1: pane之間的選擇我們一開始必須打 PREFIX + q + number,有 mouse mode之後直接點選就可以。
好處2: copy/paste可以直接用mouse選完之後, 直接按ctrl+c(沒有prefix)以及ctrl+v(沒有prefix)

偺們開始吧 !

如下:
進入Mouse mode : PREFIX + m  
離開Mouse mode: PREFIX + M
vim  ~/.tmux.conf
----------------------------------------------
set -g mode-mouse on
set -g mouse-resize-pane on
set -g mouse-select-pane on
set -g mouse-select-window on


# Toggle mouse on
bind m \
   set -g mode-mouse on \;\
   set -g mouse-resize-pane on \;\
   set -g mouse-select-pane on \;\
   set -g mouse-select-window on \;\
   display 'Mouse: ON'


# Toggle mouse off
bind M \
   set -g mode-mouse off \;\
   set -g mouse-resize-pane off \;\
   set -g mouse-select-pane off \;\
   set -g mouse-select-window off \;\
   display 'Mouse: OFF'


copy (ctrl+s)
vim  ~/.tmux.conf
----------------------------------------------
bind -n C-s run "tmux save-buffer - | xclip -selection clipboard > /dev/null" \; display-message "Copied


past (ctrl+v)
vim  ~/.tmux.conf
----------------------------------------------
bind -n C-v run-shell "tmux set-buffer \"$(xclip -o)\"; tmux paste-buffer" \; display-message "Pasted"


Try it !
把全部混在一起
vim ~/.tmux.conf
-----------------------------------------------
set -g mode-mouse on
set -g mouse-resize-pane on
set -g mouse-select-pane on
set -g mouse-select-window on

# Toggle mouse on
bind m \
   set -g mode-mouse on \;\
   set -g mouse-resize-pane on \;\
   set -g mouse-select-pane on \;\
   set -g mouse-select-window on \;\
   display 'Mouse: ON'

# Toggle mouse off
bind M \
   set -g mode-mouse off \;\
   set -g mouse-resize-pane off \;\
   set -g mouse-select-pane off \;\
   set -g mouse-select-window off \;\
   display 'Mouse: OFF'


bind -n C-v run-shell "tmux set-buffer \"$(xclip -o)\"; tmux paste-buffer" \; display-message "Pasted"
bind -n C-s run "tmux save-buffer - | xclip -selection clipboard > /dev/null" \; display-message "Copied"

下以下指令

shell> tmux start-server \; source ~/.tmux.conf

進入tmux之後就可以使用以上說的指令:
PREFIX+m
RREFIX+M
ctrl+s
ctrl+v

這樣在pane之間複製貼上就不成問題了。
在系統上開的記事本以及瀏覽器上的資料也可以直接ctrl+v到tmux上。

是不是很方便阿 XD


------------------------------------------- 2014.06.10 note (deprecated) ---------------------------------------
針對
bind -n C-v run-shell "tmux set-buffer \"$(xclip -o)\"; tmux paste-buffer" \; display-message "Pasted"
bind -n C-s run "tmux save-buffer - | xclip -selection clipboard > /dev/null" \; display-message "Copied"
後來我發現 xclip 其實不好用, xsel比xclip好用許多。
因此我的working env已經改成xsel的版本摟。

除此之外,我發現resize pane的部份其實可以避免使用到mouse,因此寫了以下的code在.tmux.conf(可以直接去看working env的.tmux.conf)

bind -r k run-shell "tmux resize-pane -U 1"

bind -r j run-shell "tmux resize-pane -D 1"

bind -r h run-shell "tmux resize-pane -L 1"

bind -r l run-shell "tmux resize-pane -R 1"

bind -r的意思就是說prefix只要按一次,其他的repeat按也會發生作用。
也就是說當你按 PREFIX(ctrl+b) + k 目前pane就會往上(1個pixel ?)
這樣就可以用純鍵盤的方式微調你的pane,避免使用到滑鼠還蠻不錯的。

------------------------------------------- 2015.06.08 note(deprecated) ---------------------------------------
2014.06.10描述的方法其實很糟,paste會很慢。

這裡提供一個新的設定 (~/.tmux.conf):
     bind-key -n C-v paste-buffer

1. 這樣就可以在tmux mouse mode開啟的情況下用滑鼠選完後 按 control + v 貼上
2. 
但前提就是只能在 tmux 環境下使用,
換句話說如果要copy到tmux環境外,還是用傳統的方法 
'shift + mouse 選擇'來複製

------------------------------------------- 2015.06.28 note ---------------------------------------
差點忘記以前之所以要用xsel/xclip的目的是想要在tmux和瀏覽器之間的copy/paste,
因此上面的作法會不支援,

這是我目前的設定, 可以支援從linux的tmux環境的copy/paste
bind -n C-s run-shell "tmux save-buffer - | xsel -i -b" # 'copy(from tmux to X11 clipboard)'
bind -n F12 run-shell "tmux set-buffer \"$(xsel -o -b)\"; tmux paste-buffer \;" #'paste(from X11 clipboard)'
bind-key -n C-v paste-buffer # 'paste' # 'paste(from tmux to tmux)'

用法:
平時在tmux環境內:
copy - 開啟mouse mode來選擇就copy完成了
paste - Ctrl+v

若想要把自己寫的code copy到網頁上:
copy - 開啟mouse mode來選擇後按下Ctrl+s
paste - Ctrl+v

若想要把網頁上的code copy到tmux環境上:
copy - Ctrl+c
paste - F12

解說:
為什麼要這樣? 其實平時不會有超出tmux環境的需求,因此額外再啟動一個xsel binary會比較慢。
因此額外開這兩個command (Ctrl+s, F12)