Emacs Application Framework 的折騰之路
用了Emacs將近13年了, Emacs的使用時間幾乎等于我的編程生涯, 可以說這么多年的編程能力和專注力都是靠Emacs來幫我提升的.
Emacs最大的威力是, 一旦你配置好了編程所需的一切, 它可以讓你完全生活在里面, 打開電腦只用Emacs, 關(guān)閉Emacs就直接睡覺, 所有的專注力都放在高效的編程環(huán)境中, 只需要思考, 條件反射式的動手指, 運行即可.
使用Emacs時間長了, 就希望所有的事情都能夠讓Emacs完成, 不僅僅是編程.
其實Emacs幾十年的發(fā)展, 除了編程以外, 還可以聽音樂(EMMS), IRC聊天(ERC), 甚至是終端(Multi-Term) 等等, 如果你是一個 old-school 風(fēng)格的黑客, 其實Emacs內(nèi)置的功能已經(jīng)夠你使用了.
但是我這十幾年的折騰 ( https://www.emacswiki.org/emacs/AndyStewart ), 完全不滿足于此, 我希望Emacs能編程程序員的操作系統(tǒng), 沒有過多的界面裝飾, 只用最簡潔的設(shè)計, 全鍵盤操作程序員希望的一切程序, 比如圖形化瀏覽器, 視頻播放器, Markdown實時閱讀器, 郵件客戶端等等.
這個小小的夢想, 十幾年前就有了, 但是限于當(dāng)時的編程能力, 走了很多彎路:
第一次嘗試: 2007年, 使用了Haskell編寫了一個類似 Emacs 的操作系統(tǒng): Manatee & 截圖, 當(dāng)時一口氣寫了編輯器, 終端, 瀏覽器, 音樂播放器, 文件管理器, 新聞閱讀器等十幾個應(yīng)用, 幾乎就要達(dá)到我夢想中的樣子了, 但是最后放棄了, 有兩個重要的原因: 第一、因為不知道怎么使用圖形混合技術(shù), 導(dǎo)致多個瀏覽器窗口無法共用一個buffer, 最直接的問題就是一個視頻瀏覽器頁面一旦分屏以后就會有兩個進(jìn)度和兩個聲音; 第二、編輯器模塊怎么寫也不可能有Emacs那么強(qiáng)大 (Manatee這個項目最大的貢獻(xiàn)就是, 因為Manatee要使用很多Gtk+控件庫, Gtk2hs 都沒有, 我貢獻(xiàn)了幾萬行代碼給Gtk2hs, 使得Gtk2hs成為當(dāng)年為數(shù)不多的Gtk+ Language Binding)
第二次嘗試, 2015年, 我用Vala寫了一個類似 Manatee 的項目: MrKeyboard, 但是最后也放棄了, 最主要的原因是曹哥的 Deepin-WM 窗口管理器尰烟妫克我的 Xlib Reparent 黑科技, 導(dǎo)致我沒法在 deepin 操作系統(tǒng)中運行 MrKeyboard, 加之當(dāng)時工作也非常忙, 沒有時間寫圖形混合器, 畫面同步都是在 XClient 端拷貝圖像實現(xiàn)的, 導(dǎo)致看視頻的時候非辰笕瘢卡.
第三次嘗試, 2018年, 從 deepin 退休后, 花了一個月的時間用 PyQt5 編寫了一個新的框架 EAF, EAF使用了 DBus/QtGraphicsView/XReparent 三種技術(shù)實現(xiàn)了多進(jìn)程通訊, 圖形混合器和粘貼窗口到Emacs, 利用這三種技術(shù), EAF可以讓任何圖形化的程序都可以直接在Emacs中運行, 包括瀏覽器, PDF閱讀器, 圖片查看器, 視頻播放器, 攝像頭, Org/Markdown實時預(yù)覽, 文件傳輸?shù)鹊葢?yīng)用. 這個項目徹底的實現(xiàn)了十幾年前我期望改造Emacs的小目標(biāo).
Emacs Application Framework 的目標(biāo)
- 增強(qiáng)Emacs的圖形化能力, 所有需要高性能圖形繪制的功能都用EAF來實現(xiàn)
- 讓Emacs專注于文本編程環(huán)境的開發(fā), 并保持 Elisp 現(xiàn)有的生態(tài)不會因為引入圖形化功能發(fā)生重大的變化
- 通過增強(qiáng)Emacs的圖形化插件來獲得現(xiàn)代IDE的很多能力, 使得Emacser能夠永久的生活在Emacs中.
Emacs Application Framework 的架構(gòu)設(shè)計
用最通俗的話來講, EAF其實做的工作和手機(jī)貼膜差不多, 就是先把 PyQt5 的圖形程序運行起來, 然后通過 XReparent 的技術(shù)把PyQt5的窗口粘貼到Emacs窗口對應(yīng)的位置.
EAF整體架構(gòu)的關(guān)鍵技術(shù)有以下幾點:
- 通過 QtGraphicsView/QtGraphicsSence 來實現(xiàn)實時圖形混合, 多個窗口可以共用一個進(jìn)程的繪制內(nèi)容, 這樣就可以適應(yīng) Emacs 的 Window/Buffer 架構(gòu)設(shè)計, 從而最終讓 PyQt5 窗口可以像 Emacs Elisp Buffer 那樣集成和切換, 順利的解決了當(dāng)年 Manatee 兩個瀏覽器窗口有多重音視頻的問題.
- 通過 X11 Reparent 技術(shù), 粘貼 PyQt5 的窗口到 Emacs EAF Buffer 的坐標(biāo)上, 實現(xiàn)多個進(jìn)程的窗口看起來是一個程序里面的不同部分, 不清楚 X11 技術(shù)的同學(xué), 可以想象一下 Chrome 的多進(jìn)程架構(gòu)設(shè)計. X11 Reparent 的技術(shù)除了達(dá)到貼膜的作用外, 還變相的實現(xiàn)了多進(jìn)程沙箱的設(shè)計, EAF圖形化的程序運行在單獨的進(jìn)程中, 即使出現(xiàn)了意外情況, 也不會影響Emacs本身的穩(wěn)定性.
- 在Emacs端實現(xiàn)了一個事件監(jiān)聽循環(huán), 當(dāng)用戶在 EAF Buffer按下任何按鍵, 都會通過 DBus 發(fā)送事件消息給 Python 進(jìn)程, Python 進(jìn)程再偽造相應(yīng)的事件來模擬Emacs端用戶的鍵盤輸入.
通過這種簡單粗狂的設(shè)計, EAF已經(jīng)實現(xiàn)了包括瀏覽器, 圖片瀏覽器, PDF閱讀器, 視頻播放器, 攝像程序, Org/Markdown實時預(yù)覽器, 文件共享程序等模塊.
5分鐘就可以寫好一個插件
只要你會基本的 Python 和 Qt 編程, 5分鐘就可以寫一個 EAF插件
如果你不會 Qt 也沒有關(guān)系, 看這個Qt教程, 幾天就會了.
未來的目標(biāo)
- 完善瀏覽器插件
- 實現(xiàn)更多的插件, 比如郵件客戶端, 新聞閱讀器, 終端模擬器等
- 移植EAF到 MacOS 平臺 (主要的障礙是 MacOS 平臺上怎么實現(xiàn) X11 XReparent 類似的技術(shù))
- 面向社區(qū)開發(fā)更友好的架構(gòu)設(shè)計和文檔工作