2012年9月29日 星期六

Git, Git X Dropbox (or Google Drive), Git X Emacs

共筆或考古詳解的協作流程,在初期(共筆->上課時,考古->上課時或工作剛分派時)較傾向於使用Google文件的協作,因為大家比較會同時進行,debug或diff的需求比較沒有需要,或是根本來不及趕上文件本身的變化速度。課堂結束或考古解題初步完成後,就可以把文件匯出為輕量級標記語言(html=> 黑魔法利器pandoc =>org mode, doc=> odt ==> odt2org ==>org mode, pdf => poppler 的 pdf2html => html)以納入 git 進行版本控制

Git

Git 教學(1):Git的基本使用
Git 教學(2):Git Branch 的操作與基本工作流程
Git 情境劇:告訴你使用 Git 時什麼情況該下什麼指令
3分鐘學會基本使用。情境劇這篇整理了很多指令,可以印一份下來參考。

http://www.cheat-sheets.org/saved-copy/git-cheat-sheet.pdf
看得懂英文的話,這份印下來很好用

□ [教學] Git使用教學 Part 1 -- 新手上路
□ [教學] Git使用教學 Part 2 -- 控制版本
這一系列用很簡單的例子講得很深入

Git教學:初學者使用心得分享(Windows)
如作者所言,是windows面向

正體中文 的Git Magic電子書。嚴格來說,翻得有點生硬,不如直接看原文的好。

Git X Dropbox (or Google Drive)

Git教學:Git的遠端操作及利用Dropbox建立Server進行協同開發(Windows)

□ [教學] Git使用教學 Part 3 -- 多人作業 延續之前提到的系列,講述用--bare選項來使雲端空間成為server的方法

Emacs

普通人(非程式設計師)的.emacs設定檔
這篇寫得滿不錯,設定的部份相當值得參考,初學emacs的話可以經常開著這頁

Hyperlinks
org mode的hyperlinks建立的方法,我覺得很重要

Git X Emacs

Emacs学习笔记(14):在Emacs中使用git

Article about using Emacs for work with version control systems 廣泛地討論了在emacs中使用git的方法,有一般化模組(VC, DVC)及特殊模組兩大類,其中 Work with Git 特別說明了git的模組。

Org-mode

