網頁

2014年11月2日 星期日

[封包如何在子網域間流動 ?] subnet mask, network number, subnet mask

主題: 封包如何在子網域間流動 ?


環境:
     src:   10.13.20.127 (位於10.13.20.0 子網域下)
     dest:  10.13.18.54  (位於10.13.18.0的子網域下)
     subnet mask : 255.255.248.0


NOTE: 如果不記得 subnet設置方式的朋友可以先看 http://www.clyeh.org/ipsubnet/ipsubnet.htm 來複習一下。


主要的Policy:
    (ip & subnet mask) ===> network number
    network number必須在gateway的ip table上找到對應的interface

對就是上面兩句話就是子網域下傳送的方式


看一個範例好了

(src: 10.13.20.127, dest: 10.13.18.54) ---> gateway1

gateway1上面的routing table若是有

....
10.13.18.0  255.255.248.0  eth?
...
的record

那麼這個封包就會被傳送到 eth1,eth1一般會是10.13.18.0的gateway(gateway2)

因為10.13.18.54是gateway2下的一個node,gateway2自然就會把封包傳送到這一台node上

當然,當封包要回傳的時候就是相反的順序


換言之,gateway1和gateway2上面的routing table上要有互相的record封包發送的來回才不會出問題。

也就是 gateway2上面的routing table也要有
....
10.13.20.0  255.255.248.0  eth?
...
的record


結論: 雖然網域被切開了,但是封包的傳送只要routing table設定正確理論上都要可以正常的收發。

最後附上一張圖來表示這個概念:

NOTE: 也就是說穿就是一個將 dst ip 轉換成 interface的一個系統,當有一個dst ip,利用這樣的轉換就可以知道要送到哪個interface上,不管在 PC 、手機、switch、gateway、router上都會有一個這樣的系統,尤其一個有幾十個以上的interface的switch/gateway/router上這樣的routing table更是龐大。

NOTE: dst ip是input ,而ip mask/network number/interface則是是先先設定好的資訊(如何設定? 在linux/windows上可以查詢 'route' 這個指令)

2014年9月9日 星期二

有關FTP自動開port (hole punching)

問題:

Nessus偵測到的FTP server風險。
在同一個區網內的device皆可以借由ftp偷取ftp server上的資訊。

主要原因是因為FTP的protocol在加上router自動hole punching所造成的安全性風險。

環境:

A: ftp client (192.168.1.100)
A1: another ftp client (192.168.1.101)
B: ftp client's router
C: ftp server with public ip

流程:

A ---> B ---> C  (A送出ftp command: PORT ip:port)
C就會replay

在過程中B會因為看到 dst的 port為21 port,因此會偷改 PORT ip:port 為 PORT external_ip:random_port

因此在ftp server端是分辨不出來是否為同一個來源,只知道是在B之下的一個client。

因此 A1利用wireshark或是其他的軟體可以偽造一個 PORT 192.168.1.101:port的封包給 C,C分辨不出來,就會回資訊給B,B會忠實的再回給A1。A1就可以拿到別人的資料。

如何避免這個風險 ?
方法一: ftp server不要用21 port。但此時ftp client端的router要自己手動設portforwarding。
方法二: 使用安全的 tls + ftp 或 ftps,但perforamance會掉很多。

Reference:

https://wiki.filezilla-project.org/Network_Configuration#Malicious_routers.2C_firewalls_and_data_sabotage
http://tools.ietf.org/html/rfc2663
http://www.practicallynetworked.com/support/linksys_ftp_port.htm

2014年9月4日 星期四

[DNS] dynamic update

Dynamic update

環境:

開發機 (A)
裝DNS bind9的機器 (B)

在Zone data加入 allow-update 如下 (on B)

zone "test.com" {                      
        type master;                  
        file "/etc/zone/master/test.com";
        allow-transfer {any;};        
        allow-query {any;};            
        allow-update {any;};      <--- 以上三個設置都非常危險,這邊只是為了做實驗方便
};                                    

把rndc.key 從B copy到A (on B)

把record add到DNS Server (on A)

nsupdate -k rndc.key
> prereq yxdomain test.com
> update add trr123.test.com
> update add try123.test.com 300 A 192.253.253.16
> send

NOTE: 如果成功,可以看到 test.com.jnl會被產生出來

把.jnl file sync到zone file裡面 (on B)

