As of 2016-02-26, there will be no more posts for this blog. s/blog/pba/

After I posted my first try of OpenCDE, I wrote an email to the developer and he sent me very useful information:
The problem that you are describing with multiple monitors could be due to the fact that OpenCDE uses the Motif Window Manager. This comes with OpenMotif and as such has not been updated for quite some time. AFAIK mwm does cause problems with multiple screens.

A solution to your problem could be to install the LessTif package, recompile wxWidgets to use LessTif (rather than OpenMotif) and then rebuild OpenCDE. This may help because LessTif provides it's own version of Motif Window Manager (based off fvwm) which may work better with multiple screens. Please be aware however that LessTif is generally less stable than OpenMotif so may introduce other bugs. A fork of mwm is planned so I can fix these bugs and maintain the software via the OpenCDE project (as dtwm)

I downloaded the LessTif 0.95.2 and installed it (it's not Gentoo Portage tree), everything went smoothly. But after I entered OpenCDE, it immediately exited. The only thing I saw was Mwm Pager.

I decided to remove OpenMotif package because I felt confused when I configured wxMotif, wxMotif didn't provide an option for you to choice which one (OpenMotif or LessTif) you would like to use. Maybe it's dynamic by `wx-config`? I don't know, the whole wx thing is not so clear to me.

Anyway, after removed OpenMotif and re-compiled, it works. However, it's still has some issue with LessTif. I can not make window move/expand/etc normally in external screen. But I still can make those operation in my original screen, then pan in Mwm Pager.

Here is a latest screenshot:


There is one more small thing I would like to point out in that screenshot. See that little icon between htop and browser? Oh boy, that's so cute as if I was back to 90's. It was a minimized window.

Before I was going to take a screenshot I encountered another problem with LessTif. I wasn't able to switch window focus after I brought up conky and xcompmgr, I wasn't sure they were the cause but the mouse clicks were still registered in each program (not keyboard inputs), I still could log out.

As for memory usage, `mwm` used 3.3 MB (4.8 MB, OpenMotif's mwm). The rest doesn't seem changed.

Well, I think that's all.

I asked for a new feature1 of Vimperator. Basically, I was not satisfied with the style of tabs bar (aka tabbrowser), they dont look consistent with Vimperators statusline. After I asked for it, I realized it might get implemented, so I decided to make my own when I found out userChrome.css can do it. I can also added it to Vimperator plugin, its not a hard task, just put it in and modify the manifest. But its not customizable yet, it will require some programming in Vimperators code.

Anyway, here is what I have now:

http://farm5.static.flickr.com/4095/4946686947_a0584635d5_z.jpg

The Vimperator is using my own style, vimPgray. You can download my userChrome.css, it might not works as you seen in screenshot. I customized in Firefox 4 and some are from vimPgray, e.g. the text shadow, but you can add on your own.

They are now nearly perfect to me, all gray!

Few issues:

  1. The all tabs button (#alltabs-button), I was able to replace it with css content, but the dropdown menu would not show up for some unknown reason after I clicked the button.
  2. I tried to replace the loading images from Firefox 4 with Unicode Block Elements (U+2581-8), but the layout was messed up.
  3. The close button and new tab button are just okay.
  4. I didnt change the styles of menu/location/etc.

Someday my Vimperator and Firefox will be flawless.

[1]http://code.google.com/p/vimperator-labs/issues/detail?id=399 is gone.

I just installed OpenCDE1 on Gentoo.

http://i.imgur.com/rLDfah.png

Its not hard to install1. It requires wxMotif and OpenMotif. On Gentoo, there already is an OpenMotif package, so wxMotif is the only package I needed to install manually. I downloaded the wxMotif 2.8.11 (you can download wxWidgets to compile of course, but you only need the Motif port)

$ ./configure --with-motif
$ gmake
$ sudo gmake install
$ sudo ldconfig

Then I compiled the OpenCDE 0.2.6.

$ cd opencde/src
$ gmake
$ cd ..
$ sudo cp -r bin etc share /usr/local/

For configuration of X, it depends on how you start your X. Basically, just replace exec your_current_wm_de with exec opencde in ~/.xinitrc, it should do the job if you already has that line.

In the screenshot above, I have conky, xcompmgr, firefox, and urxvtc + tmux running. You can run stuff you used to run. Also, I used xrandr to enable my external screen, it looked working. Well, sort of. When I dragged a window over the second screen, the left edge of a window will not be allowed to cross. So that is as far as a window can go.

The memory usage is not so light, dtpanel used 13 MB. Thats twice as Fluxbox needs. I dont know if its possible to not use dtpanel. dtwm and mwm use about 6.1 MB.

But I think those are not something would stop you using OpenCDE, the documentation is. I found no documentation. I had no idea how to configure it, there are some files in ~/.opencde, so I have put urxvt in menu. The syntax is not hard to understand. But the rest of OpenCDE, I have no idea what or how I can do.

Note

According to the first comment by Woomia and the documentation1, wxMotif is no longer needed. I didnt try the new version 0.4.2 or 0.4.3, just want to make sure you get the new information before you read this post. (2011-02-11)

[1](1, 2, 3) http://devio.us/~kpedersen/, http://devio.us/~kpedersen/documentation.php, and http://devio.us/~kpedersen/documentation.php are gone.

Accidentally stumbled upon this page

http://farm5.staticflickr.com/4121/4940670439_3dc12e553d_z.jpg

Why do people want to un-scrobble? Is it a shame to have such tracks in their profiles? However, I have done deletion for a few tracks, too. I delete some tracks long time ago, because they somehow dominated recommendations, its annoying.

Lady Gagas track occupied first four pages, really that bad? By the way, Ke$has Your Love Is My Drug at 11th place, which is actually a drug. That song was stuck in my head for day after I firstly listened to it on YouTube but not the original one. And Justin Bieber reminds me of Twitter Trending Topics, that was top one I want to remove that name from TT. For a period of time, its like being fixed in TT, it never went down like the British Empire.

A couple of days ago, I started to scrobble my MPD plays. I found that Last.fm gave me another 30 tracks for free trail, I had 30 tracks more than a year ago. I am thinking if I should subscribe again.

Gentoo is a source-based distribution. The main benefit of using Gentoo is you pick features of a software you need to compile if its configurable. Here is an example I just saw:

% emerge -pvuDNt world

These are the packages that would be merged, in reverse order:

Calculating dependencies... done!
[ebuild   R   ] www-client/chromium-7.0.503.1  USE="sse2 -cups -gnome -gnome-keyring%" 0 kB

Total: 1 package (1 reinstall), Size of downloads: 0 kB

The developer just made GNOME Keyring dependency optional if you use gnome USE flag. That cups USE tag is an example, too. When Chromium just added printing support, they have made CUPS dependency necessary. It got fixed quite fast, in just a few days, Gentoo developer fixed it.

Note

I couldnt find an issue about it on Chromium issues, but it seems fixed in upstream because I dont see any patch in Portage tree.

Anyway, after CUPS, GNOME Keyring suddenly jumped out from nowhere. I already had GNOME Keyring on my system, but I didnt have CUPS. So, I let Chromium to compile with it, I didnt have a choice. Now, we have new USE flag.

If you are using any binary-based distribution, unless you try to build on your own or with some tools, your system is always with a bunch of stuff you dont need. And you never could have even a vague idea what have been made.

I still have some packages depends on GNOME Keyring, I should check them up again, some are optional, some might have no need to be on my system.

% equery d gnome-keyring
[ Searching for packages depending on gnome-keyring... ]
dev-vcs/subversion-1.6.12 (gnome-keyring? gnome-base/gnome-keyring)
gnome-base/gnome-mount-0.8-r1 (<gnome-base/gnome-keyring-2.29.4)
gnome-base/libgnome-keyring-2.30.1 (>=gnome-base/gnome-keyring-2.29)
net-libs/libsoup-gnome-2.28.2 (gnome-base/gnome-keyring)
sys-auth/pambase-20100310 (gnome-keyring? &gt;=gnome-base/gnome-keyring-2.20[pam])
www-client/chromium-7.0.503.1 (&gt;=gnome-base/gnome-keyring-2.28.2)
                              (gnome-keyring? &gt;=gnome-base/gnome-keyring-2.28.2)

I just knew Gnash is 100% of all YouTube videos should work, its true. Also true for Flash Ads. I dont know if its about my hardware, drivers, or libraries, its performance is worse than Adobe Flash 64-bit. Yes, you can spank me, I am still using Adobe Flash 64-bit. I was aware Adobe decided to hold their support for 64-bit and I did not try to switch to 32-bit with nspluginwrappers help. I was risking myself.

Anyway, I had tried everything I could with ~/.gnashrc. I had tried every combination for hwaccel and render. I even tried vaapi, even I knew its purely meaningless since my ATI X1400 is not supported, I was desperate.

Here is some numbers. YouTube 480p using Adobe Flash 10.0 r45: 20-25%, 40-45% in fullscreen. My processor is a dual-core, so 45% means it uses almost one cores processing power. 360p using Gnash 0.8.8: 40%, nearly 100% and very laggy in fullscreen. If I use xv in mplayer for a 720p video, its around 20-25% in fullscreen.

This is my second try of Gnash, first time was probably a year ago, it didnt work out last time. Next time I try Gnash, it will be version 1.0.

I hope its just configuration thing, though I dont think so, but if you have same video card and it works smoothly for you, please tell me about your settings.

Note

Google Buzz has long gone, the code in this page will not be working.

I got this idea to make an unrelated (as in consanguinity) cousin of Im Feeling Lucky. The Im Feeling Buzzy let you feel lucky on Google Buzz1. However, I dont use Google Buzz, even I was planning to use Buzz and its API to create a something like http://mydomain/random. But I am not sure if I want a link like that. Its still worth sharing because its simple.

There are three way to feel buzzy, first one is to read ones buzz activities, you will be redirected to one of recent updated items of his or hers or its. The second is to get one random site in ones Google profile. The last one is to search on Google Buzz, you will be redirected to the first result, just as you search on Google.

Here is these three functions:

<script>
function imfeelingbuzzy_userid(userid) {
  var URL = 'https://www.googleapis.com/buzz/v1/activities/' + userid + '/public?alt=json&callback=?';
  $.getJSON(URL, function(data) {
    var data = data.data;
    var link = data.items[Math.floor(data.items.length * Math.random())].links.alternate[0].href;
    window.open(link);
    });
  }
function imfeelingbuzzy_profile(userid) {
  var URL = 'https://www.googleapis.com/buzz/v1/people/' + userid + '/self?alt=json&callback=?';
  $.getJSON(URL, function(data) {
    var data = data.data;
    var link = data.urls[Math.floor(data.urls.length * Math.random())].value;
    window.open(link);
    });
  }
function imfeelingbuzzy_search(q) {
  var URL = 'https://www.googleapis.com/buzz/v1/activities/search?q=' + encodeURIComponent(q) + '&alt=json&max-results=1&callback=?';
  $.getJSON(URL, function(data) {
    var data = data.data;
    var link = data.items[0].links.alternate[0].href;
    window.open(link);
    });
  }
</script>

You can just change the URL with your own User ID, so you can let people feel lucky to read you buzz. Like this code:

<input type="button" value="I'm Feeling Buzzy" onclick="imfeelingbuzzy_userid('googlebuzz')"/>

It will give you a button like the two above and this button will take everyone to one item of your recent 20 updated items. Or this code for sites of a profile:

<input type="button" value="I'm Feeling Buzzy" onclick="imfeelingbuzzy_profile('googlebuzz')"/>

Feeling Buzzy?


[1]http://www.google.com/buzz is gone.

Warning

The project is dead and some links have been removed. (2015-12-08T01:15:53Z)

Its a code I wrote more than two years ago, my first Google App Engine project. I didnt maintain it after a few months. Now, I have revived it and gave it a new face, those the code is still !#$%^.

http://4.bp.blogspot.com/_CLdf4ORfzWk/THiHcIgEstI/AAAAAAAAChs/wo0IQL9txcQ/s800/2010-08-28--11:47:29.png

Its kind of game. You get one word, then you enter another to create a link. You get another new word, then you just keep doing same thing, whatever the word pops up after you read the word you are going to link with, you type. I dont know what this app could achieve, its silly, without solid purpose. Just for fun, I guess.

Go to play next -> word.

Nope, this is not about the alphabet song at all. Its about how fast a Python code can generate 'abcdefghijklmnopqrstuvwxyz'.

The answer is already there, 'abcdefghijklmnopqrstuvwxyz'. Still dont see it? Alright, let me give you a full Python code:

#!/usr/bin/env python
# A program demonstrates how to generate an 'abcdefghijklmnopqrstuvwxyz' QUICK.


atoz = 'abcdefghijklmnopqrstuvwxyz'

Thats the complete code, get it?

You might ask Seriously, you are writing a post about this? Yes, Im.

I found many people have been trying to generate such string in different ways, more Pythonic, looks like smart or genius, or looks like hell. But sometimes, the direct approach is the most simple way and easy way to understand, not only by the programmer but also by people who dont know about programming. The following list is what I saw from Internet, there must be more.

atoz = 'abcdefghijklmnopqrstuvwxyz'
from string import ascii_lowercase
atoz = map(chr, xrange(97, 123))
atoz = map(chr, xrange(ord('a'), ord('z') + 1))
atoz = map(chr, range(97, 123))
atoz = [chr(i) for i in xrange(97, 123)]

Which one is the best in your mind?

1   Runtime Profiling

I did some profiling, yep, I did. Here is the code for profiling:

#!/usr/bin/env python

import sys
import timeit

def main():

  m = [
      ("atoz = 'abcdefghijklmnopqrstuvwxyz'", '', 0),
      ("from string import ascii_lowercase", '', 0),
      ("atoz = map(chr, xrange(97, 123))", '', 2),
      ("atoz = map(chr, xrange(ord('a'), ord('z') + 1))", '', 2),
      ("atoz = list(map(chr, range(97, 123)))", '', 3),
      ("atoz = list(map(chr, range(ord('a'), ord('z') + 1)))", '', 3),
      ("atoz = [chr(i) for i in xrange(97, 123)]", '', 2),
      ("atoz = [chr(i) for i in range(97, 123)]", '', 3),
      ('atoz[13]', "atoz = 'abcdefghijklmnopqrstuvwxyz'", 0),
      ('atoz[13]', "atoz = map(chr, xrange(97, 123))", 2),
      ('atoz[13]', "atoz = list(map(chr, range(97, 123)))", 3),
      ]
  max_len = max(map(lambda x: len(x[0]), m))

  for i in range(len(m)):
    stat, setup, v = m[i]
    if v != 0 and v != sys.version_info[0]:
      continue
    if setup:
      sys.stdout.write('%s\n' % setup)
    else:
      setup = 'pass'
    sys.stdout.write(('%%-%ds -> ' % max_len) % stat)
    sys.stdout.write('%12.6f us\n\n' % (min(timeit.Timer(stat, setup).repeat(10000, 100)) * 1000000))

if __name__ == '__main__':
  main()

At first, I used cProfile, but it only shows to milliseconds level, so I switched to timeit. Each one is ran for 10,000 sessions and each session accumulate 10 runs of the code, then pick up the smallest runtime as result. Which represent how fast the code might be able to be executed. But there is a catch, it might actually be run faster than that just timeit could not tell because timers precision.

Here is the results:

CODE                                                       Python 2.5.4    Python 2.6.5    Python 3.1.2
atoz = 'abcdefghijklmnopqrstuvwxyz'                  ->     4.768372 us     4.768372 us     3.814697 us

from string import ascii_lowercase                   ->   186.920166 us   177.860260 us   258.922577 us

atoz = map(chr, xrange(97, 123))                     ->   584.840775 us   560.998917 us   vvvvvvvvvvvvv
atoz = map(chr, range(97, 123))                      ->   618.934631 us   577.926636 us   vvvvvvvvvvvvv
atoz = list(map(chr, range(97, 123)))                ->   ^^^^^^^^^^^^^   ^^^^^^^^^^^^^   775.814056 us

atoz = map(chr, xrange(ord('a'), ord('z') + 1))      ->   609.874725 us   594.854355 us   vvvvvvvvvvvvv
atoz = list(map(chr, range(ord('a'), ord('z') + 1))) ->   ^^^^^^^^^^^^^   ^^^^^^^^^^^^^   811.100006 us

atoz = [chr(i) for i in xrange(97, 123)]             ->   942.945480 us   875.949860 us   vvvvvvvvvvvvv
atoz = [chr(i) for i in range(97, 123)]              ->   ^^^^^^^^^^^^^   ^^^^^^^^^^^^^   946.044922 us

atoz = 'abcdefghijklmnopqrstuvwxyz'
atoz[13]                                             ->    12.874603 us     9.775162 us     7.867813 us

atoz = map(chr, xrange(97, 123))
atoz[13]                                             ->    10.967255 us     7.867813 us     vvvvvvvvvvv
atoz = list(map(chr, range(97, 123)))
atoz[13]                                             ->    ^^^^^^^^^^^^     ^^^^^^^^^^^     7.867813 us

As you can see, using constant from string module, map, and list comprehensions are very slow. Yes, its one-time setup but the direct approach is also the one-time setup. And those, except the ascii_lowercase, would take everyone sometime to read it and understand.

2   Memory Profiling

I also did a memory profiling using this code with Guppy-PE:

#!/usr/bin/env python

from guppy import hpy

hp = hpy()

hp.setrelheap()
atoz = 'abcdefghijklmnopqrstuvwxyz'
print hp.heap()
print

hp.setrelheap()
from string import ascii_lowercase
print hp.heap()
print

hp.setrelheap()
print hp.heap()
atoz = map(chr, xrange(97, 123))
print

hp.setrelheap()
atoz = map(chr, xrange(ord('a'), ord('z') + 1))
print hp.heap()
print

hp.setrelheap()
atoz = map(chr, range(97, 123))
print hp.heap()
print

hp.setrelheap()
atoz = [chr(i) for i in xrange(97, 123)]
print hp.heap()
print

The results:

=== Python 2.5.4 ===

Partition of a set of 1 object. Total size = 656 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0      1 100      656 100       656 100 types.FrameType

Partition of a set of 1 object. Total size = 560 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0      1 100      560 100       560 100 types.FrameType

Partition of a set of 1 object. Total size = 656 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0      1 100      656 100       656 100 types.FrameType

Partition of a set of 2 objects. Total size = 888 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0      1  50      560  63       560  63 types.FrameType
     1      1  50      328  37       888 100 list

Partition of a set of 2 objects. Total size = 984 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0      1  50      656  67       656  67 types.FrameType
     1      1  50      328  33       984 100 list

Partition of a set of 2 objects. Total size = 888 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0      1  50      560  63       560  63 types.FrameType
     1      1  50      328  37       888 100 list

=== Python 2.6.5 ===

Partition of a set of 1 object. Total size = 448 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0      1 100      448 100       448 100 types.FrameType

Partition of a set of 1 object. Total size = 448 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0      1 100      448 100       448 100 types.FrameType

Partition of a set of 1 object. Total size = 448 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0      1 100      448 100       448 100 types.FrameType

Partition of a set of 2 objects. Total size = 776 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0      1  50      448  58       448  58 types.FrameType
     1      1  50      328  42       776 100 list

Partition of a set of 2 objects. Total size = 776 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0      1  50      448  58       448  58 types.FrameType
     1      1  50      328  42       776 100 list

Partition of a set of 2 objects. Total size = 776 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0      1  50      448  58       448  58 types.FrameType
     1      1  50      328  42       776 100 list

Guppy isnt compatible with Python 3, hence there is no result of Python 3.1.2.

Those use map or list comprehension would result a list and required more memory as expected, it doesnt really affect how you use it. Usually you just access it like atoz[10], it works for list and string types. But memory use tells you that string type uses less memory, however, if you notice the runtime result above, you would have seen accessing list element is faster than substring of a string.

3   Conclusion

My conclusion is wgasa.

La FaRe La FaRe ReFaSol La FaRe? Any ideas of what it means?

Another hint: Can you save me?

Last hint: The Company.


Its the song, Can You Save Me by Apple Trees & Tangerines, as theme song of the tv show, Covert Affairs. If you still dont get it, check out this opening clip of Covert Affairs.

Got it?

The rhythm has stuck in my head for two days. I watched Cover Affairs from premiere, I did not really notice that theme song, but I suddenly hummed that part of song, not the vocal part.

You can download from their website, they posted a link1. (You will need to copy the text of that link, or you will be stopped from linking out from MySpace.)

The trailer of the show if you are interested.

This show is just a normal tv show, not too outstanding but definitely a good show to kill your free time.

I think the espionage in a tv show has some power to attract people to watch. Like Chuck, I watched it because its about spy and geek. But you have to realize that a tv show is just a show, they are far away from realistic world. (Futurama probably is one exception, I heard that created a mathematics theorem specially for the show. I never watched it, dont like animation.)

Spy plus beautiful female and handsome male leading roles, definitely a must-see. Even that guy is set as a blind man in the show, but that even is a plus, because how you could imagine a blind guy work for CIA?

La FaRe La FaRe ReFaSol La FaRe

La FaRe La FaRe ReFaSol La FaRe


Just after I posted about Firefox 4 new features, a popup notification showed up telling me about new update 4.0b5pre for my current version 4.0b5pre.

4.0b5pre -> 4.0b5pre?

I am using nightly build as I mentioned before. I clicked on that Restart Minefield button with doubt, I didn't believe it would work or really get an update.

It turned out, it's really an update, Gecko/20100826. I was stunned for few things.

First, I never thought auto-update would work on Linux since I always use distro's distribution of browsers. Distro always installs browsers in system directories. But I installed FF4 on my own, well, that's an overstatement, just unpacked it to ~/var/bin/firefox.

Second, even it could do auto-update, I didn't think that would also apply on nightly build, not to mention the official branding release (using Firefox not other Foobar name) don't have 64-bit build for Linux (maybe it has just I could find it). But it works smoothly for 64-bit nightly build.

I checked out the installed directory, all dates are now 5:15 8/27, it did update for sure. And this was taken from Update History:



Amazing... and I probably wouldn't want to install Firefox through Portage tree. In face, I have already unemerged it. Sooner, I would unemerged Chromium, too, after I felt it's safe to have Firefox only.

However, I think once FF4 hit Portage stable, I might emerge it again. I am still obsessed with the mythical compiler flags.

I seem to find more feature of Firefox 4 every time I use it. I was wandering through the menu, believe me, I have done that when I just installed it. Somehow, I didnt notice there were two new things: Inspect and Web Console. You can activate them by pressing Ctrl+Shift+I and Ctrl+Shift+K.

http://i.imgur.com/Lklo4h.jpg

The Inspect (the top windows on the left, right, and bottom) is really something called very pre-alpha feature, I got crash once by just hovering my cursor around. If you try to compare it with Firebug1 or Developer Tools in WebKit-based browsers, you will be so disappointed at it. It just shows you the values, nothing fancy, you can not edit or tweak your HTML on the fly. FFs Inspect is like a blackboard updated by hand, others are like a 60 HD plasma TV updated by automatic intelligent programs.

The Web Console (the frame above Mozilla webpage) seems to be more mature and it supports console.log(). And dont forget that JavaScript Console (Ctrl+Shift+J), its the place to read error occurrences in JavaScript, Web Console is not for that purpose. I think Firefox would have integrated developer tools someday, Firebug is great but I would like to have built-in.

[1]The latest 1.6b1 still failed for six tests in Firefox 4.0b4.

I had known of this new Panorama feature in Firefox 4 from other blogs post titles. When I first saw Panorama, I thought that was Panoramio. I was wondering why Mozilla introduced Panoramio, then I read the title again and I did.

I totally forgot it when I just installed Firefox 4. I accidentally brought it up by pressing Ctrl+Space unawarely.

http://i.imgur.com/UQ94Ah.jpg

I thought What the heck just happened? then I was trying every key combinations I could think of to get back to normal browsing mode. I finally got it after I watched the introduction clip of Panorama.

https://i.ytimg.com/vi/5r0TQJ-gGi0/hqdefault.jpg

Just press Ctrl+Space again or click on thumbnail. I have no idea why I didnt try to click at first place.

Anyway, its a cool feature. You create some groups, organize them. They will even get together again next time you open them. Ctrl+Space allows you to cycle them over group by group, tab by tab. But its not a useful feature for me, I rarely would open tabs more than five. The screenshot above took me opening half of my bookmarks (liar!), I know some people are tabmanic or tabholics, Panorama must be their thing.

There is one more thing I want to mention, its the memory usage of these 16 tabs. Firefox only used less than 300 MB, I would bet its kind of improvement, though I had never known how much memory it takes for 16 tabs in previous tabs.

http://farm5.static.flickr.com/4135/4928325322_134fa21633.jpg

I am using Firefox 64-bit beta 5 prerelease nightly build, it works well on my Gentoo. And Vimperator also works, well, from the repository, of course. I have to edit the install.rdf because it only sets up up to beta 4. I bumped the version and built the xpi, it works great!

Almost all addons are not compatible with beta 5, AdBlock is the only one has an update for beta 5 prerelease, but I disabled it later. The reason I dont want to use AdBlock is same as I have with Chrome. The speed has been improved, though it is still slower than Chrome.

I think I should get some numbers, so I tested it with first website I could find from search.

Before I show you the results, I must tell you that I just wanted to get a rough idea about how fast they could execute JavaScript, I didnt try to make sure my system is all ready for the benchmark test to run. I had some programs running behind but they were not heavy tasks. Firefox 3.6.8 (8 addons) and Chromium (2 extensions) have some addons installed, but I dont think it would make big difference if I disable them.

Now, here is the chart and numbers:

http://chart.apis.google.com/chart?chxl=1:|||(ms)|Time||&chxr=0,0,1400&chxt=y,y&chbh=a&chs=800x320&cht=bvg&chco=A2C180,FF9900,BBCCED,7777CC&chds=0,1400,0,1400,0,1400,0,1400&chd=t:447.4|480.8|719.4|1255.8&chdl=Chromium+6.0.490.1|Opera+10.61|Firefox+4.0b5pre|Firefox+3.6.8&chg=-1,7,4,0&chtt=Browsers+SunSpider+Tests"
Browser Total
Chromium 6.0.490.1 0447.4ms +/- 12.3%
Opera 10.61 0480.8ms +/- 01.4%
Firefox 4.0b5pre 0719.4ms +/- 01.9%
Firefox 3.6.8 1255.8ms +/- 01.2%

From the results, Fireforx 4.0b5pre is about 60.8% slower, but a benchmark is an intense test in different special cases. The real use might not result in such difference. When I just fired it up, I immediately felt the performance improved and I couldnt real tell if its faster or slower than Chromium. The memory usage also seems improved, though I havent used it thoroughly.

Vimperator is always something very important addon for me, I even tried to create a similar way to open bookmark in Chromium. Since its already in beta stage and stable enough for me, so I think I should probably go back to Firefox and Vimperator. Hope the future release could have more performance improvement. UI improvement is really useless to me since I use Vimperator.

Console Display Manager is another great program I found on forums. I downloaded it from GitHub, the authors website seems to be down. Followed that wiki page to configure it, then deactivated XDM and rebooted. I logged in in console and the display manager showed up

https://farm5.staticflickr.com/4140/4926241632_14cb2f7af7_b.jpg

CDM works a little different than other DMs. You log in in console (tty1), then /etc/profile.d/zzz-cdm-profile.sh kicks in and you see the display manager. It checks if you are in console, then launches cdm and you choose DE/WM to continue. Basically, you dont need to manually run startx just press the enter key.

I use the default theme instead of cdm theme. You can try those themes (/usr/share/cdm/themes) just fire up cdm in your terminals, use escape key to quit. You dont have to log out only to see the theme. Honesty, the color schemes are not so good in console, thats the reason I chose default them. Its not fancy but still looks good.

The memory usage is slightly smaller, I believe if its written in C, it would use less. It is written in Bash. This was with XDM:

https://farm5.staticflickr.com/4141/4926241636_46101814d3_o.png

And this was with CDM:

https://farm5.staticflickr.com/4102/4926241640_63f50d1705_o.png

Its about 2-3 MB less but XDM had two more dbus programs running, so its probably 1-2 MB less.

The reason I used XDM was because I didnt want to type startx, now I have removed the XDM since I still dont need to with CDM. My Gentoo is slimmer a little bit.

I just watched the first episode of The Big C, I think the "C" is also for cancer, right? You can watch it on IMDb or YouTube.



I didn't know why I watched it, it's not a usual show I would like to watch especially it could be around very sad and ended up with tears. Well, it's not so bad and not so boring or slow pace as I expected.

Some people posted about Breaking Bad in comparison, I have almost forgotten that show which I stopped watching few episode before season two final. (or I stopped watching after final?) It's not because BB is a poor show but it's quite awesome and tense, I could bear watching more.

Another show was mentioned is the Weed, I have never watched it because it's already aired for a few seasons after BB.

There are few similarities in between BB and The Big C. Both leading role have cancer, both are high school teacher, both have kids with problems (In BB, it's not like the kid is bad), and probably some more. However, they are two different shows to me. I still don't know the whole point in Big C, life with cancer? life before death? living out of box?

Anyway, I think I would like to watch a few more episodes.

PS. I didn't know you need a permit to build a swimming pool.

Eight hours ago, I got an idea to use Google AJAX Search API to search for related posts. Now I have published, the first release.

I installed it within Blog Gadget with the following code:

<div class='post-footer'>
<b:if cond='data:blog.pageType == &quot;item&quot;'>
  <div style='float:right;width:312px'>
    <h4>Possibly Related Posts</h4>
       <div id='gas-results'></div>
    </div>
</b:if>
<div class='post-footer-line post-footer-line-1'><span class='post-author vcard'>

Between first line and last line are the code I added. I make sure the code wont show up multiple time. I have the rest of code at footer:

<script>
window.brps_gas = {
  limit: 10,
  add_sites: [
    'blogarbage.blogspot.com',
    'fedoratux.blogspot.com',
    'getctrlback.blogspot.com',
    'makeyjl.blogspot.com',
    'thebthing.blogspot.com'
    ],
  remove_string_regexp: new RegExp('^(YJL --verbose|Blogarbage|Tux Wears Fedora|Get Ctrl Back|make YJL|The B Thing): '),
  exclude_url_regexp: /(.*archive\.html|blog\.yjl\.im\/$|(blogarbage|fedoratux|getctrlback|makeyjl|thebthing)\.blogspot\.com\/$)/
  };
</script>
<script src="http://brps.appspot.com/gas.js"></script>

I included five other blogs, which I am no longer posting on. Note: I dont have jQuery inclusion in above code because its already in my template.

You can simply throw that three lines of code into a HTML/JavaScript gadget and pull it to a place you like. It should work.

On more thing, as you may know Blogger pages do not have labels, but you can use tag_selector option and manually install labels into your pages. You can get the related posts for pages as well.

1   Updates

I was window shopping at Community Contribution of Arch Linux Fourms for totally free new application, tried to see if I can find new toy. I saw this HC, after I read and saw some examples the author posted, I decided to give it a try.

1   Happy Valentines Day!

Too early? or too late?

r(t)=2-2sin(t)+sin(t)*sqrt(abs(cos(t)))/(sin(t)+1.4)
graphpeq(r(t)*cos(t),r(t)*sin(t),0,2pi,-3,3,-4,1)

2   No recursion? You cant stop me!

If you try to define a recursion function, you will get:

fib(n)=if(n&gt;=0,
  if(n==0,0,
    if(n==1,1,
      fib(n-1)+fib(n-2)
      )
    )
  )
Error : recursive definition.

Lets trick HC!

fibr(n)=fib(n)
fib(n)=if(n&gt;=0,
  if(n==0,0,
    if(n==1,1,
      fibr(n-1)+fibr(n-2)
      )
    )
  )

Some outputs:

> fib(10)==fibo(10)
1
> fib(70)
Error : too much recursion/nestedness. If you know what you are doing, you can bypass this with:
 \bpn.
Argument Error : if() : at least two arguments are needed (condition, true_branch, false_branch)
> \bpn
By pass is now on.
> fib(70)

You will have to wait until only God knows how long it takes

Note

Now, HC is allowed to define recursion function:

fib(n) = if(n<2,n,fib(n-1)+fib(n-2))

, read more. (2010-08-24)

3   FFT! The FFT!?

Yes, the Fast Fourier transform!

fft(x)=for(k=0,k&lt;length(x),k+=1,
  xk=0;
  for(j=0,j&lt;length(x),j+=1,
    a=x[j];
    b=exp(-2pi*k*j*0i1/length(x));
    xk+=a*b;
    );
  print(xk);
  )

Example:

> x = [1,0,3i-3,4i5,5]
> fft(x)
13i2
-7.8203160070896799i3.7250338450183462
6.7264861191111235i2.6059037339171068
-8.4904181416113337i-1.3698357564173172
1.5842480295898901i-6.9611018225181358

Confirmed by result from SciPy:

>>> import scipy
>>> scipy.fft([1,0,3-3j,4+5j,5])
array([ 13.00000000+2.j        ,  -7.82031601+3.72503385j,
         6.72648612+2.60590373j,  -8.49041814-1.36983576j,
         1.58424803-6.96110182j])</pre>

Note: the representations of complex number are different.

Note

Here is a shorter version:

fft(x)=for(k=0,k&lt;length(x),k+=1,
  for(j=0,j&lt;length(x),j+=1,
    a=x[j];
    b=exp(-2pi*k*j*0i1/length(x));
    xk=if(j==0,a*b,xk+a*b);
    );
  y=if(k==0,[xk],join(y,[xk]));
  )

(2010-08-24)

The result can be retrieved by y.

4   Conclusion

This is a great CLI program, I am going to replace SpeedCrunch. You can do some simple programming, though I found its still limited. (What do you expect? Signal processing using a calculator?) When I installed SpeedCrunch because I wanted one can allow me to easy input, bc is not so friendly, even I prefer CLI over GUI. Now, HC can do things I need and its a CLI and its resource-friendly. Definitely the top choice for me!

It has vector but its not much you can do with it at this moment, but if you just use it for 1+1, it can do much more than that. If you dont like CLI, dont worry, it provides GUI as well. But I didnt try it, so no comments on that.

It means I am reading questions on Stack Overflow because I was bored and have run out of my blogging to-do list, getting nothing to do. So I re-enabled Stack Overflow in my clis.py and improved the exclusion filter better, also took a good advantage of pyratemps for loop syntax.

http://farm5.static.flickr.com/4101/4921628199_72142baab8_z.jpg

I can now exclude categories (tags as in term of feedparser or WordPress?):

http://farm5.static.flickr.com/4138/4921628211_6a16f1abfa_z.jpg

It lists feed entries tags using this pyratemp syntax:

'[snip] !entry["title"]! !ansi.figreen!<!--(for tag in entry["tags"])-->!tag["term"]! <!--(end)-->!ansi.freset![snip]'

It works better than Stack Overflows website, the highlighter and filter on SO is very primitive and it only does simple text matching. In clis, I can use regular express in my program which can exclude many at once.

Some qualities of questions are very poor, either they are totally nothing to do with programming or you still cant understand where the question is after you read them twice or thrice. Some dont know what tags are for, or they tag with their very happy mind.

I CAN HAS SEGMENTASHUN FAULT? while my exclusion filter list is still growing

After wanting to plot the timeline of OSes I have used, I thought I could create a timeline of my blogs.

http://i.imgur.com/HFzOSl.jpg

The files can be downloaded here, my-blogs-timeline.{conf,csv}. The code was indeed from that GNU/Linux distro timeline, but after I modified and read the manual of gnuclad, I found those were from gnuclads docs and examples . So, I dont think I will need to make a attribution.

In this timeline, I started with one blog then it branched out in 2008. At the time, I thought its a good idea to have blogs with special topics. But in 2010, I decided to go back to just one blog. There is no need to have many special topic blogs and my Blogger dashboard had too many blogs. I am not a professional blogger, its hard to keep active blogging. This timeline includes some projects blogs, they are almost inactive.

When I was composing it, I tried to add images, such as logos or header images of my blogs, but some images were being resized too small. I couldnt figure out how to resolve it. There was no bug reports or no FAQ entries mentioned about images, hence I just removed the images and went back for plain texts.

Five years of blogging (I have some were not in the timeline), I did manage to create a lot of useless contents, I think. :)

I need to leave a note for myself for generating the image:

gnuclad my-blogs-timeline.{csv,svg,conf} && inkscape my-blogs-timeline.svg -D --export-png my-blogs-timeline.png

See the Bash Brace Expansion, its the commandfu!

Note

Gmail supports new operators for size range searching, see my blog post about them. (2012-11-14)

After I posted about using Googles Python XOAuth library to get the unread mail count and list, I finally found a good reason to use IMAP, you can search based on the message size! Which you cant do in the web interface.

typ, data = imap_conn.search(None, '(SMALLER %d) (LARGER %d)' % (MAXSIZE * 1000, MINSIZE * 1000))

That is just great but not awesome because Gmails IMAP server does not support SORT command, which is an IMAP4rev1 extension command, according to Python doc.

The entire source code is the similar to the one in my previous post:

#!/usr/bin/env python
# Copyright 2010 Yu-Jie Lin
# BSD license

import email
import email.header
import imaplib
import sys

# http://google-mail-xoauth-tools.googlecode.com/svn/trunk/python/xoauth.py
import xoauth

scope = 'https://mail.google.com/'
consumer = xoauth.OAuthEntity('anonymous', 'anonymous')
imap_hostname = 'imap.googlemail.com'

# How many messages will be fetched for listing?
MAX_FETCH = 20


try:
  import config
except ImportError:
  class Config():
    pass
  config = Config()


def get_access_token():

  request_token = xoauth.GenerateRequestToken(
      consumer, scope, nonce=None, timestamp=None,
      google_accounts_url_generator=config.google_accounts_url_generator
      )

  oauth_verifier = raw_input('Enter verification code: ').strip()
  try:
    access_token = xoauth.GetAccessToken(
        consumer, request_token, oauth_verifier, config.google_accounts_url_generator)
  except ValueError:
    # Could indicate failure of authentication because verifier is incorrect
    print 'Incorrect verification code?'
    sys.exit(1)
  return access_token


def main():

  # Checking user email and access token
  if not hasattr(config, 'user') or not hasattr(config, 'access_token'):
    config.user = raw_input('Please enter your email address: ')
    config.google_accounts_url_generator = xoauth.GoogleAccountsUrlGenerator(config.user)
    access_token = get_access_token()
    config.access_token = {'key': access_token.key, 'secret': access_token.secret}
    # XXX save token, this is not a good way, I'm too lazy to use something
    # like shelve.
    f = open('config.py', 'w')
    f.write('user = %s\n' % repr(config.user))
    f.write('access_token = %s\n' % repr(config.access_token))
    f.close()
    print '\n\nconfig.py written.\n\n'

  config.google_accounts_url_generator = xoauth.GoogleAccountsUrlGenerator(config.user)
  access_token = xoauth.OAuthEntity(config.access_token['key'], config.access_token['secret'])

  # Generate xoauth string
  class ImBad():
    # I'm bad because I'm going to shut xoauth's mouth up. So you won't see these debug messages:
    # signature base string:
    # GET&https%3A%2F%2Fmail.google.com%2Fmail%2Fb%2Flivibetter%40gmail.com%...
    #
    # xoauth string (before base64-encoding):
    # GET https://mail.google.com/mail/b/livibettergmail.com/IMAP/ oauth_co...
    def write(self, msg): pass
  sys.stdout = ImBad()
  xoauth_string = xoauth.GenerateXOauthString(
      consumer, access_token, config.user, 'IMAP',
      xoauth_requestor_id=None, nonce=None, timestamp=None)
  sys.stdout = sys.__stdout__

  MINSIZE = int(raw_input('Larger than in KB [1000]? ') or 1000)
  MAXSIZE = int(raw_input('Smaller than in KB [5000]? ') or 5000)
  if MAXSIZE < MINSIZE:
    print >> sys.stderr, 'Wrong size range!'
    sys.exit(1)
  print
  imap_conn = imaplib.IMAP4_SSL(imap_hostname)
  imap_conn.authenticate('XOAUTH', lambda x: xoauth_string)
  imap_conn.select('[Gmail]/All Mail', readonly=True)
  typ, data = imap_conn.search(None, '(SMALLER %d) (LARGER %d)' % (MAXSIZE * 1000, MINSIZE * 1000))
  # No SORT command on Gmail IMAP server
  #typ, data = imap_conn.sort('(REVERSE SIZE)', 'UTF-8', '(LARGER %d)' % SIZE)
  unreads = data[0].split()
  print '%d messages are between %d and %d KB.' % (len(unreads), MINSIZE, MAXSIZE)
  ids = ','.join(unreads[:MAX_FETCH])
  if ids:
    print
    print 'Listing %d messages:' % min(len(unreads), MAX_FETCH)
    typ, data = imap_conn.fetch(ids, '(RFC822.HEADER)')
    for item in data:
      if isinstance(item, tuple):
        raw_msg = item[1]
        msg = email.message_from_string(raw_msg)
        # Some email's header are encoded, for example: '=?UTF-8?B?...'
        print '\033[1;35m%s\033[0m: \033[1;32m%s\033[0m' % (
            email.header.decode_header(msg['from'])[0][0],
            email.header.decode_header(msg['subject'])[0][0],
            )
  imap_conn.close()
  imap_conn.logout()


if __name__ == '__main__':
  main()

The output would look like:

% python2.5 ./gmail-xoauth-find-large.py
Larger than in KB [1000]?
Smaller than in KB [5000]?

23 messages are between 1000 and 5000 KB.

Listing 20 messages:
[messages here]

The search would take quite a lot of time to complete, up to minutes. So, please be patient.

I want to find those big emails because I couldnt figure out why 9,085 emails can take up to 543 MB in my Gmail. I found the biggest mail, 15,189KB, 2.80% of used space. Second and third takes 9,366 and 7,659KB, together take 3.14%.