2014年5月10日 星期六

read open source pygments 2

這篇就來,繼續上次的進度 :)

上次code貼上來的結果不甚理想,所以我在想是不是要自己來寫一個format會比較方便,當然在動手之前,我想重新理解code的流程是必須的,因為要讓自己對這份open source掌握更加清楚,所以我決定利用debug的step into,來進行trace code :p

這邊就來介紹一下我用的工具,關於debug,我還是選擇用IDE,因為比較直覺化又容易使用,我是覺得沒必要去聽信那些說用gdb才是王道,畢竟那要打一些指令,實在是有點麻煩,個人是認為有興趣的話再去用那種方式 :p

說要介紹我是用哪款IDE都差點忘了 :) 這邊我是用pycharm ,這一直以來都算很有名氣,雖然是要錢的,但是網路上總有...咳咳,不過那僅限以前!!,現在可好了呢,它有提供open source版,而且功能很夠用,有興趣的人可以去載來用看看 :)



pycharm的介面如上,它提供了算是不錯的code intellisense,加上trace code也是方便,像是find definition,加上它的plugin也是挺多的,要說讓我說嘴的地方就是記憶體吃的有點多:(
另外以介面來講,我還是喜歡sublime就是了,好啦,該來講講怎麼trace code的部分了,一般來講都要先下個所謂的break point,就是讓程式執行到該行時,停下來,接著就有如下幾個操作
1. next line(step over)
2. step into
3. step out
... 等等

就先來看看這張圖吧

我在40行的地方下了中斷點,所以程式執行到這邊就會停下來,之後呢,我特別在watch中加入一些我想看的變數,上面這張圖是我step over後,可以看出它是一個class,有興趣要看它是怎麼一步一步產生的話,就必須用step into,就像接下來的HtmlFormatter,我用了step into就會如下面這張圖


程式碼頁面會跳到HtmlFormatter所在的檔案html.py,接著你更想的話,你當然可以繼續用step into,就看你想要鑽到的地方有多深,就跳多深吧 :)

另外我覺得用pycharm來debug真的是頗爽 :) 老實講真的太方便了,看前面幾張圖就知道,它其實會自己監看一些變數,起初我用sublime text閱讀源碼時,其實有點卡卡的,當時我認為是我理解力不夠,因為有很多地方看過去,我會有種不知道這樣的code會產生什麼效果,但是用了pycharm就方便多了,因為你會看到這些變數,就知道他們是否如你所想像的一樣,這樣一來多了一些證實,自然就會多了信心,閱讀起來更加順遂,就舉個例子好了,請看下面這張



我當初一眼看沒有懂的地方就是這裡
arg = ('cssclass' in self.options and '.'+self.cssclass or '')
從圖中可以看到arg的值是.highlight其實就是'.'+self.cssfile
很好!! 這樣的寫法到底是怎麼運作呢? 詳細可以看看 這個這樣的寫法不是每個programming language都可以寫的呢 :) 看看這個wiki 就知道囉~

回到正題,那行的意思是 'cssclass'有沒有在self.options裡,有的話就會回傳'.'+selfclass,沒有的話,就會繼續evaluate下去,那就是變成回傳'',這其實是用到short circuit的技術 :p
其實個人認為這邊根本不需要用到這種寫法,只是徒增不可讀性就是了,用if else還親民多了,不過這不代表這樣的寫法沒用處,我想大概可以用在 lambda這地方吧 :)

經過這次的閱讀,目前我想到一個,不用自己繼承一個HtmlFormatter的寫法了,我是用了擷取部分code,之後再自行增加一些必須的html的方式。

目前我粗略地寫了個簡單測試腳本,效果如下

 1 '''
 2 a script for python code highlighting is expected to partial html output.
 3 That's output content without the whole html tags.
 4 
 5 
 6 ex.
 7 <style>
 8 xxx
 9 xxx
10 xx
11 </style>
12 <table>
13 <div>
14 xx
15 xx
16 </div>
17 </table>
18 
19 usage: test.py inputfile outputfile
20 
21 '''
22 
23 
24 from pygments.formatters import HtmlFormatter
25 from pygments import highlight
26 from pygments.lexers import *
27 from pygments.styles import *
28 import sys
29 
30 try:
31     readfile = open(sys.argv[1], 'r')
32 except:
33     sys.exit()
34 
35 code = readfile.read()
36 readfile.close()
37 
38 file = open(sys.argv[1].split('.')[0]+'.html', 'w')
39 
40 st = get_style_by_name('native')
41 myformat = HtmlFormatter(style=st, linenos='inline')
42 
43 
44 content = '''<style>
45 .lineno {{
46     color: {};
47     margin-right: 5px;
48 }}
49 {}</style>'''.format('#'+str(int( st.background_color[1:])+303030), myformat.get_style_defs('.highlight'))
50 #rule the style
51 
52 content += highlight(code, get_lexer_for_filename(sys.argv[1]), myformat)
53 #add the highlighted code
54 
55 
56 file.write(content)
57 file.close()