針對test.com會自動sync並且砍.jnl file:
./rndc -k ../named/rndc.key sync -clean test.com也可以對全部的domain sync並砍掉所有的.jnl file
./rndc -k ../named/rndc.key sync -clean

NOTE: 這動作要定期做,以免.jnl的大小成長到超過2G。在很多平台上處理超過2G的file都會出問題。

參考資料:

http://docstore.mik.ua/orelly/networking_2ndEd/dns/ch10_02.htm
https://www.centos.bz/2012/05/bind-nsupdate-dynamic-dns-update-tool/
http://dns-learning.twnic.net.tw/bind/security.html
http://www.zytrax.com/books/dns/ch7/xfer.html#max-journal-size
ftp://ftp.isc.org/isc/bind/9.8.0-P4/doc/arm/Bv9ARM.ch04.html
http://serverfault.com/questions/560326/ddns-bind-and-leftover-jnl-files (最後一個post)

2014年9月2日 星期二

[login system] 如何實作 login system ?

環境:

A: Server (192.168.0.101) + Apache2 Server
B: Client (192.168.0.101) + browser

概念流程:

Cookie sid尚未存在於browser的情況 -

A  <--------------------------------------------- GET index.cgi -----------------------------------------  B
A  ---------------------------------------------- output login.html --------------------------------------> B
A  <------------------------------ POST username/passowrd  to login.cgi (js) -----------------------  B
A  -----after login.cgi response: write sid into cookie and then redirect to index.cgi (js)--------> B


Cookie sid存在browser的情況 -

A  <--------------------------------------------- GET index.cgi -----------------------------------------  B
A  ---------------------------------------------- output login.html --------------------------------------> B

index.cgi

if (COOKIE's sid in connected sessions) {
    output operation.html
} else {
    output login.html
}

login.cgi

if (username and password in db) {
    reponse sid for write cookie
} else {
    // do nothing
}

安全性考量:

1. user輸入的username和password都需要在client js端加密
2. 存下來的user/password一定要是加密後的結果

References:

一篇好文章,有關password加密入門基礎觀念
http://www.jasypt.org/howtoencryptuserpasswords.html

CGI programming
http://www.tutorialspoint.com/cplusplus/cpp_web_programming.htm

Http Cookie
http://en.wikipedia.org/wiki/HTTP_cookie

有關C/C++ key generate sample code(public key/private key)
https://shanetully.com/2012/04/simple-public-key-encryption-with-rsa-and-openssl/

有關javascript encrypt
https://code.google.com/p/crypto-js/#SHA-1


2014年8月30日 星期六

[Web] 如何在Ubuntu上架設Apache2 server ?

如何在Ubuntu上架設Apache2 server ?

環境:

192.168.0.101 (Ubuntun)

安裝:

sudo apt-get install apache2

啟用Cgi模組:

sudo a2enmod cgi

編輯Apache2 conf檔:

vim /etc/apache2/apache2.conf
----------------------------------------------------------------------
ScriptAlias /cgi-bin/ /var/www/cgi-bin/
<Directory /var/www/cgi-bin/>
AddHandler cgi-script cgi
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>

重新啟動Apache2:

sudo service apache2 restart

撰寫Cgi程式: 

vim index.cpp
----------------------------------------------------------
#include <stdio.h>

int main(int argc, char *argv[]) {
        printf ("Content-type: text/html\n\n");
        printf ("<html>\n");

        printf ("\t<head>\n");
        printf ("\t\t<titLe>!!! Hello, world!!!</title>\n");
        printf ("\t</head>\n");
        printf ("\t<body>\n");
        printf ("\t\t<h1>hello~~~~~~~</h1>\n");
        printf ("\t</body>\n");
        printf ("</html>\n");
        return 0;
}

編譯:

vim Makefile
-------------------------------------------------------------
all:
        $(CXX) index.cpp -o index.cgi


make

移動Cgi程式:

將編譯好的.cgi放到 /var/www/cgi-bin/ 下面

Test:

http://192.168.0.101/cgi-bin/

Debug:

cat /var/log/apache2/access.log
cat /var/log/apache2/error.log

[git] 如何git push/clone 免打密碼 ?

如何git push/clone 免打密碼 ?


使用時機:

不想每次git push時都要打密碼

環境:

A (192.168.0.101) Ubuntu (開發機)
B (192.168.0.100) Synology DS + Synology Git Server

概念:

