解決在 Vim NERDTree window 裡誤切換 buffer 的問題

這篇是承自之前提過的問題,今天終於花了一點時間,看了一下 NERDTree 的 source code 找出解法。

在自己的 .vimrc 裡新增這麼一段自訂 function:

function! LeaveNERDTree()
  if winnr() == g:NERDTree.GetWinNum()
    wincmd p
  endif
endfunction

大概的邏輯是這樣:

  1. 如果目前所在視窗的號碼等於 NERDTree 的視窗號碼
  2. 不管怎樣,跳開就對了,cursor 就是不要在 NERDTree 裡面

然後就可以套用到自己切換 buffer 的快速鍵上:

nnoremap <silent> <F3> :call LeaveNERDTree()<CR>:bprev<CR>
nnoremap <silent> <F4> :call LeaveNERDTree()<CR>:bnext<CR>

短短幾行,解決了長期以來的、常常為了自己操作錯誤而惹得很毛的問題,怨自己當初為什麼沒仔細去看 source code?

Game & Watch EG-26: EGG

昨晚,幫老婆找出童年時玩過的掌上型電玩「接雞蛋」,前因是我跟強者我同事 hSATAC 借 PS Vita 玩,被她看到又再問了一遍:「有『接雞蛋』嗎?」這是她不曉得第幾次提到「接雞蛋」了。心想平常不碰電玩、最多只玩手機休閒遊戲的她,看到別人在玩掌上型電玩就會聯想到「接雞蛋」,就像提到電視遊樂器就有很多人聯想到「超級馬力歐」那般懷念的經典?

用 “Game and Watch Egg” 去搜尋,因為這類液晶電玩,任天堂的 Game & Watch 當然是最知名系列產品,其次應該是 CASIO。

先問是不是就是影片中的這款:

老婆猛點頭說對,看來沒有比我也很懷念的 Game & Watch MW-56: MARIO BROS. 難找。

於是再往 Google Play 上找看看有沒有 clone 這款的遊戲,果然有,而且還不少人做!而 MW-56 這款搬貨工馬力歐兄弟卻沒人 clone,我難過。

看了一下維基百科才明白,原因是 EGG 這款當年在蘇聯有仿製品,所以可能是「國際」(←又是大叔的雙關語冷笑點)知名度最高的一款 Game & Watch,也解釋了為何 Google Play 裡找到的仿製遊戲面板是俄文。

頭一次見到老婆玩遊戲玩得這麼開心,比上次「打飛機」還開心。其實不管是「接雞蛋」還是「搬貨工」遊戲規則都很簡單,變化只在速度與偶爾的例外攪局,就能帶給人樂趣,在這個凡是遊戲都要 3A 級才上得了市面、看得上眼的時代,其實回頭想想,我們在追求無止盡的聲光效果進化時,是不是先問問「我這樣玩得開心嗎」?

之前在巴哈姆特裡不時有針對「任飯」「你們說任天堂作品的『遊戲性』較高?什麼叫『遊戲性』?你們自己都說不上來!」這樣的攻擊。我現在想想,「遊戲性」其實就是一種 UX(用戶體驗),或許 UI 有 guideline 可以遵循,但是光跟著 guideline 做,不代表你就能營造出讓人覺得 “Awesome!”, “Incredible”, “Wonderful” 的 UX。

嘗試做一個 envchain 的仿品 (6)

最近這幾天,下班後沒什麼動力,而且胃病又找上門,更是折磨人,還是沒有什麼明顯的進度。看了一下 dbus-rs 給的範例裡滿滿的 unwrap(),很好奇這方法是何作用,便搜尋了一下:

To “unwrap” something in Rust is to say, “Give me the result of the computation, and if there was an error, panic and stop the program.”

原來是一個錯誤處理用的便捷(且看來有點暴力?)方法。

嘗試做一個 envchain 的仿品 (5)

今天沒有什麼特別的進度,就是慢慢地把 Ruby PoC code 往 Rust 改寫而已。因為想要採行 TDD,所以按照  convention 為專案加上 tests/ 目錄,測試程式就可以放在裡面。過程當中因為同檔名程式的關係在鬼打牆,還以為怎麼程式就是無法跑出預期的結果。

