沒穿方服

索引

顯示╱隱藏內文

目前 redis db 我們只用在 rails 頁面快取用途,用過的管理工具僅 telnet。 常做的是 MONITOR 看存取狀況,為什麼行為不如預期, 然後基本的 DEL 把舊值砍掉而已。

Telnet 互動輕快,monitor 的即時性也很方便,不過每次連進去下 monitor 有點麻煩, 而且 SET 系指令會噴大塊字串(顯示寫入的值)洗畫面,太噁心了。

於是寫了個 rails 的 wrapper script, 依賴 redis-rb,且需要某處有 config/redis.yml 寫好連線用的參數
→ 簡易 redis client: scripts/redis-client — Gist

啟動方式

  • 連到 production → ./script/redis-client production
  • 連到 staging,且只顯示 key 開頭為 "staging" 的存取 → ./script/redis-client staging -f \\A\"staging

功能

  • 直接進入 monitor 狀態,可以輸入 m 暫停/繼續 monitor 的輸出。
  • 命令列選項 -f pattern(或 --key-filter=pattern)指定只 monitor 符合的 key,不符就不顯示(只影響 SET、GET 等有 key 的指令)。
  • del 接受 pattern,例如 del *foo*(pattern 會傳給 redis KEYS 指令)。
  • grep 指令,例如 grep foo\\d+(對 KEYS 結果作 ruby grep,這裡 pattern 是 ruby 的 Regexp)。
  • 部分輸出有 pretty print,另 SET、SETEX 不顯示寫入的值(而是值的長度)以節省畫面空間。
連到 staging,Flush All

License: public domain.

情況已稍微好轉

兩週前,終於更換了辦公室的座位,否則我是一秒也難以忍受。
這是一場長病,對工作的責任、與同事的相處、……這些事情,後期為了讓自己舒服一點,我大概都顧不得了。
坐視情緒惡化影響生活,其實有點恐怖,不過當下空白又蓋過恐怖。

症候群

也許基於工具和習慣,我勉強可以繼續開發工作(雖然品質有差),但已經無法平靜思考。 心思會被莫須有的疑問佔據,為什麼有人可以若無其事地插隊(車站)、為什麼下一代的行為跟上一輩同樣醜陋、為什麼這個社會怎樣怎樣…… 能不能施我一個恩惠,我的願望就是 put them to death ——而儘管這麼妄想,卻又認定他們不是真正敵人,嚴肅來說有所保留,有所矛盾。

我的心情愉快不會超過一分鐘。 一個好例子是在通勤中,養成了留意路人嘴巴的習慣,凡是雙唇不閉起來的,除了說話、笑容外,皆引起我的憤怒。 你知道這樣的人有多少嗎? 我開始觀察,結果停不下來了。 這個問題可以積極解決嗎? 我看不行,至今仍受其擾。

成因

環境沒有大改變、刺激一直差不多,但是反應方式變成會特別放大厭惡因素; 像養成運動習慣一樣,不斷訓練怨恨神經,超過半年的實作累積,黑特系統就變得如此 robust 了。

期間同事扮演一個關鍵的被針對角色,可能是接觸時間長、避不掉,所以我理智認為會這麼痛苦,主要是這個人的關係。 註:這個針對只是一個參考(reference),並非否定一個人的人格,換作某些我尊敬的人,同樣會變成痛苦來源。

解救措施

雖然寫得好像很嚴重,但外在應該感覺不太出來。 在被動的時機把話說明了,碰巧也有機會換座位,才得到改善。
人際關係的傷害多少有吧,而接下來要怎麼根治,又是另一個療程了。


播放技術死的次數也大幅增加,大約一天會聽完一輪

Vim 開啟大檔案會變慢、慢到難以忍受的問題,通常停用一些功能就會改善了。 極端點用 vim -u NONE filename(不讀 vimrc 也不開任何外掛)開檔,就知道是檔案太大還是設定問題。

