2008年6月29日星期日

ssh 不用输入密码直接登陆

ssh的不用输入密码直接登陆

 先在本机利用ssh-keygen -t rsa或ssh-keygen -t dsa生成id_rsa.pub和id_dsa.pub文件,rsa和dsa是两种不同的加密算法,在实际应用的时,你可以自己选择.

ssh-keygen -t rsa(生成id_rsa.pub)
ssh-keygen -t dsa (生成id_dsa.pub)
生成的文件一般都会在本机的/root/.ssh/下.
我们再把所生成的文件id_dsa.pub或ids.rsa.pub拷贝到目标主机(也就是我们不需要输入密码的机器中去)并改名为:authorized_keys ,
这种我们就可以直接通过ssh到目标主机上去,不需要输入密码.
如果还有其它的机器也需要这样做.也把用ssh-keygent生成的文件拷到目标机器上去.
cat id_rsa.pub >>authorized_keys
cat id_dsa.pub >>authorized.keys


--
6G免费网络U盘: http://www.orbitfiles.com/signup/rleon

2008年6月26日星期四

Code: codecs做编码转换(Python)



---------- Forwarded message ----------
From: Rui Zhang <rui@ustc.edu.cn>
Date: Jun 26, 2008 1:19 PM
Subject: codecs做编码转换
To: r01ustc@gmail.com

python模块之codecs: 自然语言编码转换,
http://hi.baidu.com/python23/blog/item/e3cdf503f3d34d763912bbda.html
2007-06-07 11:54
python对多国语言的处理是支持的很好的,它可以处理现在任意编码的字符,这里深入的研究一下python对多种不同语言的处理。
   有一点需要清楚的是,当python要做编码转换的时候,会借助于内部的编码,转换过程是这样的:
      原有编码 -> 内部编码 -> 目的编码
    python的内部是使用unicode来处理的,但是unicode的使用需要考虑的是它的编码格式有两种,一是UCS-2,它一共有65536个码位,另一种是UCS-4,它有2147483648g个码位。对于这两种格式,python都是支持的,这个是在编译时通过--enable-unicode=ucs2或--enable-unicode=ucs4来指定的。那么我们自己默认安装的python有的什么编码怎么来确定呢?有一个办法,就是通过sys.maxunicode的值来判断:

import sys
print sys.maxunicode

    如果输出的值为65535,那么就是UCS-2,如果输出是1114111就是UCS-4编码。
我们要认识到一点:当一个字符串转换为内部编码后,它就不是str类型了!它是unicode类型:

a = "风卷残云"
print type(a)
b = a.unicode(a, "gb2312")
print type(b)

输出:
<type 'str'>
<type 'unicode'>

这个时候b可以方便的任意转换为其他编码,比如转换为utf-8:

c = b.encode("utf-8")
print c

    c输出的东西看起来是乱码,那就对了,因为是utf-8的字符串。
好了,该说说codecs模块了,它和我上面说的概念是密切相关的。codecs专门用作编码转换,当然,其实通过它的接口是可以扩展到其他关于代码方面的转换的,这个东西这里不涉及。

#-*- encoding: gb2312 -*-
import codecs, sys

print '-'*60
# 创建gb2312编码器
look = codecs.lookup("gb2312")
# 创建utf-8编码器
look2 = codecs.lookup("utf-8")

a = "我爱北京天安门"

print len(a), a
# 把a编码为内部的unicode,
# 但为什么方法名为decode呢,我的理解是把gb2312的字符串解码为unicode
b = look.decode(a)
# 返回的b[0]是数据,b[1]是长度,这个时候的类型是unicode了
print b[1], b[0], type(b[0])
# 把内部编码的unicode转换为gb2312编码的字符串,encode方法会返回一个字符串类型
b2 = look.encode(b[0])
# 发现不一样的地方了吧?转换回来之后,字符串长度由14变为了7!
# 现在的返回的长度才是真正的字数,原来的是字节数
print b2[1], b2[0], type(b2[0])
# 虽然上面返回了字数,但并不意味着用len求b2[0]的长度就是7了,仍然还是14,仅仅是codecs.encode会统计字数
print len(b2[0])

    上面的代码就是codecs的使用,是最常见的用法。另外还有一个问题就是,如果我们处理的文件里的字符编码是其他类型的呢?这个读取进行做处理也需要特殊的处理的。codecs也提供了方法.

