SITE OBSOLETE. GO AWAY.

Visit uranusjr.com for updates.

I Moved

我搬家了。

每次被看到我用 Logdown 就會被念,總算還是受不了走上自己架站的老路。網站前陣子就上線了,不過 blog 文章和 Disqus 這陣子才搬得差不多。

有些比較沒價值的文章懶得搬,所以這邊還是會留著當參考用(當然我也是有備份以防 Logdown 哪天看我不爽,雖然他們應該是懶得理我XD)。Disqus 能 migrate 的都搬走了,所以這邊也就不開放留言。

總之,如果你還在看這裡的話,請把你的書籤修改爲新的部落格網址 http://uranusjr.com/blog/ 或者網站首頁 http://uranusjr.com/。新網站有 RSS(和 Atom)所以也歡迎訂閱。

新站見! :)

動態欄位的 Reusable Search Mixin View

Python, django, 2sod, taipei.py,

本周的 Django Workshop(2013-12-24) 講到了 Two Scoops of Django 第九章: Common Patterns of Forms。Alfred 在最後提到書上有一個 Reusable Search Mixin View,但是說以他自己的狀況而言,因為跨 model 的 field names 通常不一樣,所以這個 pattern 比較派不上用場。

當時我補了一句「其實這個還是有解」,本來打算稍後討論的時候提出來,不過後來被 Andy 拱上去講 naming convention 就完全忘了這件事,直到現在。 orz

所以我現在要來彌補這個錯誤。

寫出能在 Python 2 直譯器執行的 Python 3 程式:良好的 Coding Style

Python, Python3, six,

上一篇文章結束前,我列出了 Python 3 與 Python 2 不相容的主要原因,並將它們分成三類:

  1. 可以藉由建立 coding style 達到語法上(syntactic)完全相容。
  2. 可以藉由簡單的手段達到完全相容。
  3. 沒有簡單的方法可以處理。

在這篇文章中,我會討論第一種類型,也就是可以直接藉由良好的 coding style 解決的問題。Python 3 的很多新功能其實都有被 backport 回 Python 2.6 與 2.7。只要注意使用新的寫法,就可以解決很多 Python 3 的不相容問題。事實上, 即使你完全沒有用 Python 3 的打算,新寫法還是比較好,因為它們通常更為清晰,也被大多數人所喜愛。

寫出能在 Python 2 直譯器執行的 Python 3 程式

Python, Python3, six,

我前陣子在 Facebook 發了一個動態

然後 Tim Hsu 就在下面留言表示想聽 six 的東西。six 是個好東西(很重要所以再說一遍),我不排斥分享一些心得,不過一來 six 很短,二來要準備 talk 很麻煩,三來沒什麼機會可以講,四來可能也沒有太多人想聽我講話,所以最後決定不如更新一下好久沒動的 blog。

可是還有一個問題:six 很短。如果光講它,這篇文章會沒什麼內容。所以不如就把主題定得廣一點,也會對比較多人有用。:)

Qelly 1.0 alpha 3 登場

qelly, c++, qt,

抱歉這幾天因為私人問題,所以遲到今天才能把更新放出來。還是感謝大家的協助,這次的問題修正幾乎全部都是網友回報,沒有大家當白老鼠幫忙測試這些問題都不可能被找出來。

