rxvt / xterm + freetype + 中文顯示 (Chinese)

.Xresources

XTerm*faceName: Ubuntu Mono
XTerm*faceNameDoublesize: WenQuanYi Micro Hei Mono:minspace=true
XTerm*faceSize: 12
XTerm*faceSize1: 8
XTerm*faceSize2: 10
XTerm*faceSize3: 12
XTerm*faceSize4: 14
XTerm*faceSize5: 16
XTerm*faceSize6: 24

Rxvt.font: xft:Ubuntu Mono:size=12,xft:WenQuanYi Micro Hei Mono:pixelsize=18:minspace=true
Rxvt.letterSpace: -1
Rxvt.lineSpace: 2

xterm 比較討厭的地方是 freetype 的 failover 做不是很好,顯示一些 unicode 的字型時在 faceName/faceNameDoubleSize 裡頭找不到的話,就會放棄變成方塊;為了避免,只好裝 rxvt-unicode。後來因為太喜歡 rxvt fading 的功能,就決定換用了。

其中 rxvt 的 letterSpace 是要配合第一字型(在此是 Ubuntu Mono)的特性去調整的,Ubuntu Mono 間距比較寬,所以用 -1 來減少,這樣在我筆電 X220 上垂直分為左右二欄還可以有清楚的 80 欄寬。lineSpace 則是因為 Ubuntu Mono 比較寬而高度不夠,會導致文泉驛 render 出來的字太小,而且整個螢幕都是字時閱讀起來很吃力,所以加一些高度給他。麻煩的是,高度好了以後,仍然有時會跑出方塊,urxvt 顯示錯誤是

urxvt: unable to calculate font width for 'WenQuanYi Micro Hei 
Mono:slant=0:weight=200:pixelsize=19:minspace=True', ignoring.
...

size 轉到 pixelsize 是由螢幕解析度決定的,所以是否會有這情況,以及這情況發生時出來的數字,都不一定。我的情況是 pixelsize=19 出問題,由於字體大小是由第一個字型,也就是 Ubuntu Mono 決定,所以增加 pixelsize 沒用,只能試減少。減到 18 時剛剛好,字型漂亮,欄寬也夠。

xrdb -merge ~/.Xresources 可以直接讀入改好的 .Xresources,這樣下一個開的 x-terminal-emulator 就會套用新的設定。
font-test

Two-Finger Scrolling on ThinkPad X220 + Ubuntu 12.04 (precise)

The TrackPoint on a ThinkPad laptop is one of the main reasons why I kept buying laptops from them. However, as a heavy laptop user who refused to carry around one extra mouse, the constant usage of TrackPoint can cause a significant amount of pain to my fingertip, which is very unpleasant. An once-in-a-while quick movement is okay, but scrolling up/down takes longer and requires more pressure, which is the main cause of discomfort.

As a possible solution, I’ve tried to enable TouchPad and two-finger scrolling. However, for some reason it didn’t work by setting it in gnome-control-center, so instead I used the old faithful xinput. From the output of xinput list-props "SynPS/2 Synaptics TouchPad", it’s easy to spot “Synaptics Two-Finger Scrolling”, and the two parameters can enable vertical and horizontal scrolling, respectively.

The default setting of two-finger scrolling was far from intuitive — normally people would expect it to work just like the way it works on touch devices: you touch the screen, then you can push the document up by moving your finger up. That means scrolling down when your finger is moving up. But on my laptop, moving two fingers up means scrolling up, which causes the document to move down!

To make this problem worse, there is no setting in gnome-control-center to inverse this. Again, this can be solved with xinput by simply changing the values of “Synaptics Scrolling Distance” from 100 100 to -100 -100.

Here is my current .xsessionrc:

xinput set-prop "TPPS/2 IBM TrackPoint" "Evdev Wheel Emulation" 1
xinput set-prop "TPPS/2 IBM TrackPoint" "Evdev Wheel Emulation Button" 2
xinput set-prop "TPPS/2 IBM TrackPoint" "Device Accel Velocity Scaling" 50
xinput set-prop "SynPS/2 Synaptics TouchPad" "Synaptics Two-Finger Scrolling" 1 1
xinput set-prop "SynPS/2 Synaptics TouchPad" "Synaptics Scrolling Distance" -100 -100

Run Pencil on Ubuntu 12.04 / 12.10

