高見龍

iOS app/Ruby/Rails Developer & Instructor, 喜愛非主流的新玩具 :)

Vim

前言

在十年前開始接觸FreeBSD的時候,就聽聞過Vi/Vim這東西,那時候第一眼的感覺是:「這東西看起來好陽春,功能一定也很陽春」。當時在終端機上也還有別的編輯器可以選擇,例如Joe、Nano等,而且在本機的作業系統(Windows)也有其它的選擇,例如UltraEdit。

以前會覺得寫程式、開發軟體,沒有IDE一定沒辦法。有些程式、軟體的確是需要IDE的幫忙,不然不知道怎麼寫。直到近幾年的工作幾乎用的都是文字編輯器,才發現其實文字編輯器可以做的事情相當多。二年多前開始把作業系統換成Mac OS之後,除了要寫Flash需要開Flash IDE + Flash Builder之外,其它幾乎就是只用TextMate了。雖然說它的中文顯示問題一直被大家嫌到不行,而且傳說中的2.0版也一直沒消息,但它依舊是我開發上的首選工具。

TextMate 2實在是讓人等太久了,所以大家開始找它的替代品。不久前發現Sublime Text 2這個編輯器,它的中文字是正常的,外掛看起來也滿夠用的,而且還可以吃TextMate的bundle跟theme,本來打算換過去的時候突然出現TextMate 2的消息了,聽說中文顯示是正常的。但這時候我卻想,我還要過著這種逐水草而居的生活到什麼時候? 難道沒有一款編輯器是可以學了之後就一直用的嗎?

這時候我想到不久前才剛過20歲生日的Vi/Vim。雖然不久前陣子有練了一下手感,但沒認真下定決心要把它當成是自己吃飯的工具。於是,就找了個週末來認真的練了一下手感,發現出乎我意料的好用,之前在TextMate/Sublime Text 2上可以做的功能,在Vim幾乎都有替代品,我以前真的是錯怪它了!

以下大概是我目前有用到的外掛跟設定,不是很多,但就我自己工作上用得到的。這是我目前的樣子(其實NERDTree比我想像中的漂亮) image

外掛與設定

我的.vimrc設定

我把自己的設定檔跟用到的plugin放了一份在這裡,有興趣的朋友可以參考看看 :)

我用到的外掛:

Pathogen

用來管理外掛的外掛。以前安裝外掛,常常得把一包程式裡的各個資料夾到處撒在~/.vim資料夾裡,現在透過pathogen的話只要放在~/.vim/bundle裡就差不多行了,相當方便。

NerdTree && NerdTreeTab

Vim的檔案總管啦,當資料夾一多,沒有它不知道該怎麼工作了。

我在.vimrc裡有把NERDTreeToggle設定到F2鍵上,這樣就可以快速的打開、關閉了。

NerdCommenter

用這個可以方便的幫程式碼來做註解

SnipMate

看名字就知道它是從TextMate借過來的,如果覺得有不足的也可以自己建。

Command-T

TextMate跟Sublime Text 2都有可以快速搜尋檔案的功能,這個則是補足了Vim這方面的功能,也是我決定把Vim當做主要工具的原因之一。

  • update: 後來發現ctrlp用起來更方便,而且不需要另外compile ruby就可以使用。

Surround

可以很快的處理單引號、雙引號以及一些html常用的tag的問題,熟練的話會很方便。

Repeat

Vim內建的repeat功能在遇到某些事件的時候似乎會失效,加上這個外掛就沒問題了。

EasyMotion

可以在不需要滑鼠的幫助下,快速的切換游標的位置。

幾個自己有在用的syntax highlight以及配色

發現我幾乎整篇都是偷懶的直接貼別人的影片啊 Orz

另外如果你本來在TextMate下有喜歡的配色,也可以透過這個工具來轉成給Vim的格式。

有些外掛的更新後續都是在github上,要用的時候請注意最後更新日期。

其它工具

Alfred

付費軟體。有這個工具的幫忙,原本螢幕下方放滿的工具就可以少放很多了,要開軟體也不需要用滑鼠去點,只要輸入幾個關鍵字就可以跳出來:

image

Vimium

讓瀏覽器也用Vim的操作方式來瀏覽(Chrome限定)

Vimperator

Firefox也有類似功能的外掛可以用,感謝老杨提供。

結論