同時把 rustfmt 架起來,仿照 gofmt 自動在我用 VIm 儲存 Rust 程式時自動排版程式碼。

嘗試做一個 envchain 的仿品 (4)

剛剛試了一下 writePassword(),沒問題,可以用 key-value pair 的方式儲存想要保密的資料:

require 'dbus'
require 'pp'
 
session_bus = DBus.session_bus
 
kwalletd_service = session_bus["org.kde.kwalletd5"]
kwalletd_object = kwalletd_service.object "/modules/kwalletd5"
kwalletd_object.introspect
kwalletd_interface = kwalletd_object["org.kde.KWallet"]
handle = kwalletd_interface.open("kdewallet", 0, "Ruby D-Bus Client").first
pp kwalletd_interface
 
kwalletd_interface.createFolder(handle, "envpick", "Ruby D-Bus Client")
pp kwalletd_interface.folderList(handle, "Ruby D-Bus Client")
 
kwalletd_interface.writePassword(handle, "envpick", "key-0", "value-0", "Ruby D-Bus Client")
kwalletd_interface.writePassword(handle, "envpick", "key-1", "value-1", "Ruby D-Bus Client")
pp kwalletd_interface.entryList(handle, "envpick", "Ruby D-Bus Client")

完全符合我的需求。

嘗試做一個 envchain 的仿品 (3)

ruby-dbus 去戳 D-Bus,可以順利解出 KWallet 的…binary 資料?

require 'dbus'
require 'pp'
 
session_bus = DBus.session_bus
 
kwalletd_service = session_bus["org.kde.kwalletd5"]
kwalletd_object = kwalletd_service.object "/modules/kwalletd5"
kwalletd_object.introspect
kwalletd_interface = kwalletd_object["org.kde.KWallet"]
handle = kwalletd_interface.open("kdewallet", 0, "Ruby D-Bus Client").first
pp kwalletd_interface
pp kwalletd_interface.folderList(handle, "Ruby D-Bus Client")
pp kwalletd_interface.entryList(handle, "Network Management", "Ruby D-Bus Client")
pp kwalletd_interface.readMap(handle, "Network Management", "{????????-????-????-????-????????????};802-11-wireless-security", "Ruby D-Bus Client").first

翻了一下網上資料才知道是這個原因:[Bug 256155 – KWallet’s readMap is not friendly to non-C++ applications],昏倒,這同時解釋了為什麼 kwallet-query 這專用工具可以解出 human readable 的密碼,而泛用工具不行。

以上只是想要瞭解 KWallet 的操作,為之後的 coding 鋪路,實務上應該還有路可繞。為了泛用性,最多就是不要用 map 而已。

嘗試做一個 envchain 的仿品 (2)

在 qdbus 上面試著操作 KWallet 資料,撞了不少牆。參考 [Learning on the Job: Accessing the KDE Wallet from the Cmdline] 這篇,目前還是不曉得怎麼用 qdbus 取出 NetworkManager 儲在裡頭的 Wi-Fi 密碼,當然在 KWallet Manager 裡頭是沒問題的,用

kwallet-query -r "{????????-????-????-????-????????????};802-11-wireless-security" -f "Network Management" kdewallet

也可以取出密碼,但是用 qdbus 就是卡在最後不曉得怎麼把

qdbus org.kde.kwalletd5 /modules/kwalletd5 org.kde.KWallet.entryList [handle] "Network Management" "Testing"

得到的 entry 去推出 key-value。無論是用 org.kde.KWallet.readMap 抑或 org.kde.KWallet.readMapList 都得不到我預期的回傳結果,目前只能先猜是我不知道怎麼用這工具的問題。晚一點可能可以來試試用 Ruby 去戳 D-Bus。

嘗試做一個 envchain 的仿品 (1)

前幾天在公司跟同事聊「果黑」、「果粉黑」話題時順道聊到的:「Linux 上似乎還沒有一個像 envchain 這樣使用系統內建密鑰管理系統(如 OS X Keychain, GNOME Keyring, KWallet)來維護環境變數的同質產品,看是不是可以用 Rust 刻一個?」於是這幾天就在做一些基礎研究。