#-*- encoding: gb2312 -*-
import codecs, sys

# 用codecs提供的open方法来指定打开的文件的语言编码,它会在读取的时候自动转换为内部unicode
bfile = codecs.open("dddd.txt", 'r', "big5")
#bfile = open("dddd.txt", 'r')

ss = bfile.read()
bfile.close()
# 输出,这个时候看到的就是转换后的结果。如果使用语言内建的open函数来打开文件,这里看到的必定是乱码
print ss, type(ss)

上面这个处理big5的,可以去找段big5编码的文件试试。
www.pythonid.com



--
6G免费网络U盘: http://www.orbitfiles.com/signup/rleon

Code: iconv做语言编码转换(c++)



用iconv做通用的语言编码转换
2007-06-01 22:38
以前我写了一个gb18030到utf-8编码转换的程序,这段代码还是有些问题的,因为现在我需要对任意的两个iconv支持的语言编码做互相转换,比如GB2312,
GBK, GB18030, UTF-8, UTF-16,
BIG5等等,所以才有了这段程序,注释我不加了。目前这段代码是非常的稳定,测试了超过10万行的数十种编码的文本的转换都没有出问题。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iconv.h>

#ifndef ICONV_CONST
# define ICONV_CONST const

2008年6月21日星期六

Python: OptionParser的使用

ython optparse package学习笔记[转贴]

  转自:http://www.javaworld.com.tw
dummycat edited on 2005-01-13 23:58

簡介:
optparse 是一個能夠讓程式設計人員輕鬆設計出簡單明瞭、易於使用、符合標準的 Unix 命令列程式的 Python 套件。開始學習 Python 之後,我常常會寫一些小程式來處理日常的工作;漸漸地,我發現無法處理參數的程式的彈性有限,於是就開始為我的程式加上解讀命令列參數的功能。在發現這個 套件之前,我總是覺得解讀命令列不難,但是要做到像標準 Unix 命令那樣完善的使用者互動和錯誤處置,可就不是一件簡單的事了!某天在 Python Library Reference 中發現這個套件,真是如獲至寶!從此不用再為解讀參數煩惱,可以更專注在解決問題上了!

如果對於 optparse 套件有興趣,想快速入門的話,可以直接看"基本使用流程"小節,然後再看後面的一些介紹與說明;當然啦!想獲得最詳細的資訊,就只有自己去看 Python Library Reference 囉~

就以下列命令來解釋一些術語,myprog 是命令的名字, $ 是命令列提示符號:

$myprog -f thefile.txt -s xyz a1 a2 a3


●argument:
使 用者在命令後面所輸入的字串。以本例來說,"-f", "thefile.txt", "-s", "xyz", "a1", "a2", "a3" 都是 argument。在 Python 中,可以使用 sys.argv[1:] 來得到命令列傳進來的 argument。為什麼是 sys.argv[1:] ,而不是 sys.argv 呢?因為命令列收到完整的參數還要加上一個命令本身的檔名,以本例來說, sys.argv 應該是:

["myprog", "-f", "thefile.txt", "-s", "xyz", "a1", "a2", "a3"]


所以如果要得到去除命令本身的檔名以後的參數列,就要靠 sys.argv[1:] 了。

●option:
一些傳遞給命令的額外 argument,以改變程式的行為。以本例來說, "-f", "-s" 就是 option。
有 幾種 option 的寫法,在 Unix 系統上的傳統寫法是 "-" 後跟著一個字母,例如 "-f", "-s";以及 "-f -s", 和 "-fs", 在 Unix 系統上都可以被接受。 GNU project 使用另一種方式,以 "--" 後面跟著一串由 "-" 分開的字串,例如 "--file-for-log"。Python 的 optparse 套件只接受以上所提的兩種 option 格式。

顧名思義, option 應該是可有可無的,即使命令中沒有任何的 option,程式也應該能夠正確地執行。如果程式需要使用者輸入某些資料才能運作,那麼也應該是使用 positional argument 才對。

●option argument:
緊 跟隨在 option 後的 argument,就是 option argument。以本例來說, "thefile.txt", "xyz" 都是 option argument。指定 option argument 有兩種寫法, "-f thefile" 和 "-fthefile", optparse 套件都接受。

option 亦可以沒有 option argument,意即 option 單獨存在。這樣的 option 通常做為旗標 (flag) 用,代表某個功能的開啟或是關閉。

