<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>DaNmarner的中文博客</title><link>http://blog.danmarner.com/me/</link><description>有关Linux，Django，Python，Vim什么的。</description><language>en-us</language><lastBuildDate>Sat, 09 Apr 2011 22:09:33 +0000</lastBuildDate><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/danmarner/blog" /><feedburner:info uri="danmarner/blog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><title>随手翻译解救udev同学</title><link>http://feedproxy.google.com/~r/danmarner/blog/~3/hWUgzDe7cko/</link><description>&lt;p&gt;udev的大名儿是"Linux dynamic device management"，也就是管理硬件设备的同志。&lt;/p&gt;
&lt;p&gt;这位udev总管（btw，她的名字很商业嘛，优德弗听起来像不像优特友博/你管子他表姐？）是kernel陛下的外交部发言人之一。日理万机的kernel根本没空跟外界解释它是怎么决定和命名每个硬件设备的，所以每次他念出一个设备名的时候，udev同志就会出来把他老人家之乎者也的圣旨翻译成通俗易懂的设备名称，事件，并且根据她私藏的数据库通知每个相关人士。&lt;/p&gt;
&lt;p&gt;udev同志在进程大街的办公室名为udevd，通信地址是 /etc/udev/ 和 /lib/udev 。想跟她交往的同学请RTFM先。&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=hWUgzDe7cko:JCfUSJQFin8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=hWUgzDe7cko:JCfUSJQFin8:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=hWUgzDe7cko:JCfUSJQFin8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?i=hWUgzDe7cko:JCfUSJQFin8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=hWUgzDe7cko:JCfUSJQFin8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=hWUgzDe7cko:JCfUSJQFin8:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=hWUgzDe7cko:JCfUSJQFin8:XAVGb8Xj5zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=XAVGb8Xj5zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/danmarner/blog/~4/hWUgzDe7cko" height="1" width="1"/&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">DaNmarner</dc:creator><pubDate>Sat, 09 Apr 2011 22:09:33 +0000</pubDate><guid isPermaLink="false">http://blog.danmarner.com/me/entry/what-is-udev-exactly/</guid><feedburner:origLink>http://blog.danmarner.com/me/entry/what-is-udev-exactly/</feedburner:origLink></item><item><title>学Vim的人你们伤不起</title><link>http://feedproxy.google.com/~r/danmarner/blog/~3/C1oixZZkXDI/</link><description>&lt;p&gt;这是最终修正版，如果还有问题，我会继续修正……首发于 &lt;a href="http://twitter.com/#!/DaNmarner/status/46464238826434561"&gt;Twitter&lt;/a&gt;。咆哮者系本人。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.flickr.com/photos/22042381@N07/5528502444/" title="学Vim的人你们伤不起 by DaNmarner, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5179/5528502444_af683f1c2c.jpg" width="415" height="500" alt="学Vim的人你们伤不起" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;点击可以看大图。&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=C1oixZZkXDI:yRxojCDw3VA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=C1oixZZkXDI:yRxojCDw3VA:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=C1oixZZkXDI:yRxojCDw3VA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?i=C1oixZZkXDI:yRxojCDw3VA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=C1oixZZkXDI:yRxojCDw3VA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=C1oixZZkXDI:yRxojCDw3VA:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=C1oixZZkXDI:yRxojCDw3VA:XAVGb8Xj5zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=XAVGb8Xj5zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/danmarner/blog/~4/C1oixZZkXDI" height="1" width="1"/&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">DaNmarner</dc:creator><pubDate>Tue, 15 Mar 2011 04:32:10 +0000</pubDate><guid isPermaLink="false">http://blog.danmarner.com/me/entry/dont-hurt-vim-learner/</guid><feedburner:origLink>http://blog.danmarner.com/me/entry/dont-hurt-vim-learner/</feedburner:origLink></item><item><title>Django 补丁接受</title><link>http://feedproxy.google.com/~r/danmarner/blog/~3/jtXuOHIZO0g/</link><description>&lt;p&gt;这是本人第二枚遭到接受的补丁，&lt;a href="http://blog.danmarner.com/me/entry/patch-accepted-by-django-for-1st-time/"&gt;上次是2010年8月&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://code.djangoproject.com/ticket/15609"&gt;Trac #15609&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://code.djangoproject.com/changeset/15811"&gt;Change Set 15811&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;补丁内容是把所有异常的提出方式改为 raise Exception(msg) 的形式，为将来的 Python 3 移植作准备。&lt;/p&gt;
&lt;p&gt;提交到源里的是Django的创建者之一 &lt;a href="http://www.twitter.com/adrianholovaty"&gt;Adrian Holovaty&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;令人震惊的是，这个补丁从提交到进入代码库只花了2个小时！从我产生该想法到进入源玛也不到3个小时。Django 社区的效率较之从前真是高了许多呀。&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=jtXuOHIZO0g:_fbw2zKNStM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=jtXuOHIZO0g:_fbw2zKNStM:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=jtXuOHIZO0g:_fbw2zKNStM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?i=jtXuOHIZO0g:_fbw2zKNStM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=jtXuOHIZO0g:_fbw2zKNStM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=jtXuOHIZO0g:_fbw2zKNStM:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=jtXuOHIZO0g:_fbw2zKNStM:XAVGb8Xj5zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=XAVGb8Xj5zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/danmarner/blog/~4/jtXuOHIZO0g" height="1" width="1"/&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">DaNmarner</dc:creator><pubDate>Tue, 15 Mar 2011 03:32:40 +0000</pubDate><guid isPermaLink="false">http://blog.danmarner.com/me/entry/django-patch-accepted-again/</guid><feedburner:origLink>http://blog.danmarner.com/me/entry/django-patch-accepted-again/</feedburner:origLink></item><item><title>如何向Python 3过渡？</title><link>http://feedproxy.google.com/~r/danmarner/blog/~3/XidHFKAzEn4/</link><description>&lt;p&gt;如何向Python 3过渡？作为软件库提供者，你有三种选择：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;放弃 Python 2 支持，投向 Python 3 怀抱。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在 VCS (svn, git, hg, bzr) 里保留两个分支，分别支持两个版本。其效果类似第一种选择：保留Python 2分支是为了进行 bugfix ， 最终目标是等待大多数用户转而使用 Python 3 分支。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;同时发布两个版本的代码，根据运行环境决定运行哪一个版本的代码。这可能比听上去简单一些。假设你在库的 src2 和 src3 分别放置 Python 2 代码和 Python 3 代码，然后在 setup.py 里面加入下面这段代码::&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;
    import sys
    from distutils.core import setup
    if sys.version &lt; '3':
        package_dir = {'': 'src2'}
    else:
        package_dir = {'': 'src3'}
    setup(name='dual', version='1.0', package_dir=package_dir)

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这样用户安装库的时候，会得到正确的版本。&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=XidHFKAzEn4:5i11Bh-D56Y:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=XidHFKAzEn4:5i11Bh-D56Y:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=XidHFKAzEn4:5i11Bh-D56Y:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?i=XidHFKAzEn4:5i11Bh-D56Y:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=XidHFKAzEn4:5i11Bh-D56Y:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=XidHFKAzEn4:5i11Bh-D56Y:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=XidHFKAzEn4:5i11Bh-D56Y:XAVGb8Xj5zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=XAVGb8Xj5zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/danmarner/blog/~4/XidHFKAzEn4" height="1" width="1"/&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">DaNmarner</dc:creator><pubDate>Mon, 14 Mar 2011 17:21:23 +0000</pubDate><guid isPermaLink="false">http://blog.danmarner.com/me/entry/porting-to-python-3/</guid><feedburner:origLink>http://blog.danmarner.com/me/entry/porting-to-python-3/</feedburner:origLink></item><item><title>Kindle客服初体验 </title><link>http://feedproxy.google.com/~r/danmarner/blog/~3/_PAJE9K4oJc/</link><description>&lt;p&gt;Kindle 3系统升级到3.1beta速度明显有改善。可惜哈皮了没几天，Kindle就在一个风雨交加的夜晚变砖了。这可不是一般的死机：任凭你硬重启，接USB，放冰箱...屏幕的画面岿然不动！&lt;/p&gt;
&lt;p&gt;无奈之下之好去Amazon找客服。最后在order history找到了两个联系客服的选项：email和电话。电话的后面还有一括号：preffered。Preffered？好啊我也prefer打电话！填上自己的号码按下确定按钮，没过几秒电话响了。&lt;/p&gt;
&lt;p&gt;先是语音提示这次通话过程将被记录云云，最后一句是当前的等候时间为1分钟。音乐大概也就持续了20秒就终止了。一个充满愉悦之情的男性声音出现。&lt;/p&gt;
&lt;p&gt;他先问了一下我的姓名，确认了Kindle的型号和入手时间（2010年9月）。然后开始指导我尝试硬关机，失败以后又问了一下充电LED指示灯是否亮着（是）。&lt;/p&gt;
&lt;p&gt;随后，出乎意料之外，这位客服毫无延迟的继续道，“这么说来问题比较严重。我给您换给新的吧，都是免费的。”&lt;/p&gt;
&lt;p&gt;此时距电话响起，仅仅过了3分钟！就这么给我换了！&lt;/p&gt;
&lt;p&gt;换新程序是这样的：&lt;/p&gt;
&lt;p&gt;客服跟我确认了Amazon账户绑定的信用卡号码后四位。新的Kindle 3（包含已购电子书）在第二天寄到。同时我收到一封电邮，内含回寄用邮资的链接。
打印出该链接指向的内容贴到新Kindle的包装上，把变砖的Kindle放进去、交给UPS就好了。客服还特地提醒我充电器和数据线不用回寄。&lt;/p&gt;
&lt;p&gt;从我在客服页面点“call me”，到沟通完成，大概只花了6、7分钟的样子。&lt;/p&gt;
&lt;p&gt;去看其他人对Kindle客服的评价，一般都是相当正面的；亲身体验过后，我只能同意。可见有缺陷的产品在售后服务的支持下，还是可以给力的！&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=_PAJE9K4oJc:VVvJyIgID80:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=_PAJE9K4oJc:VVvJyIgID80:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=_PAJE9K4oJc:VVvJyIgID80:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?i=_PAJE9K4oJc:VVvJyIgID80:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=_PAJE9K4oJc:VVvJyIgID80:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=_PAJE9K4oJc:VVvJyIgID80:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=_PAJE9K4oJc:VVvJyIgID80:XAVGb8Xj5zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=XAVGb8Xj5zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/danmarner/blog/~4/_PAJE9K4oJc" height="1" width="1"/&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">DaNmarner</dc:creator><pubDate>Tue, 01 Mar 2011 05:11:44 +0000</pubDate><guid isPermaLink="false">http://blog.danmarner.com/me/entry/Kindle-customer-service-experience/</guid><feedburner:origLink>http://blog.danmarner.com/me/entry/Kindle-customer-service-experience/</feedburner:origLink></item><item><title>在Gentoo上使用笔记本触摸板</title><link>http://feedproxy.google.com/~r/danmarner/blog/~3/v0kVRkFcHms/</link><description>&lt;p&gt;经过几翻折腾，终于能在Gentoo下正常使用触摸板了，简单记录一下值得注意的地方。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;内核选项&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;确保 evdev 选中的前提下，把 PS/2 mouse 选中就够了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;驱动安装&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;USE 里一定要加上 hal 。&lt;/p&gt;
&lt;p&gt;然后 emerge -uN xorg-server xf86-input-synaptics 。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;功能调试&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Gentoo 的 Wiki 里充满了过时的信息。目前 Google 一下 Gentoo Synaptics ，第一个结果页面里就包含了通过 xorg.conf ， hal 和 udev 设置触摸板这三种办法。在最新版本(&amp;gt;7.3)的 Xorg 中唯一奏效的是 udev 的方法。具体步骤是创建 /usr/share/X11/xorg.conf.d/50-synaptcis.conf 文件，内容如下：&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;   Section &amp;quot;InputClass&amp;quot;
           Identifier &amp;quot;touchpad catchall&amp;quot;
           Driver &amp;quot;synaptics&amp;quot;
       MatchDevicePath &amp;quot;/dev/input/event*&amp;quot;
           MatchIsTouchPad &amp;quot;on
       Option &amp;quot;VertEdgeScroll&amp;quot; &amp;quot;on&amp;quot;
           Option &amp;quot;TapButton1&amp;quot; &amp;quot;1&amp;quot;
   EndSection&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;MatchDevicePath 这一行是触摸板在系统对应的设备文件，可以通过察看 /proc/bus/input/devices 的内容找到 (Synaptics 下面的 Handlers 项)。更多的 Option 可以在 man synaptics 里找到。比如把两指点击触发右键可以通过 Option "TapButton2" "3" 来实现。 &lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=v0kVRkFcHms:-nGRk7cjr20:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=v0kVRkFcHms:-nGRk7cjr20:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=v0kVRkFcHms:-nGRk7cjr20:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?i=v0kVRkFcHms:-nGRk7cjr20:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=v0kVRkFcHms:-nGRk7cjr20:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=v0kVRkFcHms:-nGRk7cjr20:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=v0kVRkFcHms:-nGRk7cjr20:XAVGb8Xj5zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=XAVGb8Xj5zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/danmarner/blog/~4/v0kVRkFcHms" height="1" width="1"/&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">DaNmarner</dc:creator><pubDate>Thu, 27 Jan 2011 21:35:07 +0000</pubDate><guid isPermaLink="false">http://blog.danmarner.com/me/entry/gentoo-synaptics/</guid><feedburner:origLink>http://blog.danmarner.com/me/entry/gentoo-synaptics/</feedburner:origLink></item><item><title>用clonezilla备份你的（黑苹果）系统</title><link>http://feedproxy.google.com/~r/danmarner/blog/~3/51hbYyhFEmM/</link><description>&lt;p&gt;更新10.6.6失败了以后开始找寻全盘备份黑苹果的方案，然后就找到了神奇的 clonezilla 。用它把刚刚装完雪豹的分区备份下来，以后就可以“一键恢复”了。&lt;/p&gt;
