月份: 2016 年 5 月

  • 解決在 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 而已。