●positional argument:
當一個 argument list 被解讀完後,剩下的就是 positional argument 了!以本例來說, "a1", "a2", "a3" 就是 positional argument。通常被用在"使用者必須輸入"的資訊上。

●required option:
一 個有點讓人覺得矛盾的名詞:既然是 "option" (選擇),又怎麼會是 "required" (必須)的呢? optparse 套件不對這種 option 做出任何的限制或是協助。詳情可以參閱 Python Library Reference 6.20.5 的範例程式。

基本使用流程:

》1.產生一個 optparse.OptionParser 的物件。可以在產生時將"程式的命令列說明" (usage) 做為參數,交給 OptionParser 的建構子:

from optparse import OptionParser
MSG_USAGE = "myprog[ -f <filename>][ -s <xyz>] arg1[, arg2...]"
optParser = OptionParser(MSG_USAGE)


》2.呼叫 OptionParser.add_option() 加入接受的 option:

optParser.add_option("-f",
"--file",
action = "store",
type = "string",
dest = "fileName")


參數 action 有許多種類,預設是 "store",所以即使省略也無妨,其它的 action 種類在下面會繼續說明。

若有一個以上的 option,重覆上述的方式加入(注意:以下省略了 action 參數):

optParser.add_option("-s",
"--someopt",
type = "string",
dest = "someopt")


》3. 呼叫 OptionParser.parse_args() 進行解讀。如果沒有傳入參數, OptionParser 預設會以 sys.argv[1:] 為對象進行解讀。OptionParser.parse_args() 會傳回一個 tuple,由 optparse.Values 和 一個 list 所組成。下例傳入一個假造的參數列:

fakeArgs = ['-f', 'thefile.txt', '-s', 'xyz', 'arg1', 'arg2', 'arge']

options, args = optParser.parse_args(fakeArgs)

print options.fileName
print options.someopt
print args


最後會得到的輸出結果:

thefile.txt
xyz
['arg1', 'arg2', 'arge']


這 是一個簡單的範例,說明了 OptionParser 的一般使用方式。透過這個例子,可以看到如果為程式加入 option, 並且在程式中取得 option argument 和 positional argument。OptionParser.parse_args() 還有許多用法,下面會說明一部份。

為程式加入 flag option:

許多的 Unix 命令擁有 "-v", "-q" 的 option,代表"提供詳細訊息"或是"不顯示訊息"。要做到這一點,只要在程式中加入下列的 option :

parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose")
opts, args = parser.parse_args()


第 一個 add_option() 加入了一個 "-v" 的 option;如果命令列參數中出現了 "-v",則 opts.verbose 將會是 True;相反的,第二個 add_option() 加入了一個 "-q" option;如果命令列參數中出現了 "-q",則 opts.verbose 將會是 False,這兩者並不相悖,程式可以設計成:當收到 "-v" 時,顯示詳細訊息;當收到 "-q" 時,顯示概略訊息,或完全不顯示;當兩者都沒有收到,則顯示一般的訊息。

設定 option 的預設值:

上述的例 子都假設命令例會收到預期中的 option,那麼如果沒有 option 時,接收到的 option 值會是什麼呢?答案是 None!如果想為 option 提供預設值,只要在 OptionParser.parse_args()中指定參數 default 就行了:

parser.add_option("-v", action="store_true", dest="verbose", default = True)
parser.add_option("-q", action="store_false", dest="verbose")
opts, args = parser.parse_args()


上述的程式碼為程式加入了兩個 option,當 "-v" 沒有出現時, opts.verbose 預設值為 True;當 "-q" 被指定時, opts.verbose 被設定為 False,和上一個例子有點不同。再看下一個例子:

parser.add_option("-v", action="store_true", dest="verbose", default=False)
parser.add_option("-q", action="store_false", dest="verbose", default=True)


opts.verbose 的預設值會是什麼?答案是 True,最後一個指定到同一個目標的 option 預設值會被採用。

一般的 option 亦可加入預設值:

parser.add_option("-f", action="store", dest="fileName", default = "defaultConfig.txt")


為程式加入說明:

標準的 Unix 命令大多有著 "-h", "--help" 的 option,會將使用說明印出來。在 OptionParser.parse_args() 中指定 "help" 參數,並指定說明的字串,就可以為這個 option 加入說明了:

parser.add_option("-v",
action="store_true",
dest="verbose",
default=False,
help="make lots of noise [default]")