我認為粗體、斜體、底線、刪除線等標記除了字體上的強調外,在顏色上也應該有所強調。雖然我們可以在菜單的“Org"-> "Customize"->"Expand This Menu"後於“Org"-> "Customize"->"Customize"->"Org Appearance"->"Org Empahasis Alist..."加入:background "red"這樣的設置,不過還是滿希望網上有現成的設定可利用…目前看到的解決方式多半是在~/.emacs中設定
(custom-set-variables
'(org-emphasis-alist
(quote
(("*" bold "" "") ("/" italic "" "") ("_" underline "" "") ("`" org-code "" "" verbatim) ("~" org-verbatim "" "" verbatim) ("+" (:strike-through t) "
" "") ("=" org-code "" "" verbatim))
)))

.emacs常用設定及org mode指令速查

.emacs常用設定

第一常用的應該是還原上次桌面 ,參考 DeskTop 中的 Auto-Saving the Desktop 及 Specifying Files Not to be Opened 還有 Automatically Overriding Stale Locks 。

第二常用是最大化視窗,win32平台請參考  FullScreen 。

再來是顏色的調整,參考 ColorTheme 。其中適用於 org-mode 者請參見 color themes , customizing Org appearance。另外,Org-mode FAQ 中的"Org-mode has a lot of colors? How can I change them?"有講到,要知道游標所在位置的話可按  C-u C-x = ,要修改則按  M-x customize-face [RET] ,否則使用 customize-group 的話還要找出那個 group ,滿麻煩的。

舉例來說,現在要修改 org-level-1 讓字體變大。在org載入後下達
(set-face-attribute 'org-level-1 nil :height 240)

其它常用設置可參考 Emacs 从入门到精通 ,其中 undo 的快捷鍵、them、org、gtd、git的配置滿值得參考的。

範例

coldnew 的 emacs 配置
https://github.com/coldnew/coldnew-emacs/blob/master/config.org

org mode指令速查

* 一般
M-S-ENTER (增加新item)===>類似於mindjet的Ins鍵
Tab (展開/折疊)===>類似於mindjet的C-'D'鍵
S-Tab (全部展開/折疊)===>類似於mindjet的M-C-'.'鍵
M-S Left/Right | 減/加星(層級)===>類似於大綱模式的M-S-Right/Left鍵

* Outline
C-c C-n/p (下/上個標題)===>類似於mindjet的右方向鍵
C-c C-f/b (下/上個同級的標題)===>類似於mindjet的上下方向鍵
C-c C-u (上一級標題)===>類似於mindjet的左方向鍵
C-c C-j (jump?)

cheat sheets(小抄?)

http://orgmode.org/orgcard.pdf 非常的齊全,下載的org-7.9.2.zip中也有

http://emacsclub.github.com/html/org_tutorial.html 略長,但說明文字望文生義,不錯;但是側重在export 的部份


2012年9月26日 星期三

ubuntu 12.04使用emacs的org mode內嵌圖片/pdf連結方法

網路上有很多講到iimage的文章,但是使用ubuntu 12.04原來附的emacs 23是不能動作的。解決方式參考 http://orgmode.org/worg/org-faq.html 更新 org

 如此下達 M-x org-display-inline-images 或C-c C-x C-v才會顯示圖片

還有設置 pdf 的閱讀器,不要使用 emacs 直接去打開 pdf 檔,要加入 openwith 設定於.emacs中,請參考 Emacs的插件openwith.el 。在win32平台上直接打開~/.emacs檔即可,不用去找它的位置,因為經常隨版本而改變 (冏>)

在以命令列啟動 adobe reader 時可以下達參數以指定開啟頁面,可參考 Adobe Reader Command Line Reference [closed] ,參數列表可見 http://partners.adobe.com/public/developer/en/acrobat/PDFOpenParameters.pdf 。而在org mode中的外部連結有 shell 參數可指定,可參考 External links 。目錄名稱需使用8.3形式,可參考 http://en.wikipedia.org/wiki/8.3_filename 。因此連結形式為

[[shell:C:\Progra~1\Adobe\Reader~1.0\Reader\AcroRd32.exe  /A "page=149&pagemode=none" C:\a.pdf][a]]

想要使各平台使用一致的file:形式連結,需要改寫 org-file-apps-defaults-gnu 及 org-file-apps-defaults-windowsnt 。節錄相關說明如下:

               - Regular expression which contains (non-shy) groups:
                 ...

                 Example: (\"\\.pdf::\\(\\d+\\)\\'\" . \"evince -p %1 %s\")
                     to open [[file:document.pdf::5]] with evince at page 5.


目前看來以下兩篇講的都是如何修改 evince 為預設 pdf 文件檢視器
Org-mode export to LaTeX: temptation or nuisance?

How do I make Org-mode open PDF files in Evince?

綜合起來,可以work的版本如下,注意數字的部分\d要改成[0-9]才能工作,不知道為何…

;; PDFs visited in Org-mode are opened in Evince (and not in the default choice)
(eval-after-load "org"
  '(progn
     ;; Change .pdf association directly within the alist
     (setcdr (assoc "\\.pdf\\'" org-file-apps) "evince %s")
     (add-to-list 'org-file-apps '("\\.pdf::\\([0-9]+\\)\\'" . "evince -p %1 %s") t)
))

win32上修改為

;; PDFs visited in Org-mode are opened in Evince (and not in the default choice)
(eval-after-load "org"
  '(progn
     ;; Change .pdf association directly within the alist
     (if (assoc "\\.pdf\\'" org-file-apps)
(setcdr (assoc "\\.pdf\\'" org-file-apps) "C:\\Progra~1\\Adobe\\Reader~1.0\\Reader\\AcroRd32.exe %s")
       (add-to-list 'org-file-apps '("\\.pdf\\'" . "C:\\Progra~1\\Adobe\\Reader~1.0\\Reader\\AcroRd32.exe %s") t)
     )
     (add-to-list 'org-file-apps '("\\.pdf::\\([0-9]+\\)\\'" . "C:\\Progra~1\\Adobe\\Reader~1.0\\Reader\\AcroRd32.exe  /A page=%1 %s") t)
   )
)

2012年9月23日 星期日

KM, GTD with Emacs Org Mode, & Mindmap, among others

KM

NB

http://people.csail.mit.edu/sacha/nb/tut-latest/ 這是mit的一個在PDF上注解並討論的網站,看起來很fancy,如果能結合影音討論的話,以後就不用來上課了XD

http://nb.mit.edu/welcome 這是主頁,名字就叫NB,是notebook呢,還是'牛B'呢?   XDDD

docear

http://sciplore.org/software/freemind_scholar/這是一個結合心智圖和文件管理的程式,用來寫論文很方便,跟endnote有異曲同工之妙

http://www.docear.org/software/screenshots/ sciplore的新版docear的使用方式短片,完成度已經很高了,現在就缺線上協作的部分,完成的話就天下無敵了
sciplore/docear 主要的功能在於將PDF內的書籤、註解等匯入,然而其主體 freemind 在我的 ubuntu 上匯入 folder 後竟無法 follow link ,失望之餘被我列為暫時拒往戶。因此我開始在尋找有無文字模式的 mindmap 解決方案,結果發現竟然有下面這個東西…

Emacs Org Mode 

Intro

The Org Manual (一頁HTML)
Org tutorials 一些教學文件和強者的使用經驗談
Emacs強大的Org Mode (持續更新)
[emacs] 为什么说org-mode是个神器
如果能內嵌圖片的話(org-toggle-inline-images),那麼拿來寫共筆也沒問題了,WORD就可以去吃*了XDDDD

Hands-on

普通人(非程式設計師)的.emacs設定檔 "請看stevenchan製作的簡易速查表"快速上手emacs

Emacs的Org Mode 簡單的快速上手介紹;重點:星號、移動、(平行)列表
Emacs org mode学习笔记  同上篇作者,較詳細的介紹,可以達到類似mindjet的效果;"结构化编辑"中提供了許多類比於word大綱模式的快速鍵
Emacs学习笔记(9):org-mode,最好的文档编辑利器,没有之一  更詳細一點的使用步驟
odt2org 將odt檔轉為org;可以先用LibreOffice將word的doc檔轉成odt再使用odt2org

GTD

Emacs学习笔记(11):用Org-mode实现GTD
這算是意外的發現吧,原來org mode是被這樣使用的

2012年9月22日 星期六

以perl處理ms word文件的utf8編碼問題


http://www.lemoda.net/perl/win32-ole-utf8/cp-utf8-ole.html

原文是在處理日文,不過中、韓文也適用,要訣是加上以下兩行:

use Win32::OLE 'CP_UTF8';
$Win32::OLE::CP = CP_UTF8;

順便提一下,一個起手的script可以參考
http://stackoverflow.com/questions/12070198/perl-ole-selection-property-iterating

得到script路徑的方式可參考
http://stackoverflow.com/questions/84932/how-do-i-get-the-full-path-to-a-perl-script-that-is-executing

加下以下兩行的方式比較穩定不會出錯:
use File::Basename;
my $dirname = dirname(__FILE__);

至於拜訪表格的方式,尤其是有合併的儲存格存在時,請參考
http://www.experts-exchange.com/Software/Office_Productivity/Office_Suites/MS_Office/Word/Q_27818826.html

__________________________________________________________________________

以下部分不確定,先持保留態度。為了關掉警告,會產生換行符號的轉換問題,有點不值得

常規表示法match中文時的解決方法
http://www.jeffhung.net/blog/articles/jeffhung/417/

輸出到檔案(及stdout等io設備)要做些處理,以關掉警告訊息
http://blog.wu-boy.com/2009/07/perl-with-utf-8-mode/

結果,換行的地方也會出問題

我是是接把換行字元變成 \x0d 來解決\n被轉換掉的問題

2012年9月14日 星期五

PDF中的索引和書籤(五)

在使用 swig 結合 c++ 的這個方向遇到困難後,回過頭來看看 evince 。結果發現 evince 根本就沒有用到 c++ 的介面,而是使用了純粹的 c 的介面(evince-3.5.90\libdocument\ev-document-links.c(52))。get_links_model 負責將索引組建成為樹狀結構(evince-3.5.90\backend\pdf\ev-poppler.cc(1384)),此結構剛好在 http://search.cpan.org/~tsch/Gtk2-1.203/xs/GtkTreeModel.xs 提供了 perl 介面。document 則由 ev_document_factory_get_document 取得(evince-3.5.90\libdocument\ev-document-factory.h(37)),其參數剛好是 char* ,非常有可能直接使用 swig 即可順利完成perl介面。很諷刺的是,本來一開始是想研究 evince 並繞過它直接呼叫 poppler ,沒想到 evince 本身可能已經完成了很多工作。這或許不是壞事,因為如果能整合 evince 本身的(自訂的)書籤系統的話,那麼我們很可能可以直接處理這個系統來得到想要的功能。

另一方面來說,evince 在 python 的介面似乎一直有人在維護,可以參考以下兩個連結
https://mail.gnome.org/archives/evince-list/2009-December/msg00007.html
http://www.techques.com/question/1-3672847/How-to-embed-Evince

不過這條路看起來也不輕鬆,尤其是有些package並沒有port到新版的ubuntu:
Choosing between Lucid and Squeeze packages? 由下連結可知,evince-python只更新到11.04版
http://packages.ubuntu.com/source/natty/gnome-python-desktop

這時又發現有python-poppler這個package,看來是最省事的作法
sudo apt-get install python-poppler
參考以下連結,寫個簡單的grep,看來還行
 http://lucasvr.gobolinux.org/etc/pdfGrep

2012年9月12日 星期三

swig產生poppler的perl介面步驟(一)

剛看了一下,apt-get install下來的 libpoppler19 和對應的原碼 libpoppler-dev 版本竟然不同,後者為0.18版。不過暫且放下這個問題,等到要編譯時再說。

產生 i 檔如下, 命名為 popplerIntf.i
%module popplerIntf
%{
#include "/usr/include/poppler/PDFDoc.h"
%}
%include "/usr/include/poppler/PDFDoc.h"
然後下swig指令
swig -c++ -perl5 popplerIntf.i

看起來是成功了。不過問題才剛開始,下一步編譯和連結,必需要確定版本的一致性,因此還是從官網直接抓最新的 source 下來編譯比較保險。可參考http://linux.vbird.org/linux_basic/0520source_code_and_tarball.php
  • poppler 似乎同時維護兩種 build systems,分別是 CMake 和 autotools (automaker等) ,參見 http://blogs.gentoo.org/lu_zero/2010/01/24/cmake-vs-autotools-poppler/ 。
    • autotools 的使用可參考 http://riverhippo.blogspot.tw/2010/03/gnu-autotools-share-library.html ,其腳本似乎為根目錄下的autogen.sh
    • CMake 的組態檔取名為 CmakeLists.txt ,參見 http://zh.wikipedia.org/wiki/CMake
  • 根目錄的 INSTALL 檔案說明了一些基本的安裝方式,但沒看到configure檔,顯然我們需要執行 aclocal, autoconf, automake,參見 http://blog.roodo.com/rocksaying/archives/12687975.html
  • 但以上功能已由 autorecon 取代,被寫在 autogen.sh 中,因此整個組建流程簡化為:
  1. 建立並進入子目錄(先確認 <程式庫安裝完整目錄> 已建)
  2. 執行 ../autogen.sh --prefix=<程式庫安裝完整目錄>
  3. make
  4. make install
其實以我們現在的情況是要寫module的話,安裝目錄不指定可能反而比較方便封裝
根據 swig-2.0.8/Doc/Manual/Perl5.html#Perl5_nn9 ,編譯 *_wrap.cxx 檔:
g++ -fPIC -c popplerIntf_wrap.cxx -I/usr/lib/perl/5.14/CORE -I./poppler-0.20.3 -I./poppler-0.20.3/mydist/poppler
g++ -shared popplerIntf_wrap.o -L/home/sig/usr/local/lib -lpoppler-cpp -o popplerIntf.so
最後測試一下
perl -MpopplerIntf -e 'print "hi\n"'
但問題還是出現了
perl -e 'use popplerIntf;$doc=new popplerIntf::PDFDoc("a.pdf");'
訊息如下:
No matching function for overloaded 'new_PDFDoc' at popplerIntf.pm line 62.

根據此文的暗示,可能要自己寫 typemaps...

2012年9月11日 星期二

細說swig產生perl介面步驟

模組 (module)

講到 swig 在 perl 的應用就要先了解 perl 的模組,因為任何引用的行為在 perl 當中都是以模組 (module) 為單位,因此撰寫可重用的程式碼也必需循此一標準。要了解這些概念,我推薦這篇文章: module,package,use , require , BEGIN,END 全部用法攻略 。(這個網站每篇文章都值得細讀,這篇文章應是來自 http://www.tutorialspoint.com/perl/perl_modules.htm ,以駱駝書的5.2節為基礎加以改寫的)。
  1. 要講到 module,就要先講到 package; package 是處理 scope 的問題,而 module 就是單一 scope 的檔案。
  2. 取用module時的指令為 use (和require,但不常用)。要被引用的識別字需加到 @EXPORT 
  3. 最後的程式就是用 h2xs 產生模組目錄,並用 tar 打包上傳。安裝時執行 Makefile.PL 即可
  4. 在實作時,善用 Module::Starter + Module::Install 會節省不少時間。
至此講的是以perl寫模組。那以c寫模組呢?就是在下 h2xs 參數時少個 X ,這樣就出現了個 .xs 檔案可以寫 c 的宣告和定義,然後流程是一樣的。可參考 https://sites.google.com/site/squallpro/%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88/perl/c-perl/h2xs 。應用 Module::Starter 則請參考 http://c9s.blogspot.tw/2009/04/modulestarter.html

好,那麼 swig 的角色呢? 請再複習一次


  1. (從 h 檔中)找出所要包裝的函數(和 h 檔)
  2. 建立 i 檔
  3. (從 h 檔中)複製函數宣告到 i 檔中,或使用 %include指令處理整個 h 或 c 檔
  4. 確認語法合於ANSI
  5. 如果不是直接引入 h 檔,請確認宣告的型態順序正確,以使介面可以順利編譯
  6. 將main()函數改名(但函式庫中應該不會有這個函數)
  7. 執行swig並編譯

(可參 http://stuff.mit.edu/afs/athena/astaff/project/svn/src/swig-1.3.25/Examples/perl5/class/index.html 。呼叫上可參此頁中"Key points"那段。)

歸納起來模組在perl中有三種編譯方式;

第一種是原生的呼叫gcc

第二種編譯方式是利用 h2xs (背後其實用了 ExtUtils::MakeMaker 來產生Makefile.PL),在 http://fans.huhoo.net/perlxs/perlxs.doc  有更深入的介紹

perl Makefile.PL
make
make install

上述兩種編譯的方法中,有人討論過與swig的搭配,請見以下兩串討論串,正解在第二串,但整個thread已吵得雞飛狗跳...( 因h2xs預設產生了 Makefile.PL,大家想當然爾認為swig該當如此)據該thread作者所言,在 http://www.swig.org/tutorial.html 上的編譯方式因此而更新;為維持可攜性,第二種編譯方式(使用MakeMaker)仍然是比較多人擁戴的
http://www.perlmonks.org/?node_id=895499
http://www.perlmonks.org/?node_id=895682
第三種是利用 Model::Starter;官方建議的MakeMaker已經有十多年的歷史了,較新的解決方案是 Module::Starter + Module::Install 。可以參考 http://c9s.blogspot.tw/2009/04/modulestarter.html 中的說明。但是沒人討論過與swig的搭配,或許是因為太前衛了 XD

解決問題的洞察力

最近寫太多硬派的文章了,想記錄一下最近的心情。

時代一直在前進,但是感覺前進的速度不成比例。一樣是大一的學生,比起十年前、二十年前明明多了那麼多工具,但是他們未必能欣賞這些工具的好,甚至因為看起來要"多"學一些東西,一開始就去排斥。(不過說實在的這或許是老師的問題,因為沒有點出方法論的重要性。)

另一方面是工具拿在手上要知道怎麼用,刀槍都有時要知道何時用刀、何時用槍。這是我覺得沒辦法與時俱進的能力,就是了解並解決問題的 insight ,我姑且稱之為洞察力好了。這其實是很高層次的心智活動(遊戲?),涉及空間推理、抽象化、符號處理、模式辨識、歸納邏輯、推理演譯等。如果今天我們只是把教科書電子化,把作業上線,這根本就只有方便了教授和助教,對型塑學生的心智能力毫無幫助。教學生資料搜尋的技巧、網路協作、然後丟一個問題給他,觀察他解決的方式,點出他的盲點,難道不是"教"的功能嗎?不然你也只是個"教師"而已了不是嗎?傳給他一套量身打造的武功,可能比所有人都教同一套少林武功要好得多了…

回過頭來說洞察力。這種能力是可以培養的,我覺得寫系統分析文件是很好的訓練方式。先說明想要解決的問題,然後觀察一些類似的問題和解法,然後把問題到結果之間拉出一條線,鞏固這個陣地,最佳化整個解答,最後反覘陣地確定效果。開始一定要作些類比,觀察類似的問題及解決的角度,最好能利用現成的解法稍加修改即可。

PDF中的索引和書籤(四)

Outline *PDFDoc::getOutline() 是屬於poppler的函式,一呼叫就會傳回一個樹狀的結構,因此需要一個 traverser 或 iterator 來去把它遍歷以存取每個節點。這也是遞迴函式 static void fillToc(...) 在程式中的用途,去遍歷節點進行處理,當然它一個函式包含了遍歷的演算法和處理節點的邏輯,在模組化的方面作的還有點不夠,不過因為他是個demo,所以也就不要太強求了。 從函式庫的使用者觀點,我們現在要做的是
  1. 開啟檔案,得到 PDFDoc* ==> PDFDoc::PDFDoc(GooString *fileNameA,...)
  2. 呼叫 Outline *PDFDoc::getOutline()
  3. 拜訪( visit )  Outline * 資料結構
ps.
看到第6點"將main()函數改名"我突然想到,其實這些函式庫經常帶有一些demo,這些demo本身就會調用函式庫,所以提供了使用上的順序和方法的資訊…(這不就是demo應該要做的事嗎)。目前看到幾個主程式
  1. poppler-0.20.3\glib\demo\main.c
  2. poppler-0.20.3\qt4\demos\main_viewer.cpp 當中的 main() ,由其定義可知,整個程式乃是使用命令列的第一個參數作為所要打開的檔案名稱,並呼叫了 loadDocument 函數
  3. poppler-0.20.3\utils\pdftohtml.cc(178) 當中亦定義了main(),420行呼叫了 dumpDocOutline ,其定義在  HtmlOutputDev.cc ,而取得書籤的函數定義在 poppler-0.20.3\utils\HtmlOutputDev.cc(1684): Outline *outline = doc->getOutline(); 

其實如果懶得跟 pdf 週旋下去的話,直接把它 dump 成 html 來處理也是滿可行的。事實上ubuntu似乎預裝了 pdftohtml ,而測試的結果也證實,這樣一轉以後,所有的格式資訊都消失了…

python-poppler 及 ruby-poppler 都以套件的形式在apt的套件庫中存在。稍微看了一下是很久沒維護的樣子,可能是不需要,還是沒人?不知道…不過我有點可以理解,因為poppler的版本演進還滿快的,如果介面經常改變,那可能會令人失去追逐新版本的熱情。為了維持自身的穩定性,可能最好是抓個固定的版本編譯後給自己用,而不去使用系統預裝的版本。

要查ubuntu中安裝了那些套件,如poppler,可以下此命令
sudo dpkg --get-selections | grep poppler
結果會發現 libpoppler19 已經預裝了。以下命令可以查詢其資訊及位置
dpkg -s libpoppler19
dpkg -L libpoppler19

2012年9月6日 星期四

PDF中的索引和書籤(三)

但是如果我們連ui都不要的話呢?如前所述我們追蹤到了 static void fillToc(...) ,但是它的參數都是QT的ui,而toc實際上是由這行

const QDomDocument *toc = document()->toc();

所取得的,其內容如下


    QDomDocument *Document::toc() const
    {
        Outline * outline = m_doc->doc->getOutline();
        if ( !outline )
            return NULL;

        GooList * items = outline->getItems();
        if ( !items || items->getLength() < 1 )
            return NULL;

        QDomDocument *toc = new QDomDocument();
        if ( items->getLength() > 0 )
           m_doc->addTocChildren( toc, toc, items );

        return toc;
    }


m_doc的型態為 DocumentData * ,宣告在 poppler-0.20.3\qt4\src\poppler-private.h(78) 。其 doc 成員宣告在 188行,型態為 PDFDoc * 。 PDFDoc::getOutline() 定義於 poppler-0.20.3\poppler\PDFDoc.cc(1466):


Outline *PDFDoc::getOutline()
{
  if (!outline) {
    // read outline
    outline = new Outline(catalog->getOutline(), xref);
  }

  return outline;
}


所以現在問題就是,1:catalog怎麼來的,2,xref又那來的,3,getOutline()做了什麼,前文說

從xref(p-67)中取得catalog(p-77),存入catDict,找出其中的 Outlines(96) 並回傳之

所以問題簡化為:1:xref怎來的,2:取catalog,3:取outlines

xref 的建構在 poppler-0.20.3\poppler\PDFDoc.cc(268):
   xref = new XRef(str, getStartXRef(), getMainXRefEntriesOffset(), &wasReconstructed);

這屬於248行的 GBool PDFDoc::setup(GooString *ownerPassword, GooString *userPassword) 的工作;而catalog也在282行被初始化。因此呼叫 Outline *PDFDoc::getOutline() 就是取得目錄的標準方式了。


perl xs及swig初探

XS

  1. XS是用來供為perl呼叫C函式(反之亦可)的介面,可建立程式庫供動態載入或靜態連結;此一介面的描述語言,我們稱為"XS語言"。
  2. XSUB是XS介面的基本單位,其中sub即為subroutine(副程式)之縮寫。
  3. xsubpp是"XS語言"的編譯器,將"XS語言"編譯為C語言的函數定義,以做為perl及C之間呼叫函數的橋樑。
  4. 這黏著劑一般的程式碼,對參數及傳回值在背景進行轉換,參數可以傳值或傳址方式被修改。
  5. 為了簡化流程,我們可以用"XS語言"來撰寫介面,然後以xsubpp編譯之。"XS語言"讓我們可以表達在perl及C當中副程式被呼叫的"簽名"的對應。兩這兩者的型態一樣時,還有一種叫做h2xs的工具程式,用來將整個標頭檔(*.h)對應為"XS語言"檔。
  6. 在"XS語言"中,typemaps指令用來描述如何將C函式的參數和傳回直轉換為perl型態,反之亦然。perl本身帶有的預設typemap,可以處理常見的C型態,但是除此之外的typemap仍然需要手動撰寫。
  7. XS格式的檔案,一開始是一個C語言的節段,直到出現第一個MODULE=指令為止;之後則可以是其它的XS指令或是XSUB定義,這裏使用的語言就是之前曾經提到過的"XS語言"。

swig

Dave Beazley's SWIG可能提供了更方便的機制,請造訪 http://www.swig.org/ ,至於中文版可參考 http://www.swig.org/translations/chinese/index.html

在進行利用swig產生標頭之前,先來稍微了解一下流程,參考 SWIG (Simplified Wrapper and Interface Generator)

why

在幾個以國數字為標題的項目中,我們感興趣的是一及二。一的部分就是單純只有C檔,然後為它撰寫 i 檔。這個做法當然不像是一個好主意,至少通常現在的函式庫中都寫好了 h 檔。因此二的部分就是單純利用此 h 檔,產生 wrapper ,將它與函式庫一起編譯為 so 檔。要注意的是此 so 檔必需要在程式執行前先行手動載入。(此外五中使用了標準函式庫,其作法也值得參考一下。)不過即然可以直接由 h 檔產生介面,那為何還要手寫 i 檔呢?答案就在官方文件中~~

先來研究一下官方的文件。在抓下來的swig解開後,swig-2.0.8/Doc/Manual/Sections.html#Sections 有文件的目錄,16章以前講的是一般性的東西,17章以後針對個別的語言講解,其中perl的部分在第31章。第五章是官方建議必讀,像為何要另外撰寫 i 檔,答案在 5.7.4 中。第一個原因就是控制 scope,很多函數沒有必要去呈現成為介面,而且全部都產生介面的話會形成無用的巨大檔案;因此, i 檔可以提供精確的控制、組織;另一方面,swig有它的局限性,無法轉譯的介面,仍然需要在 i 檔中予以處理;最後,它本身就可以做為一個文件,使用者不必去挖 h 檔裏面的資訊,就可以了解如何使用介面。

how

接下來看看怎麼進行。5.7.1講解流程:
  1. (從 h 檔中)找出所要包裝的函數(和 h 檔)
  2. 建立 i 檔
  3. (從 h 檔中)複製函數宣告到 i 檔中,或使用 %include指令處理整個 h 或 c 檔
  4. 確認語法合於ANSI
  5. 如果不是直接引入 h 檔,請確認宣告的型態順序正確,以使介面可以順利編譯
  6. 將main()函數改名(但函式庫中應該不會有這個函數)
  7. 執行swig並編譯
官方文件在 swig-2.0.8/Doc/Manual/Perl5.html#Perl5_nn3 ,31.2節首先說明最簡單的情況,i 檔被 swig 編譯後會產生 c 檔(包含 i 檔中對應的宣告,應在此檔提供定義)及 pm 檔(包含載入模組的 perl 程式),要建置模組就必需將 c 檔編譯並連結到程式(我想它說的是31.2.2~4節所言,連結到perl);linking 有兩種,一種是動態,一種是靜態(不建議);31.2.2及31.2.3講的是編譯動態連結程式庫,前者使用gcc(不建議),後者使用Makemaker(建議使用)。31.2.2看一下可以了解連結的基礎,概念和一般win平台上dll的編譯其實是一樣的,要注意shared object 的名稱需同於module,並且至少要用gcc編譯swig產生的 *_wrap.c 檔;31.2.3則稍微說明一下Makemaker的用法,注意這裏提供的參數與上節的對應,另外在 http://gdwang.blogspot.tw/2011/09/linux-how-to-write-perl-extension-use.html 有給出比較實際的語法,而且所連結的成員通常是會包含程式庫沒錯,步驟上就是呼叫swig,用gcc編譯swig產生的 *_wrap.c 檔,寫Makefile.PL,執行perl Makerfile.PL,make,make install。31.2.5後半講到連結so的可能問題,算是這個架構的收尾。

PDF中的索引和書籤(二)

從 poppler-0.20.3\glib\poppler-page.cc 來看, poppler_page_get_link_mapping 這個函數是將所給定的頁面中的 Annots (似乎很確定就是Links) 走過一遍,然後回傳。

另一方面,從該檔的標頭檔看來,與cairo有很深的糾葛,或許是glib本來就是負責繪圖的部份使然。

在使用google 查詢 getAnnots()時,發現另外有個 Ruby 的專案 origami-pdf 也能parse pdf檔,不過看起來比較沒有在更新,而且個人猜測是單純對poppler作複製而已。

poppler-0.20.3\qt4\demos\toc.cpp 中似乎透露著更多顯示 TOC (table of contents) 的更多細節。其中定義了此一靜態函數 static void fillToc(...) ,是一個明顯的遞迴呼叫,同時對外它也被void TocDock::fillInfo() 呼叫,其中比較令人在意的是這行敘述

const QDomDocument *toc = document()->toc();

其定義應來自於 poppler-0.20.3\qt4\src\poppler-qt4.h

    class POPPLER_QT4_EXPORT Document {
...
QDomDocument *toc() const;

然後其定義依序又呼叫了 getOutline() ,

poppler-0.20.3\poppler\PDFDoc.cc(1466): Outline *PDFDoc::getOutline(){
poppler-0.20.3\poppler\PDFDoc.cc(1470):     outline = new Outline(catalog->getOutline(), xref);

看看 getOutline() 的定義 @poppler-0.20.3\poppler\Catalog.cc(827):

Object *Catalog::getOutline()
{
  if (outline.isNone())
  {
     Object catDict;

     xref->getCatalog(&catDict);
     if (catDict.isDict()) {
       catDict.dictLookup("Outlines", &outline);
     } else {
       error(errSyntaxError, -1, "Catalog object is wrong type ({0:s})", catDict.getTypeName());
       outline.initNull();
     }
     catDict.free();
  }
  return &outline;
}
大意是說,從xref(p-67)中取得catalog(p-77),存入catDict,找出其中的  Outlines(96) 並回傳之

結論就是,我們主要需要改寫的地方就是 static void fillToc(...) ,頂多再加上 void TocDock::fillInfo() 的小修改即可,為方便起見透過xs由perl來呼叫,這待下回分解

p.s.另外我也意外地發現 poppler-0.20.3\cpp\poppler-toc.h 中也定義了 toc(),但為 private
p.s.2.提及頁數的部分,均指"PDF 1.2 Reference Manual"

p.s.3. 原來已經有人用swig寫好了!!  http://search.cpan.org/~cornelius/Poppler-0.04/lib/Poppler.pm

2012年9月4日 星期二

在ubuntu上快速完成工作的小抄

有些快速鍵跟WIN32平台上差滿多,有必要整理一下

1.Mastering The Linux Shell – Bash Shortcuts Explained (Now With Cheat Sheets)
作者說他沒有全部放進去,我可是已經頭昏腦脹…光個shift+pgup/pgdn就非常有用了

2.Bash Shortcuts
還有連按兩次TAB的各種變化,真的是很威…

3.Bash command line shortcuts Cheat Sheet

精練多了,只是缺了shift+pgup/pgdn…這個其實滿有用的說

4.Bash Shortcuts For Maximum Productivity

高手級的,說真的很變態…

5.http://www.catonmat.net/
Bash One-Liners Explained, Part I: Working with files
Bash One-Liners Explained, Part II: Working with strings
Bash One-Liners Explained, Part III: All about redirections  該作者狂熱地研究並記錄者所有shell及script的用法,真是近兩年來的佳作。上面這幾篇來說,第三篇最重要;不過嚴格來說這三篇和shortcuts比較扯不上關係…

其它還有3篇

這篇要先會一點emacs才會有感覺,或許不是很重要的技巧,總之就是借用emacs的指令於bash中使用
這篇要先會一點vi才會有感覺,或許不是很重要的技巧,總之就是借用emacs的指令於bash中使用
這篇重要性高於前兩篇,當你一直按向上的箭頭要找出不知多久前下的一行指令,相信我,你會很需要把這篇附的cheatsheet找出來…

ps.剛在用firefox時不小心發現,把連結拖到在寫的blogger或是google docs文章是OK的!!這簡直太省事啦!!

ps1.有提到要改命令列提示符的話,請看  [分享]加快終端機下指令速度的方法

不過這件看來簡單的小事,在ubuntu上要弄到好,其實也接近令人抓狂的程度了

重點是要知道去修改那個檔案

http://www.csie.nctu.edu.tw/~tsaiwn/course/introcs/history/linux/linux.tnc.edu.tw/techdoc/Bash-env.htm

看看這篇文章,可以了解在預設情況,ubuntu 12.04 lts 版本在使用者的目錄已經有bash_login檔了,所以一股腦的照網路上找到的文章去改.profile 只會讓自己懷疑自己的能力而已。尤其是去改~/.bashrc,套句流行語,“你很奇怪耶你” XD

提示及ls顏色暫時先這樣改了
export PS1='\[\033[1;33m\]\u\[\033[1;37m\]@\[\033[1;32m\]\h\[\033[1;37m\]:\[\033[1;31m\]\W \[\033[1;35m\][\A] \[\033[1;36m\]:\!:\#:\$ \[\033[0m\]'
alias la='ls -la --color=auto' #長目錄列表
alias ll='ls -alFGh --color=auto' #長目錄列表,目錄末端附加/符號,不列group
alias ld='ls -CFd --color=auto' #這是抄來的,其實不大清楚功能
alias l='ls -CF' #目錄末端附加/符號

# 有顏色的 man

export PAGER="`which less` -s"
export BROWSER="$PAGER"
export LESS_TERMCAP_mb=$'\E[01;34m'
export LESS_TERMCAP_md=$'\E[01;34m'
export LESS_TERMCAP_me=$'\E[0m'
export LESS_TERMCAP_se=$'\E[0m'
export LESS_TERMCAP_so=$'\E[01;44;33m'
export LESS_TERMCAP_ue=$'\E[0m'
export LESS_TERMCAP_us=$'\E[01;33m' 另外,bash script中的cd為何沒有作用呢? http://stackoverflow.com/questions/255414/why-doesnt-cd-work-in-a-bash-shell-script 答案是要設成alias

輸入法的部分我習慣用無蝦米,試過ibus, gcin,覺得還是這個最正常
https://sites.google.com/a/dayi4u.co.cc/da-yi-xing-lie-qing-song-shu-ru-fa/fu-xia-mi-shu-ru-fa

PDF中的索引和書籤(一)

在WIN7用adobe reader時,並不怎麼注意索引和書籤的分別;但是在ubuntu上發現可以自訂書籤,卻無法自訂索引後,回頭才發現WIN7不能自訂書籤,要在adobe acrobat上才可以(http://blog.yam.com/ebag/article/32389172)。這把我搞得一頭霧水啊…

由 http://blog.csdn.net/q465162770/article/details/5802151 該文初步可知,“/Type”中除了有“/Catalog(index 目录对象)”外,还有“/Outlines(bookmarks 书签大纲对象)”、“/Pages (页面组对象)”

再查 Portable Document Format Reference Manual (v 1.2) 看看,outline在94頁,catalog在75頁,還是不大懂啊…

http://ftp.gnome.org/pub/GNOME/sources/evince/3.5/?C=S;O=A
evince是ubuntu上開源的pdf viewer,抓下來看看源碼,發現在 ./po/zh_TW.po 裏有語言的轉換,看來開檔的動作主要在函式 ev_window_open_uri 當中執行,索引側欄定義在 ev-sidebar-links.c 中,bookmark側欄定義在 ev-sidebar-bookmarks.c 中,

由函式中稱為metadata的資料似乎對應到bookmarks來看,metadata應該是存在本機某個資料夾的資料,因此bookmarks並不是直接存到pdf檔中。

函式 ev_job_load_new 依序被呼叫。EV_TYPE_SIDEBAR_PAGE 是側欄的父類別,衍生出來的類別會以下列敘述宣告
./shell/ev-sidebar-attachments.c:                        G_IMPLEMENT_INTERFACE (EV_TYPE_SIDEBAR_PAGE,
./shell/ev-sidebar-layers.c:                        G_IMPLEMENT_INTERFACE (EV_TYPE_SIDEBAR_PAGE,
./shell/ev-sidebar-links.c:                        G_IMPLEMENT_INTERFACE (EV_TYPE_SIDEBAR_PAGE,
./shell/ev-sidebar-annotations.c:                        G_IMPLEMENT_INTERFACE (EV_TYPE_SIDEBAR_PAGE,
./shell/ev-sidebar-bookmarks.c:                        G_IMPLEMENT_INTERFACE (EV_TYPE_SIDEBAR_PAGE,
./shell/ev-sidebar-thumbnails.c:                        G_IMPLEMENT_INTERFACE (EV_TYPE_SIDEBAR_PAGE,

_EvDocumentLinksInterface 是做為 virtual table, 模擬 c++ virtual functions. In ev-poppler.cc:

iface->get_links = pdf_document_links_get_links;

是實際填上這個vtbl的地方,此函數中呼叫 poppler_page_get_link_mapping 來取得 mapping_list ,然後此函數離開了evince 的部分,進入 poppler 函式庫。

剛好在這時發現,poppler下的glib/demo目錄似乎有範例程式,且其中的links.c亦呼叫了 poppler_page_get_link_mapping ,似乎可以好好研究一下。又在ubuntu下建立的書籤,到底是存在那呢?應該比較修改前後PDF檔的大小即可判斷。比較結果確定書籤是存在其它地方,而ubuntu上顯示為“索引”的資料在WIN7則顯示為“書籤”。總之這又是一個命名不一致而產生的誤會。

2012年9月1日 星期六

Siri技術解析

可以看一下這篇文章http://itseer.blogspot.tw/2012/04/siri.html

不知道裏面有沒有用到stanford parser呢?

跟google的semantic web的關係,可以看這篇
http://mmdays.com/2011/11/11/would-siri-become-google-threat/

要救HTC,先做一套出來再說吧(當然你可以說那是google的事)

話說今年3月曾經有人做出土炮版siri,HTC是不是應該趕快去三顧茅蘆一下?

"An Introduction to Language Processing with Perl and Prolog"
331頁, 12.9 "Augmenting the Database and Answering Questions"
裏面說明了很多nlp在回答問題上的處理方式,也滿值得一看的

有空的話,比如說多兩個月的暑假,還想把下列的論文翻上一翻
自然语言处理主流会议近年最佳论文列表  
100 NLP Papers

Stanford Chinese Segmenter初探(二)

關於簡繁互轉的工具

http://sptuner.blogspot.tw/2012/08/convertz-v802.html 只適用win平台下,big5/gbk/unicode/utf-8/jis/shift-jis/euc-jp各種內碼之間自由轉換

http://search.cpan.org/~audreyt/Encode-HanConvert-0.35/lib/Encode/HanConvert.pm 提到以下三種方式

# iconv | b2g | iconv
# Encode::HanConvert b2g.pl -u
# Lingua::ZH::HanConvert trad2simp

再來還有cconv及opencc
根據 http://www.byvoid.com/application/opencc/ 的說法,opencc目前是最佳解了
官網在此: http://code.google.com/p/opencc/

ps.路上經過一個大陸的corpus 網站 http://www.corpus4u.org/forum/index.php  ,滿有趣的