Dr Chip 的 LargeFile plugin 就是在偵測到大型檔案時,自動關閉 syntax、folding 等昂貴功能,離開 buffer 時再調回來。 使用上不必多做什麼動作,就能達到明顯加速效果,20 萬行的 rails log 開起來也沒什麼感覺。


原版 LargeFile 設定較少,所以我的 .vimrc 一直有整段抄襲版的 BigFile 實作,用了好幾年,一直有解不開的怪問題,發作起來會把全域 'undolevels' 設為 -1 害我完全不能 undo,非常困擾。

這次直接 fork 原版 LargeFile,程式先重構一下,居然就解掉了……
自訂的選項也都加了進去,專案在 bootleq/LargeFile,再測一陣子就會送交原作者處置。


具體設定例

基本選項,就這幾個:

let g:LargeFile           = 40            " 超過這個 size 才會處理。 預設是 20
let g:LargeFile_size_unit = 1024          " g:LargeFile 的單位,1024 就是 KB。 預設是 MB
let g:LargeFile_patterns  = '*.log,*.sql' " 只處理 log 和 sql 檔案。 預設是 *
let g:LargeFile_verbose   = 0             " 不要顯示訊息(例如 LargeFile 生效時)。 預設是 1

LargeFile 會停用 FileType autocmd,如果想對特定檔案動手腳,可使用新增的 autocmd 事件:

autocmd User LargeFileRead call s:large_file_read()   " 每次 Large File 發生 BufRead 時發動
autocmd User LargeFile call s:large_file_detected()   " 偵測到 Large File 時發動,包含 :edit! 或 jump 進入時

function! s:large_file_detected()
  let ext_name = expand('%:e')
  if ext_name == 'log'
    " nnoremap <buffer> <LocalLeader>ddd :EmptyFile<CR>   " 按這個鍵把 log 全清掉(實作省略……)
  endif
endfunction

function! s:large_file_read()
  let dir_name = expand('%:p:h')
  if dir_name =~ '/home/www/some_rails_app/\(\w\+/\)\?log'
    if &fileencoding != 'utf-8'   " 不是 utf-8 就重讀吧
      edit! ++enc=utf-8
    endif
    syntax match railslogEscape '\e\[[0-9;]*m' conceal    " 有這個才不會看到一堆色碼(需要裝 rails.vim)
  elseif dir_name == '/home/www/logs'
    set syntax=httplog    " 上色(需要裝 httplog)
  endif
endfunction

xml.vim(原 vim script 1397)這個 plugin 提供一些小功能,寫 HTML 的時候很實用。
不過檢討一下發現,我只用到其中一兩個 mapping 而已…… 最後決定移除,自己重製。