老樣子,原碼與 Windows 版 binary 仍然可以從 GitHub 發佈區取得。若有任何問題與建議同樣請麻煩回報。這個版本基本上已經沒有增加什麼新功能了,如果沒有意外下一個版本就會進行 feature freeze 進入 beta。之前答應的自動字型調整目前還有問題,我會持續看看能不能趕上下一版,否則就等 2.0 吧。:(

這個版本主要針對小螢幕的顯示狀態進行修正,主要是讓工具列被隱藏時仍然可以(以彈出視窗)顯示位址列。另一個功能是我私心希望的,參考常見 terminal 軟體的作法,把滑鼠中鍵對應到(純文字)貼上。其他就是一些 UI 問題與臭蟲修正。

Qelly 1.0 alpha 2 發佈

qelly, qt, c++,

Qelly 1.0 alpha 2 發佈!感謝大家提供的問題回報和其他建議,很多東西如果沒有大家提出來我應該很難自己想到。

Windows binary 與原碼同樣由 GitHub 發佈,請至發佈區下載。新的功能已經著手進行中,目標是完成自動字型調整(#45),當然如果本版發佈後出現新的問題也會一併修正。

這個版本最重要修改是新增了許多人想要的「可攜版」功能。實作方法採用了 @Wcw5504 的建議,當 Qelly 執行檔的相同目錄下存在一個名稱為 PORTABLE 的檔案(注意不可有副檔名)時,便會進入可攜模式。在可攜模式下,Qelly 的設定(含站台與表情符號)會存放於一個叫 data 的子目錄,而不是使用者的個人目錄。

Qelly: Yet another BBS client

qelly, qt, c++,

Qelly 1.0 alpha 版發佈!可以從這裡找到 Windows binary 載點。

Qelly (發音同英文名 Kelly) 是我最近在玩的 BBS client project。本來是我等當兵的時候 (2011) 無聊寫的東西,最近因為常用 Windows 覺得 PCMan 不合用才挖出來繼續,一些功能補完之後現在基本上告一個段落了,所以拿出來分享一下順便拐測試員

不用安裝,沒有 (Windows) registry,只會在你的個人資料夾裡放三個文字檔儲存資料 (見文末說明)。除了 Windows 外的其他平台基本上只要能編 Qt 大概都能自己編 dependency 和本體,有興趣的也可以自己編來玩,我測過用 Qt 4 或 5 都可以,只是要注意 LibQxt 用的 Qt 版本要相符。

你不知道的英文:發音篇

因為實在太多人亂發音了,把我目前想到的寫下來以正視聽。

字中有 ham 者 h 不發音

例如 Birmingham 應發 bear-ming-em(另外注意 bir 的發音)或 bear-ming-gem(當地口音造成,如果下個音節沒有開頭的子音,有些地區會把 -ng 的 g 帶過去),而非 bear-ming-ham。中譯音近「伯明根」。

其他例子包括 Buckingham Palace 的正確音譯應該類似「白金根宮」,Tottenham 音近「托特南」,以及 David Beckham 的姓其實音近「貝肯」。

不過以上規則僅限「字中」適用,如果 ham 是獨立字就是另一回事——ham(火腿)還是要發 ham,West Ham 地區也是一樣。

Note: Triggering "click" in jQuery

javascript, jquery,

狀況

Works

$('<button>foo</button>')
  .click(function() { alert('Foo!') })
  .click();

Works

$('<a href="bar">go to bar</a>')
  .click(function(e) {
    e.preventDefault();
    alert($(this).attr('href'));
  })
  .click();

Does not work

$('<a href="bar">go to bar</a>').click();

Works!!

$('<a href="bar">go to bar</a>')[0].click();

說明

好,其實我也不知道為什麼...。根據 Stack Overflow 的回答,jQuery 物件只能觸發由 jQuery 創造的 click 事件,所以像 a tag 的連結導向事件就沒辦法用,因為它不是 jQuery 物件上的事件。

如果想觸發 a tag 的點擊事件,就必須找到正確的物件——也就是那個 a tag 本身。[0] 取出包裹器中的單一 DOM 元素,使得 click() 不再作用於包裹器物件,而是 DOM 元素,因而觸發了瀏覽器點擊 a DOM 元素的事件。

感謝 Stevanicus 的回答。順帶一題,雖然那個回答下面有人說 Safari 不能用,不過我實測(Safari 6.0.5, OS X 10.8.4)的結果是可以的。

Note: Slugify Unicode Strings in Django

django, Python,

這篇基本上是筆記…

Django 的 slugify filter 不支援 Unicode(把非 ASCII 字元傳進去會直接被忽略)。可能的輔助工具:

slugify_unicode

Mezzanine 從 Mozilla 的 unicode-slugify 改寫而來,位於 mezzanine.utils.urls。不需要額外函式庫。

import re
import unicodedata
from django.utils.encoding import smart_unicode

def slugify_unicode(s):
    chars = []
    for char in unicode(smart_unicode(s)):
        cat = unicodedata.category(char)[0]
        if cat in "LN" or char in "-_~":
            chars.append(char)
        elif cat == "Z":
            chars.append(" ")
    return re.sub("[-\s]+", "-", "".join(chars).strip()).lower()

會直接把非 ASCII 字元進行 URL encoding 後送出。優點:可讀性不錯,尤其如果瀏覽器會自動解碼網址列,可以直接看到原本的標題。缺點:如果沒有自動解碼,網址列會是一團(對使用者而言)莫名其妙的東西;如果有解碼,則該字串並非真正的網址,如果拿去貼到某些地方(例如 BBS)會無法正確識別。

unidecode

這篇文章有提到一些其他的解法。unidecode 這個套件可以把非 ASCII 字元以合理的邏輯轉換成 ASCII 字元(以中文而言,會用拼音與空白取代)。如果先用它處理過,再把字串送進 Django 內建的 slugify,就可以得到一個有意義的 slug。和一些主流網站的行為類似,Logdown 目前也是使用類似方法。優點:沒有瀏覽器自動解碼與否的問題。缺點:網址可讀性變差,尤其中文的同音異字異義問題很大,有時候出來的網址會完全不可讀。

如果要用後面的解法,還有一些其他的小工具可以讓事情更簡單。python-slugifyunidecode 包成一個 slugify 函式,還附上了一個 Unicode 可用的 truncate 函式(!)。django-uuslugpython-slugify 的功能接到 Django 上,讓它可以輸出 unicode 物件(而非 str),並且附上一個方便產生 unique slug 的 helper function。

What a time-saver!