其實 envchain 程式最關鍵處,就是從 Keychain 取出來環境變數,然後在呼叫 execvp() 執行程式時加上這些環境變數,原理不難懂。

我自己使用的桌面環境是 KDE Plasma,所以預設的密鑰管理系統就是 KWallet。一開始直接去 Google 搜尋 “KWallet API”,心想大概就是要用 FFI 之類的去 call C ABI 來解,雖然很硬斗,但是也還能接受。

再找了一下既有的 Rust crates 資源,以及瞄了一下 KWallet 的 package 內容檔案列表,發現其實不用這麼硬幹,透過 D-Bus 的介面就可以操作 KWallet API。

我的自炊(書籍電子化)經驗

由於書架滿了,且我沒有錢買間大房子,所以才決心買了這組「自炊」工具:

  • Brother ADS-2000 雙面文件掃描器
  • GREENON Meteor A3專業級裁紙機

加起來共一萬五千多,雖然要價不斐,但還是比起某些大大買的、更強大的組合要便宜個至少五千,也比買一間房子便宜

Brother ADS-2000 原本是看中它的可以直接插 USB 儲存裝置、直接掃成 PDF 功能,但是我手邊的任一 USB 碟它都不吃,我只好當作沒這個功能,退而求其次,回到連接電腦的方式來進行掃描作業。

GREENON Meteor 則比我預期還要好用,但是拆書的時候,還是得先用美工刀先將書不斷對切到約十張左右的小份,才能去裁邊,這是省不下的細工。

Brother ADS-2000 有提供 Linux 驅動程式,但是只有 *.rpm 與 *.deb 的套件格式,於是我還是上 AUR  去找好心的大德已經包好的 brscan4,順利在我的電腦上驅動這台掃描器,且 XSane 連它的雙面掃描功能 (Duplex) 都有對應支援,可以完整發揮它一次饋紙就掃雙面的功能,這台在 Linux 上功能也不打折,價格也頗實在,我很滿意。現在買還送標籤機跟印表機,真是吃撐我了,家裡都沒空間了還送我這麼多東西。

掃描好的影像檔,再送到 Scan Tailor 去處理校正歪斜、裁去白邊、去雜點、調整輸出濃淡後,輸出成 *.tif 檔。

接著再用

tiffcp -a scan-*.tif book.tif

將多個 TIFF 檔合併為單一多頁 TIFF 檔,

tiff2pdf -z -o book.pdf book.tif

將這個單一多頁 TIFF 檔轉為 PDF 檔,就大功告成。

如果沒有雙面文件掃描器與裁紙機的輔助,只用傳統平台式掃描器與美工刀,我看一本紙本書轉成電子書的工作大概要花上好幾天,且很可能這些人工繁雜到會讓你想半途而廢,所以如果要搞自炊,請至少一定要買一台雙面文件掃描器,它會讓整個作業不只變快,也減少失誤。

既線上又離線的 The Rust Programming Language 讀書會 (1)

前因:強者我同事揪的讀書會,要讀 [The Rust Programming Language]。我礙於家庭因素,不便親至,所以想跟著當次進度看,遠距參與,有點像函授學校吧。(啥?)

關於  Rust 這個語言,我不算陌生,但說嫻熟也還差得遠。因著這個機會,能促使自己把它有系統地學好,也是福氣,所以在此先感謝 BobChao 的慫恿,括號笑。

如果不小心路過讀到這篇的您,對 Rust 還一無所知,我想先為您引介:

  • 這是 MozillaSamsung 合作的新一代瀏覽器引擎 Servo 所使用的最主要語言。能寫「瀏覽器」這個應該是當前消費者市場上最複雜的軟體,我想以一個系統程式語言來說,應該可以佐證它的能力足堪重任。
  • 另外,庄晓立先生的〈为什么我说Rust是靠谱的编程语言〉這篇文,寫得很生火(令人想躍躍一試的意思),但是論述很實在、不浮誇,我也推薦一讀。

倘若您看完上述介紹,覺得 Rust 值得跳進來玩玩,竭誠歡迎跳坑。

接下來就是我自己的讀書筆記了。(遠目)