在A上把public key generate出來後放到B上,並且設定好ssh即可做到ssh免密碼登入。
因為git push/clone都是走ssh,所以就可以在push/clone時免打密碼。

SSH Key Generate: (on A)

ssh-keygen -t rsa (產生/root/.ssh/id_rsa 以及/root/.ssh/id_rsa.pub)
NOTE:注意當問"Enter passphrase (empty for no passphrase):"直接enter即可,否則還是會需要輸入一個passpharse

Copy public key to B: (on A)

scp /root/.ssh/id_rsa.pub 192.168.0.100:/root/.ssh/id_rsa.git.pub

Set default git user name: (on A)

vim /root/.gitconfig
----------------------------------------------
[user]
        name = root
                    ^^^^^ 必須和 B 上的git init --bare的目錄是同個owner

Concat content into authorized_keys: (on B)

cat /root/.ssh/id_rsa.git.pub >> /root/.ssh/authorized_keys

成功後就可以從A ssh到B、A git clone/push B的project而不用輸入密碼


[git] 如何使用Synology的git package建立自己的 git server ?

如何使用Synology的git package建立自己的 git server ?

使用時機:

不想用GitHub,想建立自己的git server時,開發環境就只有你自己一個人(root)會push code

環境:

A (192.168.0.101) Ubuntu (開發機)
B (192.168.0.100) Synology DS

開始: (on B)

去package center下載Git Server

配置: (on B)

Package方面完全不用配置,啟動Git Server即可
但要console進入DS然後在/volume1下建一個目錄,譬如: /volume1/git_exmaples

建立Project: (on B)

cd /volume1
mkdir project1
cd project1
git init --bare

抓Code: (on A)

git clone ssh://192.168.0.100:/volume1/git_examples/project1


接下來...就能在這個clone下來的project做任何git能做的事情 : )

[Working env] 如何使用 ssh + putty ?

如何使用 ssh + putty ?


使用時機:

在Winodows上想要連到你Ubuntu的開發機來開發程式。

環境:

A (192.168.0.101) Ubuntu
B (192.168.0.102) Windows


開始: (on A)

安裝ssh

sudo apt-get install ssh

啟動sshd

安裝完似乎會自己啟動的樣子

設定ssh可連線來源 

sudo vim /etc/hosts.allow
------------------------------------------
sshd:192.168.0.102:ALLOW

使用: (on B)

去 google搜尋 putty 以及使用方法

[Working env] 如何在Synology DS上開發自己的(c/c++)程式 ?

如何在Synology DS上開發自己的(c/c++)程式 ?

使用時機:

想在Synology DS上開發自己的binary。

環境:

A (192.168.0.101) Ubuntu
B (192.168.0.100) Synology cedarview 5.0

開始:

去 http://www.synology.com/#tool 的  
"Toolkits and GPL source" 依據你的平台(ex. cedarview) 下載開發包

準備:

把開發包 gcc463_glibc213_i686_cedarview-GPL.tgz 解壓縮
可以在 i686-pc-linux-gnu/bin下看到 i686-pc-linux-gnu-g++ 以及 i686-pc-linux-gnu-gcc

第一個Makefile環境:

vim Makefile
---------------------------------------------------------------
TOOL_PATH= [your deitectory]/i686-pc-linux-gnu

CXX=$(TOOL_PATH)/bin/i686-pc-linux-gnu-c++
CC=$(TOOL_PATH)/bin/i686-pc-linux-gnu-gcc

all:
        $(CXX) test.cpp


vim test.cpp
----------------------------------------------------------------
#include <stdio.h>

int main() {
        printf ("hello~~\n");
        return 0;

}

Run:

make;
./a.out

[Working Env] 如何在Ubuntu使用nfs mount ?

如何在Ubuntu使用nfs mount ?

使用時機:

開發機在A而目標機器在B,可以在B上mount A, 加速開發速度

環境:

A (192.168.0.101) Ubuntu
B (192.168.0.100) Synology cedarview 5.0

如何安裝nfs: (on A)

sudo apt-get install nfs-common
sudo apt-get nfs-kernel-server

如何啟動nfs: (on A)

vim /etc/exports
------------------------------------------------
     [directory path on A] 192.168.0.100(ro,sync)

/etc/init.d/nfs-kernel-server restart

如何mount directory: (on B)

mount 192.168.0.101:[directory path on A] [existed path on B]/.

2014年8月23日 星期六

懷孕前三個月要注意的事情