&lt;p&gt;先简略介绍一下这个软件的几大特点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;开源。代码在 sourceforge 。其实是个基于 Debian 的 Linux 发行版。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;由台湾牛人开发，支持中文，相信对很多朋友来说是很重要的。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;操作傻瓜化。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;最重要的，功能强大。具体表现在支持 HFS+ 和 NTFS 等等各种格式的全盘/分区备份。同时备份MBR信息，所以不用担心 bootloader 丢失。Server 版本还支持多机部署。程序本身也可以运行在 Windows 或者 Linux 下面。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;下面介绍一下单机版 （clonezilla-live） 在 Linux 下的使用过程：&lt;/p&gt;
&lt;p&gt;有系统镜像制作或使用经历的人想到的第一步应该是“启动介质”吧？
它可以是一张光盘，一个U盘或者外接USB硬盘。&lt;/p&gt;
&lt;p&gt;clonezilla 也要求使用这样一个介质，准备它的过程简单到了极点：只要根据你的操作系统&lt;a href="http://tuxboot.org/download/files-on-sf.php"&gt;下载&lt;/a&gt;这个叫做 &lt;a href="http://tuxboot.org"&gt;Tuxboot&lt;/a&gt; 的图形化小工具。插入你准备使用的启动介质，打开 Tuxboot，在界面的"type"部分选择你的介质，然后点"OK"。Tuxboot 会自动下载合适的 clonezilla 并安装到你的介质上，并把它设置成一个启动介质。注：这些下载涉及到 sourceforge，可能需要翻墙。&lt;/p&gt;
&lt;p&gt;Tuxboot界面很简洁，如下图：&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.flickr.com/photos/22042381@N07/5333191078/" title="Tuxboot by DaNmarner, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5283/5333191078_af9d22c8c3.jpg" width="500" height="310" alt="Tuxboot" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;clonezilla 大概 100+MB 的样子，下载过后的安装过程很快。&lt;/p&gt;
&lt;p&gt;如果你对这种全自动过程放心不下，也可以在&lt;a href="http://clonezilla.org/clonezilla-live.php"&gt;官网&lt;/a&gt;找到手动安装的步骤。&lt;/p&gt;
&lt;p&gt;启动介质做好以后的事情就简单多了，插入启动介质（比如U盘）到你想备份的系统分区所在的机器，（对我来说是装了黑苹果的华硕 1005ha 上网本），重启，选择从该介质启动。看到一个类似 Grub 的菜单。在这里可以选择语言。然后会进入文字菜单的界面，选择制作还是恢复镜像，镜像的保存位置和来源，镜像文件分隔体积等等，跟着提示操作就行了。我用了专家模式，没有碰到任何意外。&lt;/p&gt;
&lt;p&gt;一个 35G 的 HFS+ 分区镜像大概花了45分钟就做好了。生成的镜像有 15G 左右（根据选择的压缩模式不同可能比例也不一样）。&lt;/p&gt;
&lt;p&gt;以后再碰到黑苹果升级失败就不用重头装了，估计 Linux 甚至 Windows 也用的上吧。&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=51hbYyhFEmM:O_KKK7UwLls:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=51hbYyhFEmM:O_KKK7UwLls:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=51hbYyhFEmM:O_KKK7UwLls:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?i=51hbYyhFEmM:O_KKK7UwLls:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=51hbYyhFEmM:O_KKK7UwLls:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=51hbYyhFEmM:O_KKK7UwLls:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=51hbYyhFEmM:O_KKK7UwLls:XAVGb8Xj5zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=XAVGb8Xj5zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/danmarner/blog/~4/51hbYyhFEmM" height="1" width="1"/&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">DaNmarner</dc:creator><pubDate>Fri, 07 Jan 2011 14:31:47 +0000</pubDate><guid isPermaLink="false">http://blog.danmarner.com/me/entry/clonezilla-clone-hackintosh/</guid><feedburner:origLink>http://blog.danmarner.com/me/entry/clonezilla-clone-hackintosh/</feedburner:origLink></item><item><title>在Ubuntu 10.10安装Emacs 23.2</title><link>http://feedproxy.google.com/~r/danmarner/blog/~3/Fh-hMcn7Cm0/</link><description>&lt;p&gt;Ubuntu 10.10 自带的 Emacs 是23.1 版本的。因为需要用到 js-mode 等不及 11.4 的同学可以从 PPA 安装 Emacs 23.2 ：&lt;/p&gt;
&lt;p&gt;sudo apt-add-repository ppa:ubuntu-elisp/ppa&lt;/p&gt;
&lt;p&gt;sudo apt-get update &amp;amp;&amp;amp; sudo apt-get upgrade emacs --purge&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=Fh-hMcn7Cm0:dhlIpqQD7kY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=Fh-hMcn7Cm0:dhlIpqQD7kY:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=Fh-hMcn7Cm0:dhlIpqQD7kY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?i=Fh-hMcn7Cm0:dhlIpqQD7kY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=Fh-hMcn7Cm0:dhlIpqQD7kY:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=Fh-hMcn7Cm0:dhlIpqQD7kY:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=Fh-hMcn7Cm0:dhlIpqQD7kY:XAVGb8Xj5zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=XAVGb8Xj5zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/danmarner/blog/~4/Fh-hMcn7Cm0" height="1" width="1"/&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">DaNmarner</dc:creator><pubDate>Tue, 04 Jan 2011 18:11:50 +0000</pubDate><guid isPermaLink="false">http://blog.danmarner.com/me/entry/ubuntu-1010-emacs-232-installation/</guid><feedburner:origLink>http://blog.danmarner.com/me/entry/ubuntu-1010-emacs-232-installation/</feedburner:origLink></item><item><title>英文中文，Ubuntu下设定Emacs输入法的曲折经历</title><link>http://feedproxy.google.com/~r/danmarner/blog/~3/BBZnoZv0dSE/</link><description>&lt;p&gt;这片文章是在 Ubuntu 10.10 英文界面下，用 ibus-sunpinyin 在 Emacs 里敲出来的。它之所以存在完全是因为本人对中英混合环境要求过于苛刻，导致初学Emacs 的笔者经历了一次小小的波折。&lt;/p&gt;
&lt;p&gt;DaNmarner 选择“出墙”（Sorry Vim）学习 Emacs 的三大原因之一是中英文混合输入的时候它的表现比 Vim 更加自然。后者的最强项在遇到中文输入以后变成了致命硬伤：命令模式在字母键上的绑定。即使经过了很多年的使用（例如本博客之前所有的中文文章都是在 Vim 下面写的），在从编辑模式切换到命令模式的时候避免命令被输入法程序截取还是一件很头痛，很影响效率的事情。&lt;/p&gt;
&lt;p&gt;然而为了在 Ubuntu 这个麻瓜友好的环境里享受 Emacs 对以上问题的免疫力，笔者遭遇了两个问题。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第一回合：iBus 在 Emacs 里失灵了&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;通过 apt-get 安装了 Emacs 以后，一个英文 Ubuntu 用户会发现通过 Ctrl+空格 启动 ibus 在 Emacs 里毫无效果。&lt;/p&gt;
&lt;p&gt;这个问题相信会用 Google 的同学都能解决：只要把 LC_CTYPE 的值设定为 zh_CN.UTF-8 就可以了。&lt;/p&gt;
&lt;p&gt;保存这个值的位置有很多，比较明显的地方是 /etc/environment ，在这个文件最后加上&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;LC_CTYPE=&amp;quot;zh_CN.UTF-8&amp;quot;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;然后重启一下就可以在 Emacs 里正常启动 iBus 了。&lt;/p&gt;
&lt;p&gt;这里澄清一件事，很多 Google 后出现的结果里说 Ctrl+空格 因为和 Emacs 默认的选择命令冲突而无法激活 iBus ，这其实是不对的。事实证明 X 会保证先于Emacs 截获它从而顺利激活 iBus 。不过为了 Emacs 避免使用这个组合还是有价值的，改成 Shift+空格 就不错，除非你喜欢 C-@ 多过 C-&amp;lt;SPC&amp;gt;。&lt;/p&gt;
&lt;p&gt;一般来说，问题到这已经解决了。但对于 DaNmarner 来说，还有一个很头痛的问题。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第二回合：RTFM 的要求&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;一个无奈的现实：DaNmarner 已经习惯了英文的技术文档。中文文档虽然有爱，但因为从一开始就在英文环境里摸爬滚打，所以中文的 Emacs 手册看起来觉得很吃力……矛盾吧，还在用中文写作！（其实这也是为了 keep-up 自己的中文水
平。） &lt;/p&gt;
&lt;p&gt;在修改了 LC_CTYPE 以后，Emacs 会很友好的把所有帮助/手册以中文显示（相对Vim 这是一个不错的优势）。可惜笔者（臭屁地）认为这是友好过度了！那么怎么找回英文手册呢？能不能不修改 LC_CTYPE 就让 iBus 正常工作呢？一番调查之后笔者的结论是：在 Ubuntu 下这还是一个未解之谜。&lt;/p&gt;
&lt;p&gt;所以最终的 Workaround 是，保留 zh_CN.UTF-8 作为 LC_CTYPE 的值，使得 iBus 可用，然后在 Emacs 配置文件里强制设定语言环境为英文，既加入下面这行：&lt;/p&gt;
&lt;p&gt;(set-language-environment 'English)&lt;/p&gt;
&lt;p&gt;这是一个差强人意的方法，至少英文手册回来了，iBus-sunpinyin 也能用了。根本的解决办法，或许是背叛 Ubuntu 投靠其它发行版吧 ：）&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=BBZnoZv0dSE:LxLFoW894Hw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=BBZnoZv0dSE:LxLFoW894Hw:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=BBZnoZv0dSE:LxLFoW894Hw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?i=BBZnoZv0dSE:LxLFoW894Hw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=BBZnoZv0dSE:LxLFoW894Hw:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=BBZnoZv0dSE:LxLFoW894Hw:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=BBZnoZv0dSE:LxLFoW894Hw:XAVGb8Xj5zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=XAVGb8Xj5zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/danmarner/blog/~4/BBZnoZv0dSE" height="1" width="1"/&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">DaNmarner</dc:creator><pubDate>Mon, 03 Jan 2011 09:16:05 +0000</pubDate><guid isPermaLink="false">http://blog.danmarner.com/me/entry/ubuntu-emacs-ibus-setup-and-english-manual/</guid><feedburner:origLink>http://blog.danmarner.com/me/entry/ubuntu-emacs-ibus-setup-and-english-manual/</feedburner:origLink></item><item><title>在Kindle上学Emacs</title><link>http://feedproxy.google.com/~r/danmarner/blog/~3/Czn8Kwsrwtw/</link><description>&lt;p&gt;最近我这个多年Vim粉丝在“出墙”学Emacs。&lt;/p&gt;
&lt;p&gt;作为一个深度Kindle 3用户mobi格式的用户手册是必不可少的。&lt;/p&gt;
&lt;p&gt;所以只好自己做了一个，Twitter上放过链接了，这里再放一次算是充数一篇博文。&lt;/p&gt;
&lt;p&gt;有兴趣的请猛击下载&lt;a href="http://db.tt/xyrJkma"&gt;mobi格式英文Emacs用户手册&lt;/a&gt;。&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=Czn8Kwsrwtw:BuCoNzvLXl8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=Czn8Kwsrwtw:BuCoNzvLXl8:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=Czn8Kwsrwtw:BuCoNzvLXl8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?i=Czn8Kwsrwtw:BuCoNzvLXl8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=Czn8Kwsrwtw:BuCoNzvLXl8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=Czn8Kwsrwtw:BuCoNzvLXl8:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=Czn8Kwsrwtw:BuCoNzvLXl8:XAVGb8Xj5zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=XAVGb8Xj5zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/danmarner/blog/~4/Czn8Kwsrwtw" height="1" width="1"/&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">DaNmarner</dc:creator><pubDate>Tue, 28 Dec 2010 06:55:08 +0000</pubDate><guid isPermaLink="false">http://blog.danmarner.com/me/entry/kindle-mobi-emacs-user-manual/</guid><feedburner:origLink>http://blog.danmarner.com/me/entry/kindle-mobi-emacs-user-manual/</feedburner:origLink></item><item><title>PDF去边利器：Kindle 的 GNU 好友 pdfcrop</title><link>http://feedproxy.google.com/~r/danmarner/blog/~3/b-8w6s2qvnI/</link><description>&lt;p&gt;PDF是最流行的文档格式之一。大多数的在线文档都提供PDF格式，LaTeX，OOo 甚至 MS Office也提供PDF格式的转换。遗憾的是该格式优点无数，可就是不适合在Kindle 3上阅读——它本身是为了打印而发明的，所以边缘预留了适当的空白区域，直接导致正文在Kindle 3的可读性下降。&lt;/p&gt;
&lt;p&gt;虽然大多数PDF文件的字体还是偏小，去掉空白以后的阅读效果还是会增强不少的，如果有什么工具能自动实现这一点就好了……下面隆重推出 Ubuntu 里隐藏的一个 Python 脚本： pdfcrop ，它只有一个功能，你猜是什么(囧，就这么写吧)？&lt;/p&gt;
&lt;p&gt;废话不说了，pdfcrop 是 texlive-extra-utils 的一部分，从图形界面或者用下面这行命令进行安装：&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;sudo apt-get install texlive-extra-utils&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;安装好了可以用&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;pdfcrop -h&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;看帮助，其中我们关心的只有这一条：&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;pdfcrop --margins 0 原pdf文件 输出pdf文件&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;其中 --margins 后面的数字是留白的宽度，默认是0。可以用四个数字依指明左、上、右、下留白的宽度。如果一点空白也不想要的话可以直接这样：&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;pdfcrop 原文件.pdf 新文件.pdf&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;另外，pdfcrop的主页在&lt;a href="http://pdfcrop.sourceforge.net/"&gt;这里&lt;/a&gt;，如果你的Linux发行版不包含它，可以通过主页链接到sourceforge下载该脚本。&lt;/p&gt;
&lt;p&gt;Kindle 也是 Linux 家族，一家人碰到一块就是给力呀！&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=b-8w6s2qvnI:mqcm9jxJefY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=b-8w6s2qvnI:mqcm9jxJefY:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=b-8w6s2qvnI:mqcm9jxJefY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?i=b-8w6s2qvnI:mqcm9jxJefY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=b-8w6s2qvnI:mqcm9jxJefY:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=b-8w6s2qvnI:mqcm9jxJefY:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=b-8w6s2qvnI:mqcm9jxJefY:XAVGb8Xj5zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=XAVGb8Xj5zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/danmarner/blog/~4/b-8w6s2qvnI" height="1" width="1"/&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">DaNmarner</dc:creator><pubDate>Wed, 08 Dec 2010 07:03:15 +0000</pubDate><guid isPermaLink="false">http://blog.danmarner.com/me/entry/kindle-gnu-friend-pdfcrop-remove-pdf-margins/</guid><feedburner:origLink>http://blog.danmarner.com/me/entry/kindle-gnu-friend-pdfcrop-remove-pdf-margins/</feedburner:origLink></item><item><title>我的推特同步脚本</title><link>http://feedproxy.google.com/~r/danmarner/blog/~3/eRpFkQUWC9o/</link><description>&lt;p&gt;&lt;a href="http://www.williamlong.info/"&gt;月光&lt;/a&gt;曾经发布过一个通过GAE同步推特到国内微博的脚本。使用过一段时间以后，DaNmarner 发现其中有一些问题，比如一旦同步某个服务超时，本次的同步就无法被记录下来，而下次同步的时候一些平台就会出现重复信息。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/DaNmarner/twitter-syncr"&gt;这里&lt;/a&gt;是我对该脚本的hack。利用了Task Queue来避免超时的问题。&lt;/p&gt;
&lt;p&gt;使用方法是在 config.py 去掉需要同步平台的注释，填写对应用户名和密码。别忘了最后写上需要同步的Twitter ID。&lt;/p&gt;
&lt;p&gt;当然还要修改 app.yaml，写上你GAE程序的id。&lt;/p&gt;
&lt;p&gt;另外在 README.txt 也提到，如果你需要修改代码再次发布，不妨利用 deploy 以及 secret.py。&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=eRpFkQUWC9o:6rFmjO3uSZE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=eRpFkQUWC9o:6rFmjO3uSZE:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=eRpFkQUWC9o:6rFmjO3uSZE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?i=eRpFkQUWC9o:6rFmjO3uSZE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=eRpFkQUWC9o:6rFmjO3uSZE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=eRpFkQUWC9o:6rFmjO3uSZE:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=eRpFkQUWC9o:6rFmjO3uSZE:XAVGb8Xj5zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=XAVGb8Xj5zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/danmarner/blog/~4/eRpFkQUWC9o" height="1" width="1"/&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">DaNmarner</dc:creator><pubDate>Mon, 29 Nov 2010 19:04:52 +0000</pubDate><guid isPermaLink="false">http://blog.danmarner.com/me/entry/twitter-sync-script/</guid><feedburner:origLink>http://blog.danmarner.com/me/entry/twitter-sync-script/</feedburner:origLink></item><item><title>Javascript点滴0x05：第一滴血</title><link>http://feedproxy.google.com/~r/danmarner/blog/~3/er4DgJZN804/</link><description>&lt;p&gt;全局变量是魔鬼。在 Javascript 遇到魔鬼的可能性比任何其它语言都大。作为一个 Coder， 尽量少召唤魔鬼是一种至高美德。你的模块应该生活在一个单一的全局变量里，比如 MYAPP:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;var MYAPP = MYAPP || {};&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;添加一个模块：&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;MYAPP.module = MYAPP.module || {};&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;使用 || 检查模块名是否已经存在是很好的习惯。然而一旦模块层次多了起来，这样的代码很快就会变成一种负担（MYAPP.module2.model1.obj0 怎么定义？）。&lt;/p&gt;
&lt;p&gt;所以下面这个 namespace() 方法应该作为你全局变量的第一个方法：&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;MYAPP.namespace = function(ns_str) {
    var parts = ns_str.split('.'),
        parent = MYAPP,
        i;
    if (parts[0] === 'MYAPP') {
        parts = parts.slice(1);
    }

    for (i=0; i&amp;lt;parts.length; i+=1) {
        if (typeof parent[parts[i]] === 'undefined') {
            parent[parts[i]] = {};
        }
        parent = parent[parts[i]];
    }

    return parent;
}&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;有了它，上面括号里的问题答案就变成了：&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;var obj0 = MYAPP.namespace('MYAPP.module2.model1.obj0');&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;或者省略参数中的MYAPP:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;var obj0 = MYAPP.namespace('module2.model1.obj0');&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;有了这第一滴血，增加人品就轻而易举了。&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=er4DgJZN804:SfUdOGUOoVM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=er4DgJZN804:SfUdOGUOoVM:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=er4DgJZN804:SfUdOGUOoVM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?i=er4DgJZN804:SfUdOGUOoVM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=er4DgJZN804:SfUdOGUOoVM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=er4DgJZN804:SfUdOGUOoVM:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=er4DgJZN804:SfUdOGUOoVM:XAVGb8Xj5zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=XAVGb8Xj5zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/danmarner/blog/~4/er4DgJZN804" height="1" width="1"/&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">DaNmarner</dc:creator><pubDate>Thu, 25 Nov 2010 19:58:20 +0000</pubDate><guid isPermaLink="false">http://blog.danmarner.com/me/entry/javascript-0x04-namespace-function/</guid><feedburner:origLink>http://blog.danmarner.com/me/entry/javascript-0x04-namespace-function/</feedburner:origLink></item><item><title>Javascript点滴0x04：动态规划</title><link>http://feedproxy.google.com/~r/danmarner/blog/~3/J9ElpmEXst4/</link><description>&lt;p&gt;还记得动态规划吗？它曾经是我高中最大的困惑。动态规划这个词译自 Dynamic Programming —— 一个不知所云的短语。相比之下我更喜欢另一个描述同样东西的字：Memoization 。至少它暗示了动态规划的精髓：保存运算的结果，下次碰到同样的运算则直接使用该结果，从而剩下重复运算过程花费的时间。&lt;/p&gt;
&lt;p&gt;Javascript 的运行环境决定了动态规划这类节约时间的算法有额外的价值。问题是再哪里保存代码执行的结果？显然全局变量是最糟糕的答案，比放在某个 Object 的属性里还烂。最好的地点其实是运算代码本身所在的 function 实例里面。&lt;/p&gt;
&lt;p&gt;function 在 Javascript 里只不过是 object 的衍生类型，意味它可以有自己的属性甚至方法。如果使用 function 来执行了某个时间开销大的运算过程，那么不妨把每次运算使用的参数和结果保存在这个 function 自身，下次运算的时候先检查得到的参数是否已经有了结果，如果是就直接返回，没有再开始运算。具体请看下面这段代码：&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;var expensiveOperation = function () {
    var cachekey = JSON.stringify(Array.prototype.slice.call(arguments)),
        results;

    if (!expensiveOperation.cache[cachekey]) {
        result = {};
        // 执行运算
        expensiveOperation.cache[cachekey] = result;
    }

    return expensiveOperation.cache[cachekey];
};
expensiveOperation.cache = {};&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;把所有的参数转换成一个字串作为键，运算的结果作为值，保存到 function 的 cache 属性里。每次被调用的时候先检查这次参数在 cache 里是否有对应值，如果没有，则进行正常的计算，否则略过计算过程直接返回保存在 cache 里的结果。&lt;/p&gt;
&lt;p&gt;千万不要忘了最后那一行：cache 的初始化。&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=J9ElpmEXst4:PnwFyXPZtZU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=J9ElpmEXst4:PnwFyXPZtZU:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=J9ElpmEXst4:PnwFyXPZtZU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?i=J9ElpmEXst4:PnwFyXPZtZU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=J9ElpmEXst4:PnwFyXPZtZU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=J9ElpmEXst4:PnwFyXPZtZU:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=J9ElpmEXst4:PnwFyXPZtZU:XAVGb8Xj5zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=XAVGb8Xj5zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/danmarner/blog/~4/J9ElpmEXst4" height="1" width="1"/&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">DaNmarner</dc:creator><pubDate>Tue, 09 Nov 2010 12:00:00 +0000</pubDate><guid isPermaLink="false">http://blog.danmarner.com/me/entry/javascript-0x04-memoization/</guid><feedburner:origLink>http://blog.danmarner.com/me/entry/javascript-0x04-memoization/</feedburner:origLink></item><item><title>Javascript点滴0x03：会变身的原生类型</title><link>http://feedproxy.google.com/~r/danmarner/blog/~3/qvkeEigEoNM/</link><description>&lt;p&gt;Javascript 有几个原生的数据类型：number, string, boolean, null 和 undefined，剩下的＂东西＂全都是 object 及其衍生类。其中的 number，string 和 boolean 各自还有一个增强版本，可以使用对应首字母大写的构造函数
生成。&lt;/p&gt;
&lt;p&gt;这些增强版本比原生类型＂强＂在了自带的各种方法：Number的toFixed()，String的charAt()等等。&lt;/p&gt;
&lt;p&gt;很多人错以为原生类型和它们对应的增强类型是一样的。这很正常。因为在原生类型上调用增强类型的方法是合法的：Javascript 碰到这种情形会自动把前者转换成后者。下面用代码演示一下：&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;var prim = &amp;quot;hEllo&amp;quot;, // 原生string，用字面值建立
      augt = new String(&amp;quot;WorLD&amp;quot;); // 增强类型，由构造函数建立
alert(prim.toUpperCase()); // 输出 &amp;quot;HELLO&amp;quot;
alert(augt.toUpperCase());  // 输出 &amp;quot;WORLD&amp;quot;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;这里 prim 是原始生类型，augt 是增强类型，可以看到在二者调用 toUpperCase() 效果是一样的。
那他们之间的区别在哪？请继续看代码：&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;alert(typeof prim); // &amp;quot;number&amp;quot;
alert(typeof augt) // &amp;quot;object&amp;quot;
prim.n_of_l = 2;
augt.n_of_l = 1;
alert(prim.n_of_l); // &amp;quot;undefined&amp;quot;
alert(augt.n_of_l); // &amp;quot;1&amp;quot;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;上面的代码演示了Javascript的原生类型与其增强版本之间的两个区别：&lt;/p&gt;
&lt;p&gt;1  typeof 可以高速我们二者的本质区别：增强类型就是普通的 object 了。这点从new的使用也能体现出来。&lt;/p&gt;
&lt;p&gt;2   由于增强类型都是 object ，可以自由的给它赋予新的属性和方法；原生类型就没有这样的特性。给原生类型添加属性不会引发错误，但这么做没有效果。&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=qvkeEigEoNM:h5JvY6-z7q8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=qvkeEigEoNM:h5JvY6-z7q8:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=qvkeEigEoNM:h5JvY6-z7q8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?i=qvkeEigEoNM:h5JvY6-z7q8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=qvkeEigEoNM:h5JvY6-z7q8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=qvkeEigEoNM:h5JvY6-z7q8:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/danmarner/blog?a=qvkeEigEoNM:h5JvY6-z7q8:XAVGb8Xj5zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/danmarner/blog?d=XAVGb8Xj5zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/danmarner/blog/~4/qvkeEigEoNM" height="1" width="1"/&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">DaNmarner</dc:creator><pubDate>Sun, 07 Nov 2010 12:00:00 +0000</pubDate><guid isPermaLink="false">http://blog.danmarner.com/me/entry/javascript-0x03-primitive-vs-augumented/</guid><feedburner:origLink>http://blog.danmarner.com/me/entry/javascript-0x03-primitive-vs-augumented/</feedburner:origLink></item></channel></rss>