Pencil is simply the best (open) sketchy mockup solution on Ubuntu. However, as described on its download page, you cannot install it as a Firefox extension because it’s not compatible with the Firefox 18.x that comes with Ubuntu 12.04. The standalone version runs okay but some features such as export as PNG fails silently because of the same compatibility issue.

Turns out you don’t need to install the deb package provided on its website. Simply download the latest tar ball from the download page on google code, then download xulrunner (Mozilla runtime) from ftp.mozilla.org. I used the latest supported version: 16.0.2.

Now extract these to a preferred place, then add a file called pencil anywhere in your $PATH with the following content:

exec <somewhere>/xulrunner/xulrunner --app "<somewhere>/pencil-2.0.4/usr/share/pencil/application.ini"

then chmod +x pencil, done.

virtualenv, python-rope and pylint

python-ropemac is really useful for developing python in emacs, and pylint is also very handy as a analyzer. However, they both don’t work very well with virtualenv, especially because I always run emacs in server mode, and the server instance is usually not under virtualenv.

Here is how to make things work:

Edit .ropeproject/config.py:

# You can extend python path for looking up modules
    prefs.add('python_path',
              '/your-virtualenv-dir/lib/python2.7/site-packages/')

For pylint, generate (by pylint --generate-rcfile) or copy your default pylintrc to project root dir. Edit it:

# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
init-hook='this_file="/your-virtialenv-dir/bin/activate_this.py";execfile(this_file, dict(__file__=this_file))'

After this pylint will work even in emacs.

Swap every windows between workspaces in awesome wm

awesome is the tiling windows manager I use daily and I just wrote a very useful (at least for me) function for it. Basically it swaps every client (similar to windows) between the current tag (similar to workspace) and the target tag. Normally I put terminal clients for my current task at tag#3, right next to my Emacs-only tag#2 so I can quickly switch between browser (#1), editor and terminals. Now if I want to switch to a different task I just need to swap in terminals from another tag while swap out current terminals to that tag.

-- i is the index of target tag in variable `tags'
function ()
   local screen = mouse.screen
   local from = client.focus:tags()[1]
   local to = tags[screen][i]
   if to then
       t = to:clients()
       for i, c in ipairs(from:clients()) do
           awful.client.movetotag(to, c)
       end
       for i, c in ipairs(t) do
           awful.client.movetotag(from, c)
       end
   end
end

I put this under

-- Bind all key numbers to tags.
-- Be careful: we use keycodes to make it works on any keyboard layout.
-- This should map on the top row of your keyboard, usually 1 to 9.
for i = 1, keynumber do
    globalkeys = awful.util.table.join(globalkeys,
        awful.key({ modkey }, "#" .. i + 9,
                  function ()
                        local screen = mouse.screen
                        if tags[screen][i] then
                            awful.tag.viewonly(tags[screen][i])
                        end
                  end),
        awful.key({ modkey, "Control" }, "#" .. i + 9,

in my copy of default rc.lua.

Multi-thread testing in Pyramid

If you want to do multi-thread testing in Pyramid, it probably won’t work the first time because request and registry are thread local, and things like get_renderer will call get_current_registry. When it happens in a thread, it won’t get the same value as it would have in the main thread.

So, here is a hack to address this:

import pyramid.threadlocal
from threading import Thread, Lock

candidates = [
    (self._test1, ()),
    (self._test2, ()),
    (self._test3, ()),
    ]

def random_func(pyramid_thread_locals):
    pyramid.threadlocal.manager.push(pyramid_thread_locals)
    time.sleep(random.random())  # 0 ~ 1 sec
    func, args = random.choice(candidates)
    func(*args)

pyramid_thread_locals = pyramid.threadlocal.manager.get()
threads = [Thread(target=random_func, args=(pyramid_thread_locals, ),)
           for i in range(100)]
for thread in threads:
    thread.start()
for thread in threads:
    thread.join()

There is no guarantee that pyramid.threadlocal.manager will always be there. Even if it’s there, there’s no guarantee it can be used this way. So, this should only be considered as a temporary workaround.

Rename file extension to lower case

I have been too lazy to write this but today I was finally bothered enough. I don’t pipe it to sh inside awk because you may want to check what it will do before you actually do it.

#!/usr/bin/awk -f

# Usage: ls -1 | lowercase.awk | sh

match($0, /\.[[:upper:]]+$/) {
        if (RSTART == 1)
                next
        name = substr($0, 1, RSTART-1)
        ext = substr($0, RSTART, RLENGTH)
        printf("mv \"%s%s\" \"%s%s\"\n", name, ext, name, tolower(ext))
}