比起上次用原來的指令,所產生出來的html檔,這次不需要再多做一些修正,可以將完整的內容直接複製貼上,相對起來大概是有比較方便吧 :) 這篇就先到此吧~

下次再繼續PO心得
最後來首音樂吧



2014年5月4日 星期日

read open source pygments 1

pygments 簡單說是一個syntax highlighter,他支援的語言十分之多,最近會突然想閱讀他源碼,其實有部分原因是想開始練習閱讀open source,畢竟為了我另外一個project,我想,閱讀open source的能力,勢必要有所上升才行 :)

另外原因是,之前有朋友問,怎麼在blogger上面hightlight code,關於這個,我之前都是用這個 ,這是based on javascript的,所以必須要在blogger的後端,加入一些連結,而且每次要寫code時,都必須把code包覆在<pre brush:xx></pre>裡面,才會有效果出現,其實就以寫blog而言,真的有那麼一點不順就是了 :(

不過朋友說他做了設定後,卻沒有效果出來,好吧,我人沒在他旁邊,所以也不知道問題出在哪,所以最近在想乾脆用用pygments將code highlight後output成html格式,再將它PO在blog上面,這樣就比較簡單了 :) 於是我的閱讀之旅就這樣開始拉,雖然僅能利用假日來讀 :(


我想,首先就從package的 __init__.py來開始看,應該是沒錯的,如上圖所示,它做了一些最基本的說明 "pygments 是一個用python寫的語法高亮器 bla bla bla" 以下省略 :p

這邊特別說明一下 __all__ 這個東西的效用,其實看官網 的說明,就大概知道了,當你用 from pygments import *,如果你有定義 __all__ ,那它只會import 在all裡面的那些東東而已,沒定義的話,就會看你的 __init__.py 裡面有什麼就 import 啥,比如上面有import sys,那它也會跟著import sys,好啦轉回正題~

這個檔案的結構也滿簡單的,highlight這個function用到了 lex 和 format,另外當__init__.py被當成執行入口時,它會import cmdline.py,所以接下來我要去讀的package和檔案其實也滿明顯的,接下來我是選擇先閱讀cmdline.py,其實從名字一看也知道這是關於在cmd中如何進行操作的檔案,看完這檔案,應該就知道怎麼使用 pygments了,畢竟先懂得怎麼使用,然後再試著修改,我想這應該是不錯的順序吧 :p,另外也不用再去看官方docments的操作說明 :)


看吧,果然有使用方法,不過這檔案用到挺多東西的,其中它用到了兩個standard module,

1. getopt
2. textwrap

python果然真的是太方便了,光是內建就有一堆好用的東西,雖然這些自己寫一個也是OK拉:p

看了官方說明, getopt 主要是一個 sys.argv的parser, textwrap總之,方便文字格式處理的module,詳細不多說,畢竟這不是這篇文章的重點,且官方有不少說明,或者更有興趣直接看textwrap.py和getopt.py也是可以的。

 看了一些code後,使用上並不難,比如想要對test.py輸出一個語法高亮格式為html的檔案,打這樣的指令就可以了

pygmentize -O full,style=emacs -o test.html test.py

基本上只要你有提供輸入輸出檔,pygments會自動判斷該檔案的語法,當然你也可以自己輸入參數去規定syntax就是了,另外關於-O 那邊的設置,可以找源碼中的formatters的html.py裡面有相關說明,不同的輸出格式,會有一些有不同的option,效果如下

1
2
3
4
5
a = [ x for x in range(10) ]
b = a[::2]

print(a)
print(b)


我是將輸出的html內容擷取並貼上來,而且還要做一些小處理,只是如果每次都要這樣其實也滿累的 :( 目前就先到這邊吧,下次在PO繼續閱讀的心得,並且想個解決辦法 :p