各種功能重現

  • 自動關閉 tag

    <div 後面輸入 > 時,會自動補上 </div> 並把游標放回 tag 中間。
    現改為以下 function,按 >> 發動。
    inoremap <buffer> >> <C-\><C-N>:call <SID>html_close_tag()<CR>
    function! s:html_close_tag()
      " Find < or >, should take action only when < appears first.
      if search('\v(\<)|(\>)', 'bnpW') == 2
        let missing_gt = getline('.')[col('.')-1] == '>' ? '' : '>'
        execute "normal! a" . missing_gt . "</" . "\<C-X>\<C-O>" . "\<C-\>\<C-N>F<"
        call feedkeys('i', 'n')
      else
        call feedkeys('a>>', 'n')
      endif
    endfunction
    無論在 <div<div> 後都能正常運作。
  • 將 tag 拆為多行

    前述 <div>|</div>再按一次 >(| 為游標位置)的話,tag 會被拆為
    <div>
      |
    </div>
    這個我沒做。 但可配合下面的 function 改為按 >> 後再按 ;; 達成。
  • 自動建立 tag

    輸入 div;; 就會展開為
    <div>
      |
    </div>
    且如果該 tag 前面已有文字,就不會拆為多行,而是變成單行的 <div>|</div>
    新的實作如下:
    inoremap <buffer> ;; <C-\><C-N>:call <SID>html_make_tag()<CR>
    function! s:html_make_tag()
      let save_reg = [getreg(), getregtype()]
      execute "normal! a \<C-\>\<C-N>db"
      let tag_name = @"
      call setreg(v:register, save_reg[0], save_reg[1])
    
      " Skip invalid tag_name (non-words)
      if tag_name =~ '\W'
        " Special case to break single-line tag into multiline form. (that is, 'make' an existed tag)
        " e.g.: when input ;; between <div></div>
        if tag_name == '>' && search('\%#\s*<', 'cnW', line('.'))
          execute "normal! cl" . tag_name . "\<C-\>\<C-N>a\<CR>"
          call feedkeys('O', 'n')
        else
          execute "normal! cl" . tag_name
          call feedkeys('a;;', 'n')
        endif
        return
      endif
    
      let unaryTagsStack = get(b:, 'unaryTagsStack', "area base br col command embed hr img input keygen link meta param source track wbr")
      if index(split(unaryTagsStack, '\s'), tag_name, 'ic') >= 0
        execute "normal! a<" . tag_name . ">"
        call feedkeys('a', 'n')
      else
        " Don't break tag into multi lines if current line is not empty.
        if getline('.') =~ '\S'
          execute "normal! cl<" . tag_name . "></" . tag_name . ">\<C-\>\<C-N>F>"
          call feedkeys('a', 'n')
        else
          execute "normal! cl<" . tag_name . ">\<CR></" . tag_name . ">\<C-\>\<C-N>O"
          call feedkeys('"_cc', 'n')
        endif
      endif
    endfunction
  • 在開/關 tag 之間移動

    <div> 上按 % 就能跳到 </div> 的位置,也可來回跳。
    這個其實不必裝 xml.vim,啟用 matchit 就能辦到了,見 :help matchit
  • change 外圍 tag

    <di|v>foobar</div>\c,可以把成對的 div 取代為別的值。
    這個也不必裝 xml.vim,改用 surround.vim 比較實在。
    按鍵是 cst< (Change Surrounding Tags with Tag...) 就會提示你輸入 tag name。

備註

  • 本文的 2 個 inoremap 正確用法是在 filetype 為 html 時才生效。
  • 以上實作會依賴一些選項,譬如 auto close tag 是藉由 </ 後的 omni-completion 達成,換行部分可能也需要正確的 indent 設定。
  • xml.vim 還有一些額外功能,例如處理 HTML comment 什麼的,因為沒在用,我就沒研究了。

zsh 還未正式支援 cap (Capistrano) 自動完成,不過以下專案有實作:

  • zsh-users/zsh-completions
    準官方的 _cap function,能補全命令列參數和 tasks。 不過沒做快取,使用上有延遲感。
  • oh-my-zsh
    只能補 tasks,且不包含 task 的說明。
    有快取,會在 Rails 目錄下存一個 .cap_tasks~ 暫存檔,當 config/deploy.rb 變動時更新。
    問題是比較過時,至少要等 Pull Request #367 後才支援 Capistrano 2.0。

我不用 oh-my-zsh,所以我想你們也不會。

好掌握的擴充方式是自己 mkdir 放自己的補全方數,譬如放 ~/.zsh/completions/,就要配合 .zshrc 這麼寫(在 compinit 之前):

# user completion plugins
if [[ -d ~/.zsh/completions ]]; then
  fpath=(~/.zsh/completions $fpath)
fi

我選擇 oh-my-zsh 的 task 補全(不顯示說明,比較簡短)和快取(但換成擺到 tmp/ 裡),加上 zsh-completions 的選項補全。 組成的 ~/.zsh/completions/_capistrano 內容在 zsh _capistrano completeion function — Gist