沒穿方服

封存

顯示╱隱藏內文

有時會發現 command line 輸出怪異單引號,例如某些機器上
rm all humans
輸出 `all' 和 `humans',最左邊的符號是 backtick(`)而不是引號,難道是某種內行人的黑話?

查了一些資料,原來是錯誤的歷史用法。

簡短說明

書寫引號原本是以「」和「」為一對,不過早期電腦只支援垂直的「'」, 於是許多輸出設備把

  • 重音符號`」顯示為「
  • 單引號 「'」顯示為「

這樣輸入「``I can't''」就能顯示為「‘‘I can’t’’」—— 顯示正確,但是資料錯誤。

直到 Unicode (1991) 制定各種型式的引號,才算可以處理這個需求。
既然這個月我們還在用 Big-5 的系統報稅,看到這種引號似乎也不必太驚訝。

我的精神一直受噪音(不需要大聲)折磨。
夜半流浪狗、餐廳咀食客、車廂吸牙人、俗不可耐的電視新聞、傍若無人的蠢動、……。

在露天拍賣買了 Mack's 矽膠耳塞(4 顆,NT$ 229),真是相見恨晚。

矽膠耳塞

拆封時有包裝紙,所以照片反光;實際像黏土,顏色是胡蘿蔔色

安裝還算方便。 按一按、調一調,展開就能隔音,也不容易掉。
毋需侵入耳道(也不允許,有標明 Do not insert),所以戴起來也很舒適。

隔音程度是聽得見講話內容,但聽不見有人在你旁邊插口袋。
例子有點爛,總之大部分的聲音只是變小,不會消滅; 其餘小雜音,真的會消失

缺點是會聽到骨導傳遞的聲音,參考常見問題 13 的解釋。
自己身體的聲音,一旦在意起來,也很不自在。

Vundle 何時才會集滿 pull request

以 plugin 管理工具來說,Vundle 概念清楚、使用穩定、開發品質高(不是一個 toy project),名字也漂亮(重要); 比較不滿的是開發進度,已確認的 pull request 等了很久也沒 merge 回去,享受不到,著急。

這次整理 plugin 覺得卡在 Vundle 蠻悶的,就變節 NeoBundle 去了。

NeoBundle 是什麼

NeoBundle 的開發者是 neocomplcacheunite.vim 的作者 Shougo,他的 Vundle fork 改了太多東西,就獨立出來了。
使用上除了 :BundleInstall 的花俏畫面不見外,其他沒什麼損失; 新增功能(部份是實驗性的)則包括:

  • 鎖定 plugin 版本,有新版也不更新
    不想一直踩地雷的話,這個會很實用:
    NeoBundle 'Shougo/vimshell', '3787e5'
  • 支援 svn 和 Mercurial (hg) repository
    使用 type 參數指定 svnhg,也能從 URL 自動判斷:
    NeoBundle 'some.hg.repo.url', {'type': 'hg'}
    其實 Vundle 也有實作,但目前未採用,理由參考 Pull Request #134: Adding more DVCS support by ralesi · gmarik/vundle, 比較傾向將來以 Vundle plugin 的方式實現。
  • 自動使用 vimproc
    如果有裝 vimproc,就會用 vimproc 執行外部指令。(這個我沒用過)
  • unite.vim 介面
    用途類似 Vundle 的 interactive mode,另開 window 瀏覽 plugin,可以各別按 i 進行 Install 等操作。
    我認為 unite.vim 介面比較親切,因為不必學特殊 key mapping。
    註::Unite neobundle 基本上需要裝 vimproc,否則只有 neobundle/log、neobundle/lazy 和 neobundle/search 可用。
  • base 和 nosync 選項
    base 可以把特定 plugin 安裝在不一樣的目錄,nosync 可以讓 plugin 不自動更新,變成很例外的處理。
    NeoBundle 'muttator', {'type': 'nosync', 'base': '~/.vim/bundle'}
    我發現測試 local plugin 的時候很好用,後述。
  • build 選項
    安裝時可以自動執行指定的 script,如果 plugin 需要編譯就會有用:
    NeoBundle 'Shougo/vimproc', {
          \ 'build': {
          \     'windows': 'echo "Sorry, cannot update vimproc binary file in Windows."',
          \     'cygwin': 'make -f make_cygwin.mak',
          \     'mac': 'make -f make_mac.mak',
          \     'unix': 'make -f make_unix.mak',
          \    },
          \ }
    Vundle 作法是提供 callback 介面,不過目前還放在 events branch。
  • Lazy Load
    少用的 plugin,可以先不加進 runtimepath 以縮短啟動時間。
    NeoBundleLazy 'klen/python-mode'
    需要的時候再用 :NeoBundleSource 讀進來:
    autocmd FileType python NeoBundleSource python-mode
    或許可以用 autocommand FuncUndefined 達成自動 source 的功能。
  • 其他看不見的變更
    相信 NeoBundle 還重寫了很多東西,比如「改善 :NeoBundle 的效率」。 不過這些東西在 doc 甚至 commit log 都不很清楚,其實也是個問題。

忘掉安裝程序

從 Vundle 轉換到 NeoBundle,大致上把一些目錄、指令改名即可,安裝過程幾乎沒變。

不過整個流程還是太特殊/脫序了,我不想每次查文件,所以乾脆把檢查寫進 .vimrc,若有問題,直接提示我該怎麼做。

  1. 設定一個目錄放所有 plugin,通常是 ~/.vim(我會視環境調整)下的 bundle 目錄。
    (之後我會把預設的 runtimepath (~/.vim) 砍掉,讓 Vim 只吃 bundle 目錄裡的 script)
    然後把 neobundle.vim 加進 runtimepath,才能繼續安裝。
    if has("gui_win32")
      " g:gvim_rtp should be set by gvimrc
      if exists('g:gvim_rtp') && isdirectory(fnamemodify(g:gvim_rtp, ':p'))
        let s:rtp = g:gvim_rtp
      else
        echoerr "You must set runtimepath (for plugin bundling) manually."
        finish
      endif
    else
      let s:rtp = "~/.vim"
    endif
    
    if !isdirectory(fnamemodify(s:rtp, ':p'))
      try
        call mkdir(fnamemodify(s:rtp, ':p'), "p")
      catch /^Vim\%((\a\+)\)\=:E739/
        echoerr "Error detected while processing: " . v:throwpoint . ":\n  " . v:exception .
              \  "\nCan't make runtime directory. Skipped sourcing vimrc.\n"
        finish
      endtry
    endif
    
    execute "set runtimepath+=" . fnamemodify(s:rtp, ':p') . "bundle/neobundle.vim"
  2. 呼叫 neobundle#rc
    失敗的話就是沒裝 NeoBundle,請提示我 git clone 到剛設定的目錄。
    try
      call neobundle#rc(fnamemodify(s:rtp, ':p') . "bundle")
    catch /^Vim\%((\a\+)\)\=:E117/
      echoerr "Error detected while processing: " . v:throwpoint . ":\n  " . v:exception .
            \ "\n\nNo 'Bundle plugin' installed for this vimrc. Skipped sourcing plugins." .
            \ "\n\nTo install one:\n  " .
            \ "git clone http://github.com/Shougo/neobundle.vim.git " . fnamemodify(s:rtp, ":p") . "bundle/neobundle.vim\n"
      finish
    endtry
    註:步驟 1、2 要包進 if has('vim_starting') ... endif 才不會每次讀 .vimrc 時都做。
  3. filetype off。 這個步驟我沒研究為什麼 doc 說必須做(而且要在一開始做?),拿掉好像也沒事。
    接著移除預設 runtimepath。
    filetype off
    set runtimepath-=~/.vim
  4. 列出要裝的 plugin,最後再把 filetype 開回來。
    NeoBundle 'Shougo/neobundle.vim'
    NeoBundle 'nginx.vim'
    NeoBundle '有幾個 plugin,這裡就加幾行'
    filetype plugin indent on
    註:實際上我不在這做 :NeoBundle,而是用後述 s:bundles 處理。
  5. 這樣就完成 NeoBundle 設定了。
    進入 Vim 執行 :NeoBundleInstall 把 plugin 都裝起來。
    安裝後 :NeoBundleLog 可以看 log,個人感覺比 Vundle 的輸出有用。

自己控制 bundle 列表

把舊的 :Bundle 全部換成 :NeoBundle 也是很空虛的動作,所以我把 plugin 列表寫成陣列,這樣即使回鍋 Vundle 也比較好改。

  1. 建立 s:bundles 變數,就可以自訂選項,減少對 bundle plugin 的依賴。
    let s:bundles = [
          \   ['Shougo/neobundle.vim'],
          \   ['L9'],
          \ ]
    let s:bundles += [
          \   ['bootleq/vim-gitdiffall', {":prefer_local": 1}],
          \   ['nginx.vim'],
          \ ]
  2. 此處的自訂選項有 :skip:prefer_local
    :skip 就是不要裝,因為寫成陣列就不能直接註解掉一行了……
    :prefer_local 則是為了測試 plugin 方便,如果這個 plugin 有一份 repository 裝在 ~/repository,那就是我自己亂改的版本,請 NeoBundle 還是要讀它,但更新的時候要跳過。
    for bundle in s:bundles
      let s:tmp_options = get(bundle, 1, {})
      if get(s:tmp_options, ":skip")
        continue
      elseif get(s:tmp_options, ":prefer_local")
        if isdirectory(fnamemodify('~/repository/' . split(bundle[0], '/')[-1], ':p'))
          let s:tmp_options = {"base": '~/repository', "type": "nosync"}
        endif
      endif
    
      call filter(s:tmp_options, "v:key[0] != ':'")
      execute "NeoBundle " . string(bundle[0]) . (empty(s:tmp_options) ? '' : ', ' . string(s:tmp_options))
    endfor
    unlet! s:bundles s:tmp_options

Windows 沒有 git 怎麼辦

其實這次整理 plugin 最想做的是更新 Windows 上的 bundle,結果沒什麼進展。

最後做法是:

  1. 從有 git 的環境複製 .vimrc 和整個 bundle 目錄。
  2. gVim 的 vimrc 去 :source 真正使用的 .vimrc。