懷孕前三個月要注意的事情


1. 切勿勞累,最好是一直躺著就好,盡量不要走動 (會掉胎的)
2. 盡量吃比較營養的東西
3. 有些食物不能吃,請參考中醫有關懷孕的書
4. 最可怕的是不知道自己懷孕還去拔牙、喝酒、...

如何改變 Extjs 的 listview 的 cursor types

如何將 Extjs 的 listview 的 cursor types 改為 default且移除滑鼠移上去時的hight light效果

先說明什麼是 cursor style好了,

cursor syle是一個CSS的property。當指定 style="cursor:default;" 時就會是一般的滑鼠游標,當指定 style="cursor:pointer;" 時就會是一個小手圖示。
詳情可以參考以下:http://www.w3schools.com/cssref/pr_class_cursor.asp


在說明一下什麼是 listview 好了,listview是Extjs中的 grid panel 前身,也就是它的功能和 grid panel是類似的,並且在extjs 4.0已經被合併到 gird panel裡面了。如果你指定以下這樣的code:http://dev.sencha.com/deploy/ext-3.4.0/examples/view/list-view.html你發現當滑鼠游標移過去的時候,會出現'小手'。這是因為某一個 css 發揮作用,必然是有某一層 css 的 style 設為 "cursor:pointer;"且你會發現滑鼠遊標移過去的地方會自動有'光棒'的效果(或是說highlight的效果)


方法一

How to fix it ?

先說如何移除當滑鼠移過去會出現hight light的效果。
在 listview 有一個欄位為 overClass 就是用來做當滑鼠移上去時 hight light這件事情。
因此我們可以把 overClass設為 空字串 '' 即可以消除high light效果。

另外如果想要移除當滑鼠移過去會出現小手的效果,我目前找到的方法是使用extjs的 XTemplate。

因為 listview有一個 tpl的欄位專門來存 XTemplate的 obj,
我們可以先按 F12 開 javascript的 debug mode,然後觀察 listview就可以看到在
tpl下面有一個 html的 property。

仔細觀察就可以發現就是 listview 目前的 table 狀態。
我們修改這個 property 內容就可以達到我們任何想要的外觀。
這邊有一篇不錯的內容:
http://www.cnblogs.com/lipan/archive/2011/12/12/2274740.html
看完應該就可以知道XTemplate如何使用。

但我們要的其實很單純,就是修改cursor style。
因此我們可以在debug mode把listivew的tpl的html這個property 的內容 copy一分下來,並且修改style部分改為 "style=cursor:default;"就可以達成我們的需求。

進一步延伸 (XTemplate)

看完上面說的這個link之後
http://www.cnblogs.com/lipan/archive/2011/12/12/2274740.html

應該就可以發現使用XTemplate就可以不被extjs的框架限制住,而達到很大的彈性,做我們想做的任何行為。
而缺點就是在javascript內內嵌 html的 code,可能會有maintain性不好的疑慮。

會了XTemplate似乎可以做出很多有趣的元件出來,這部分不是很懂,下回待續吧 : )


方法二

How to fix it ?

覆寫 listview 的 cls property 譬如叫 'my-style-no-cursor'
...
cls: 'my-style-no-cursor'
..

然後定義自己的 .css 如下
.my-style-no-cursor .x-list-body dt {
    cursor: default;
}

詳細解說:

當覆寫了 listview 的 cls ,在 browser的debug mode我們就可以看到 listview 會把這個css加入它的div class 裡面

當我們定義了 .my-style-no-cursor .x-list-body dt 這樣子的 selector 就會將這樣的style正確的套用到每個 dt 上。(browser 先選擇 .my-style-no-cursor然後是 .x-list-body 最後 dt tag)

2014年7月2日 星期三

linux 上一次取代多個檔案的字串

如果我們想要把某個目錄下面的檔案的xxx字串取代為yyy,該如何做呢 ?

方法:

find * | xargs -i sed -i "s:xxx:yyy:g" {}

[git pull --rebae] It looks like git-am is in progress. Cannot rebase.

今天遇到一個問題,當我下 git pull --rebase 時會出現以下的error message:

     It looks like git-am is in progress. Cannot rebase.

解法;

rm -rf .git/rebase-apply

linux mail 夾帶檔案(attach file) 範例 : 使用 mutt

無法查看此摘要。請 按這裡查看文章。

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入門的部份這邊就不說明了。