自己順手的兵器,其實應該只要一把就夠了。雖然我用的是MacVim,但會儘量避免用太多Mac專屬的設定,這樣一來我在本機的作業環境(Mac OS、Windows、Ubuntu)在切換的時候都可以有差不多的編輯習慣,甚至連遠端終端機作業的時候也不會差很多。

Vim很強大,但它不是一個可以一、兩天就能上手的工具。我相信只要學得好,它絕對是可以到哪裡都走透透的兵器。現在還不夠熟,不過我相信一直強迫自己用下去,遲早可以跟它變好朋友。(像這篇文章就是在Vim底下打的,打得很不順,但就強迫自己練習)。接下來應該就是繼續把它再磨利一點,再練得順手一些,讓自己可以更快的完成工作,有更多時間可以做自己想做的事,以及陪家人(講是這樣講.. 但大概會花更多時間再寫更多的程式碼吧)

各位如果有不錯的外掛也歡迎留言一起討論囉 :)

Automated Testing in Javascript

這是在大澤木小鐵(Jace)主辦的第一回WebDev Party上用到的投影片: image View on Speak Deck | Download PDF | Download ScreenCast

這是當天的錄影:

主要內容是分享一些我近期在做自己的產品的時候用到的一些測試工具組合及心得。原本打算用中文做投影片,但還是無法割捨漂亮的英文字體。這應該是今年的最後一場表演了,希望大家會喜歡。

有提到的工具:

  • QUnit - A easy-to-use JavaScript testing framework.
  • Jasmine - A BDD framework for testing your JavaScript code.
  • Zombie.js - A headless testing tool.
  • Sinon.js - Standalone test spies, stubs and mocks for JavaScript.
  • Phantom.js - A headless WebKit with JavaScript API.
  • Guard - A command line tool to easily handle events on file system modifications.

若有任何問題或是我講的內容有不對的地方,歡迎大家留言一起討論、指正。之後也會持續的續把一些測試JavaScript的方法跟工具整理成文章,希望可以給大家帶來一點點的幫助。

第九回 AS讀書會之測試你的 Robotlegs 專案

這是在第九回的Flash/AS讀書會上用到的投影片: image View on Speak Deck | Download PDF

部份內容是現場Demo,所以沒辦法在投影片裡看到。在分享的過程,從大家的眼神中似乎可以感覺得出來大家對於"寫測試"這件事很陌生(其實我也是新手),我之後會再花一些時間把關於如何在Flash/ActionScript裡寫測試整理成文章,希望可以讓大家可以更了解TDD(Test-Driven Development)是怎麼一回事,又該怎麼進行。

感謝大家今天天氣這麼冷還能前來參加,咱們下回見 :)

敗家之路之 Kindle 人生

放心,這不是勸敗文也不是開箱文,只是我自己最近用幾天的一點小小心得。

image

我很愛買書、看書,家裡書櫃的書已經多到快裝不下了,但仍樂在其中。每次出門,我包包裡面一定至少會放一本書,不管是等人或是通車的時候都可以拿出來翻。

自從一年前入手 ipad 後,開始把書裝進去,這樣出門只要帶一台, 如同某購物台業務所說,裡面的書就算有幾百本也不會變重,真的超方便的 XD

不過好景不長,近來我的 ipad 最近被老媽跟小朋友霸佔了,所以只好再想辦法再弄一台。這回在找替代品有給自己定幾個評估的重點:

  1. 成本。
  2. 是否方便攜帶。
  3. 是否支援之前買的電子書。

最後評估下來有兩個候選人,一個是 Kindle,另一個是 Kindle Touch,沒有選其它家的產品是因為他們的功能都太多太複雜了,而且用 Kindle 在 Amazon 買書會比較便宜。最後 Kindle 勝出的原因是它比較便宜,而且 Touch 的功能我並不需要,我只要可以看書就好。最後感謝在美國的友人的幫忙,幫忙弄了一台79塊美金的 Kindle 4。

使用感想