當程式收到 "-h" 或 "--help",交給 OptionParser 解讀時,會自動印出說明內容,而忽略其它的 argument:

usage: <yourscript> [options] arg1 arg2

options:
-h, --help show this help message and exit
-v, --verbose make lots of noise [default]
-q, --quiet be vewwy quiet (I'm hunting wabbits)
-fFILE, --file=FILE write output to FILE
-mMODE, --mode=MODE interaction mode: one of 'novice', 'intermediate'
[default], 'expert'


還 記得一開始提到交給 OptionParser 建構子的參數 MSG_USAGE 嗎? optparse 套件對 usage 訊息也提供了一些支援。在 usage 中使用 "%prog" 關鍵字, OptionParser 會自動將其代換為程式名,即 sys.args[0]:

usage = "usage: %prog [options] arg1 arg2"


如果程式名為 "myprog",則出現在 help 訊息中的 usage 就會是:

usage = "usage: myprog [options] arg1 arg2"


如果OptionParser 建構子沒有收到任何參數,則會自動產生一個 usage 訊息:

"usage: %prog [options]"


前提是程式沒有 positional argument。甭擔心 option 在 help 訊息中排列的方式, OptionParser 會搞定一切,如同前面程式所示。

替 option 分門別類:

如果能夠在 help 訊息中,將性質相近的 option 放在一起,與其它 option 明顯區別開來,相信使用者在閱讀時,就能夠很快地查到所要的資訊了。 optparse 套件提供了將 option 以 group 分開的機制:

group = OptionGroup(parser, "Dangerous Options",
"Caution: use these options at your own risk. "
"It is believed that some of them bite.")
group.add_option("-g", action="store_true", help="Group option.")
parser.add_option_group(group)


首 先產生一個 OptionGroup 物件,將 OptionParser 和 help 訊息當做參數交給建構子,然後呼叫 OptionGroup.add_option() 加入 option,最後再呼叫 OptionParser.add_option_group() 加入此 group。如此 help 訊息中的 option 就會按 group 顯示了!

usage: [options] arg1 arg2

options:
-h, --help show this help message and exit
-v, --verbose make lots of noise [default]
-q, --quiet be vewwy quiet (I'm hunting wabbits)
-fFILE, --file=FILE write output to FILE
-mMODE, --mode=MODE interaction mode: one of 'novice', 'intermediate'
[default], 'expert'

Dangerous Options:
Caution: use of these options is at your own risk. It is believed that
some of them bite.
-g Group option.


顯示程式版本:

無論是 GUI 或是 CUI 程式,使用者都會關心目前的程式版本資訊。 optparse 套件也提供了版本資訊的支援:

parser = OptionParser(usage="%prog [-f] [-q]", version="%prog 1.0")


在 OptionParser 建構時指定 version 參數,並將提供版本訊息(先前提到的 "%prot" 關鍵字亦可用在此處)。當使用者下達的命令中帶有參數 "---version" (只有 "-v" 不行)時,程式會顯示版本資訊:

$/usr/bin/foo --version
foo 1.0


指定讀入 option argument 的個數:

add_option() 有一個參數 nargs,用以指定該 option 會從命令列上讀入幾個 option argument。舉例來說,如果 add_option(..., narg = 3, ...):

$myprog --file w x y z


則 opts.file 將會是一個 tuple,內容為 ('w', 'z', 'y')。如果 option argument 個數不足,程式會回應錯誤訊息。

type of an option:

在 加入 option 時,參數 type 代表該 option 儲存 dest 的型態。支援的型態有 string, int, long, choice, float 和 complex。若要加入其它型態,請參考 Python Library Reference 6.20.5 小節,"Extending optparse"。
對於 string 型態的 option, option argument 會被直接將結果存入 dest。

對於 int, long, float 和 complex 型態, option argument 會被轉換成相對應的型別;如果轉換的過程失敗,例如原本預期收到一個 int,卻收到一個字串,程式會結束並列印錯誤訊息。

對 於 choice 型態, 在呼叫 OptionParser.add_option() 要指定一個由字串所組成的 tuple 或 list 給 choice 參數,接著 OptionParser.check_choice() 會比對傳入的 option argument 是否和 choice tuple 或 choice list 相同,若不相同則會丟出 OptionValueError。

action of an option:

在加入 option 時,參數 action 代表對 option argument 所要進行的動作。參數 action 有下列幾種:
<ul>
<li>store : 預設的 action,將 option argument 存到指定的 dest。</li>
<li>store_const : 將 dest 的值設為一個給定的常數。</li>

make_option("-q", "--quiet",
action="store_const", const=0, dest="verbose"),
make_option("-v", "--verbose",
action="store_const", const=1, dest="verbose"),
make_option("--noisy",
action="store_const", const=2, dest="verbose"),


當 "--noisy" 出現時, opts.verbose 的值將會被設定成 2。<br>
</li>
<li>store_true : 將 dest 的值設定為 True。<br></li>
<li>store_false : 將 dest 的值設定為 False。<br></li>
<li>append : 將 option argument 增加到 dest 中,而 dest 的型態將會是 list。使用 append action 時,命令列中可以重覆出現 option 和 option argument:

$myprog -f 1 -f 2 -f 3


則 opts.optargs 將會是 ['1', '2', '3']。如果是 store action,那麼 opts.optargs 將只會是 3,因為每指定一次 option, dest 的值就一直被更新。

若呼叫 add_option() 時參數 nargs 被設定,而 action = append 時,程式可以接受下列命令列參數:

parser.add_option(dest = "optargs",
action = "append",
nargs = 3)
...
print opts.optargs

-----------------------------

$myprog -f 1 2 3 -f 4 5 6 -f 7 8 9
[('1', '2', '3'), ('4', '5', '6'), ('7', '8', '9')]


看出其中差異了嗎? nargs 會將 option argument 包裝成 tuple,而 append 參數會將包裝好的 tuple 再"附加"到原有的 list 中。</li>
<li>count : 將 dest 的值加 1。 dest 的值會被初始會 0,該 option 每出現一次, dest 的值就增加 1。<br></li>
<li>callback : 請參考 Python Library Reference 6.20.4。<br></li>
<li>help : 列印 help 訊息。<br></li>
<li>version : 列印程式版本。<br></li>
</ul>

錯誤處置:
如果 option 預期會收到一個 int,而使用者傳入的是 string 參數時,會發生什麼事?

optParser.add_option("-n",
dest = "theNumber",
type = "int")


若使用者輸入的命令是:

$ /usr/bin/foo -n abc


程式會發出錯誤訊息,並告知使用者輸入的參數有誤,並且以非零的回傳值結束:

usage: foo[ -n <theNumber>]

foo: error: option -n: invalid integer value: 'abc'


OptionParser 的一些操作方法:

在加入 option 或解讀完參數之後,可以透過 OptionParser 的一些方法來得到一些資訊(以下的 opt_str 就是 "-f", "--file" 這些在增加 option 時所用到的參數):

<UL>
<LI>has_option(opt_str) : 檢查 OptionParser 中是否有某個 option。</LI>
<LI>get_option(opt_str) : 取得 OptionParser 中的某個 option。</LI>
<LI>remove_option(opt_str) : 刪除 OptionParser 中的某個 option。</LI>
</UL>

當 option 發生碰撞(重覆)時:

option 以下列的方式加入時:

parser.add_option("-n", "--dry-run", ...)
...
parser.add_option("-n", "--noisy", ...)


就稱為"碰撞"。當 option 碰撞時, optparse 會丟出 OptionConflictError。程式設計師應該在設計期就解決掉這個問題,也就是說,不應該使用 try - except 來捕捉這個錯誤 - 畢竟這在設計期就可以被處理掉的。

當 OptionParser 的被繼承時,一些標準的 option 就很有可能被子類別覆蓋掉。這種情況下,可以設定 OptionParse 處置碰撞的方式:

parser.set_conflict_handler("resolve")
or
parser = OptionParser(..., conflict_handler="resolve")


都 可以讓後來加入的 option 覆蓋掉原有的 option。預設的 conflict_handler 值為 "error",也就是直接丟出 OptionConflictError。所謂覆蓋,也不是直接移除掉原有的 option,而是避開後來加入的 option:

parser = OptionParser(conflict_handler="resolve")

parser.add_option("-n", "--dry-run", ..., help="original dry-run option")
...
parser.add_option("-n", "--noisy", ..., help="be noisy")


在 help 訊息中,就會看到:

options:
--dry-run original dry-run option
...
-n, --noisy be noisy


第一個 option 的 "-n" 被刪去了。如果這時又加入一個 option,使用了 "--dry-run"做為名稱呢?那麼第一個 option 就會直接被移除,因為它已經完全被覆蓋掉了,程式將不認得它, help 訊息中也不會有它的蹤跡。

在這裡我省略了 Callback option 和 Extending optparse 兩個小節,如果有興趣,可以親閱 Python Library Reference;對於這篇文章若有疑問的,也可以先找找 Reference,也許我漏掉了也說不定。

程 式寫得愈多,愈覺得自己的渺小。這些設計精良的套件,若不是當初由許多無私的前輩們開發出來,我們又怎麼夠享受到它的便利性?以上是我參考 Python Library Reference, 6.19 optparse 介紹的內容,所寫的心得筆記。希望對這裡的 Python 同好有幫助,如果有錯誤也請多指正!


void optparse::OptionParser::add_option ( std::string  shrt_flag,


std::string  lng_flag,


std::string  destination,


std::string  help = "",


action_t  act = STORE,


type_t  type = STRING,


std::string  dfault = "",


std::string  allowed_values = "" 

)


Add an option to the parser.

Parameters:

shrt_flag Short option name, like e.g. "-q".

lng_flag Long option name, like e.g. "--quiet"

destination Key under which the option argument is stored in the dictionary.

help Help string for generating the usage info.

act Action, one of STORE, STORE_TRUE, STORE_FALSE.

type Type info of the expected option argument. One of INT, DOUBLE, STRING, BOOL.

dfault Default value. Value stored in the dictionary if the option is not given.

allowed_values List of possible option values. A string of comma-separated allowed values. An empty string means that any value is allowed.

 
 
 
 

--
海阔天空,做什么就记什么。主要是 Ubuntu Linux 和 Latex 及编程相关的东东: http://hai-kuo.blogspot.com/ 



上房老大买二手房,看实景照片,挑专业经纪人

2008年6月8日星期日

[Code]: some Python code

get system platform
>>> os.name
'posix'
>>> sys.platform
'linux2'
>>>

get HOME path

>>> os.environ['HOME']
'/home/rui'
>>> os.system('echo $HOME')
/home/rui
0
>>>

get command line

>>> sys.argv
['']
>>>

--
海阔天空,做什么就记什么。主要是 Ubuntu Linux 和 Latex 及编程相关的东东: http://hai-kuo.blogspot.com/ 



上房老大买二手房,看实景照片,挑专业经纪人

2008年6月5日星期四

[Code]: Python中发邮件时,使用中文subject

 
msg=mail.Message.Message()    #一个实例
msg['to']='love@python.com'      #发送到哪里
msg['from']='my@email.com'       #自己的邮件地址
msg['date']=time.ctime()      
       #时间日期
msg['subject']=email.Header
.Header('邮件主题','gb2312')
#这里用Header方法处理subject.
完成后的样子.
>>> print msg.as_string()
to: love@python.com
from: my@email.com
date: Mon Jul 11 20:18:13 2005
subject: =?gb2312?b?08q8
/tb3zOI=?= 
 
 

--
海阔天空,做什么就记什么。主要是 Ubuntu Linux 和 Latex 及编程相关的东东: http://hai-kuo.blogspot.com/ 



上房老大买二手房,看实景照片,挑专业经纪人

[Code]: Python code to statistic file size

>>> import os
>>> print os.getcwd()
/home/rui/projects/simplemaile
r
>>> print os.listdir('.')
['example', 'mimemail.py', 'weblogger.tar', '.git']
>>> os.stat('mimemail.py')
(33188, 341L, 2054L, 1, 1000, 1000, 4874L, 1211887832, 1210834210,
1210834210)
>>> os.stat('mimemail.py').st_size
4874L


 
 
 

--
海阔天空,做什么就记什么。主要是 Ubuntu Linux 和 Latex 及编程相关的东东: http://hai-kuo.blogspot.com/ 



上房老大买二手房,看实景照片,挑专业经纪人

2008年6月1日星期日

Source code for Programmer's Notepad

Programmer's Notepad, sourcecode:  http://code.google.com/p/pnotepad/
 
 
 

--
海阔天空,做什么就记什么。主要是 Ubuntu Linux 和 Latex 及编程相关的东东: http://hai-kuo.blogspot.com/ 



中 国 最 强 网 游 --- 网 易 梦 幻 西 游 ,166 万 玩 家 同 时 在 线