入手的第一個感覺是:哇,它好輕喔!

  • 電子墨水省電,聽說充一次電可以用很久。
  • 79元版本雖然有廣告,但廣告只會在非閱讀的時候出現,而且老實說廣告看起來還滿漂亮的,不會覺得不舒服或干擾。
  • 在閱讀的時候底下有個進度條,告知目前這本書讀了多少百分比,感覺像打電動會告訴你還有多少經驗值才昇級。
  • 畫面不會發光,所以長時間眼睛看起來不會太辛苦,雖然關燈就看不到了,不過即然都要關燈,表示你也該休息了。
  • 有內建字典功能,雖然是英英字典,但至少比還得另外翻字典要方便多了。
  • 可以畫重點,而且畫的重點可以另外取出來用,還會標記是在哪一本書的第幾頁。
  • 可以同步桌上版或 iPad 版的 Kindle 閱讀軟體的閱讀進度,也就是說不管在電腦上、iPad 上,或是在 Kindle 上閱讀,都可以同步閱讀進度,另外,除了自己畫的重點之外,也可以看得到別人分享出來的重點,這很棒,有共同筆記的感覺(不過這只有直接在 Amazon 上買的書才有這個功能,自己上傳的沒有)。
  • 雖然支援 PDF 格式,但因為畫面只有6吋實在太小,而且 Kindle 不支援 PDF 的 reflow,也就是說沒辦法像 mobi 格式一樣的改變字體大小。有些工具可以把 PDF 轉成 mobi 格式,但效果不佳,目前看來 ePub 轉 mobi 的效果還滿好的。
  • 除了電子書之外,現在有些方便的瀏覽器外掛,可以直接把頁面重新排版成適合 Kindle 閱讀的內容之後再傳送到 Kindle 裡,有些很棒的網站來不及看,可以透過這個工具把它存到 Kindle 裡離線閱讀,這相當好用。個人推薦"Send to Kindle“(Chrome 限定)。

我大部份的書都是電腦相關的,遇到有程式碼的時候,我發現其實橫著看就滿舒服的,像這樣:

image

而且這樣我一樣單手就可以很輕鬆的拿著,大拇指可以用來按翻頁鈕,相當沒負擔,這也這也是我當初沒選 Touch 的原因之一。

其它週邊

我知道有些人會比較保護心愛的東西,可能會買皮套或是保護貼之類的。我偶爾也會,但我覺得 Kindle 並不需要太多的保護措施。因為目前坊間大部份的皮套重量可能就比 Kindle 本身還重了,當初選擇 Kindle 的原因之一就是因為它很輕便、好拿,沒道理要再加個皮套來增加重量。螢幕保護貼更是不需要了,因為不是 Touch 機種,螢幕也不太會弄髒。不過因為 Kindle 很輕,可能還滿容易不小心手滑飛出去,也許加個果凍套邊框之類的如果不會妨礙翻頁的話還滿 ok 的。

我不保護它不代表我不愛惜它,而是就像一般的書一樣,書,是買回去讀的,不是買回去擺好看的 :)

結論

Kindle 對我來說,可能真的是開啟了另一條敗家之路了,重點不在機器本身,而是因為買 Kindle 版的電子書,不只速度快,而且幾乎都比一般印刷版本還要便宜個幾塊美金,甚至有到對折的。如果買一本書便宜 5 塊美金的話,買個十幾本那台 Kindle 的成本就回來了,方便又便宜,真的會讓我之後少跑很多次的天瓏書局了。(或是可能在天瓏看到喜歡的書,然後從 Kindle 直接下單..orz)

我知道工程師們常會有「拿到新的 3C 產品不 root 一下會很不舒服」的症狀,看看能不能 hack 一下,幫它加功能讓它變得功能更強大或什麼的。我不覺得這樣做有什麼意義,對我來說,當初買 Kindle 的用途就是拿來看書的,其它的就不要想了。想要多功能的,也許你該考慮是不是用平板電腦就好。Kindle 裡面有內建瀏覽器,但我想非必要的時候大概也不會用到它。這些額外的功能通常帶來的結果就是「分心」,那不是我想要的。

幾個重點:

  • 不要把它當電腦用。
  • 不要把它當 ipad 用。
  • 只要把它當書用。

以上是我自己最近使用的一些簡單心得,跟大家分享 :)

幫你的 Octopress 增加文章分類

發現在 Octopress 似乎沒有現成可以放在 sidebar 的分類,於是便自己動手刻一個,順便練一下手感。程式碼短短的,使用方法也很容易,首先你可以按下面程式碼區塊右上角的 download,並將檔案存在 Octopress 的 plugins 資料夾:

(category_list.rb) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# encoding: utf-8
module Jekyll

  class Site

    def create_category_list
      write_to_tag_cloud if @config['category_tag_cloud']
      write_to_sidebar if @config['category_sidebar']
    end

    private
    # generate category tag list and write to 'source/_includes/asides/categories_tag.html'
    def write_to_tag_cloud
      puts ' => Creating Categories Tag Cloud'
      lists = {}
      max, min = 1, 1
      @categories.keys.sort_by{ |str| str.downcase }.each do |category|
        count = @categories[category].count
        lists[category] = count
        max = count if count > max
      end

      html = ''
      lists.each do | category, counter |
        url = get_category_url category
        style = "font-size: #{100 + (60 * Float(counter)/max)}%"
        if @config['category_counter']
          html << " <a href='#{url}' style='#{style}'>#{category.capitalize}(#{@categories[category].count})</a> "
        else
          html << " <a href='#{url}' style='#{style}'>#{category.capitalize}</a> "
        end
      end

      File.open(File.join(@source, '_includes/asides/categories_tag.html'), 'w') do |file|
        file << """{% if site.category_tag_cloud %}
<section>
<h1>#{@config['category_title'] || 'Categories'}</h1>
<span class='categories_tag'>#{html}</span>
</section>
{% endif %}
"""
      end
    end

    # generate category lists and write to 'source/_includes/asides/categories_sidebar.html'
    def write_to_sidebar
      puts ' => Creating Categories Sidebar'
      html = "<ul>\n"
      # case insensitive sorting
      @categories.keys.sort_by{ |str| str.downcase }.each do |category|
        url = get_category_url category
        if @config['category_counter']
          html << "  <li><a href='#{url}'>#{category.capitalize} (#{@categories[category].count})</a></li>\n"
        else
          html << "  <li><a href='#{url}'>#{category.capitalize}</a></li>\n"
        end
      end
      html << "</ul>"
      File.open(File.join(@source, '_includes/asides/categories_sidebar.html'), 'w') do |file|
        file << """{% if site.category_sidebar %}
<section>
<h1>#{@config['category_title'] || 'Categories'}</h1>
#{html}
</section>
{% endif %}
"""
      end
    end

    def get_category_url(category)
      dir = @config['category_dir'] || 'categories'
      File.join @config['root'], dir, category.gsub(/_|\P{Word}/, '-').gsub(/-{2,}/, '-').downcase
    end
  end

  class CategoryList < Generator
    safe true
    priority :low

    def generate(site)
      if site.config['category_list']
        puts "## Generating Categories.."
        site.create_category_list
      end
    end
  end

end

程式碼寫得有點髒,應該有更漂亮的寫法 :)

再來,請打開根目錄的_config.yml,加上一些設定:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# ----------------------- #
#    Categories           #
# ----------------------- #
# create categories page
category_list: true
# use counter after categories
category_counter: true
# category title
category_title: 分類
# create an include categories list in @source/_includes/asides/categories_sidebar.html
# and don't forget to add 'asides/categories_sidebar.html' into @default_asides if you want to enable it.
category_sidebar: true
# create an include categories tag cloud page in @source/_includes/asides/categories_tag.html
# and don't forget to add 'asides/categories_tag.html' to @default_asides if you want to enable it.
category_tag_cloud: true

其中,category_list就是用來啟用是否產生側類分類的;category_counter就是用來決定要不要秀出計數器,category_title是那個區塊的標題,category_sidebarcategory_tag_cloud打開的話,則各會產生兩個用來include的檔案。category_sidebar的效果就是一個一個的排下來,但如果你的文章分類很多可能會讓頁面拉很長,如果不喜歡,也可以改用category_tag_cloud的呈現效果。

產生完檔案還不夠,你還需要在_config.yml加一下你要include的區塊,以下是我自己的設定,請依個人需要修改:

1
default_asides: [asides/about.html, asides/recent_posts.html, asides/categories_tag.html, asides/googleplus.html, asides/plurk.html, asides/recent_comments.html, asides/twitter.html, asides/links.html, asides/advertise.html]

最後,重新rake generate之後應該就可以看到成果了,就如同你現在正在看的這篇文章的右手邊分類一樣的效果。

為了tag cloud看起來不會太擠,你可能會需要用CSS來調整一下line-height

不確定這樣做是不是最好的做法,而且有些程式碼我還是硬寫在Ruby裡的,如果有更好的做法還請不吝告知 :)