HHKB开箱

心仪已久的HHKB终于趁着双十一下单了。水一篇开箱博客。

箱子真是小,快递给放到云柜里面去了。包装很好,没有多余的东西,只有键盘本地,一根两头可以插拔的线,以及说明书。说明书也写的简单明白。

我的上一个键盘用的HHKB Lite2,用了一年,觉得很顺手。现在换到HHKB Pro2 Type-s,感觉没有了方向键两头对称感觉更美观了,但是也更不方便了。比如Mac切换屏幕是Control+方向,现在要通过Fn组合实现方向的功能。

键盘手感比较像红轴,但是声音小很多(呼哧呼哧的声音),比Lite2的声音也是小很多。刚上手感觉手感不是很好(感觉还不如Lite2)需要适应一段时间(键帽弧度,手腕高度)等。用一天下来感觉挺好的了。静音电容,能感受到的就是不用按到底就打出来字了。但其实好像并没有什么卵用,本来我们打字是肯定会按到底的

附上维基百科的HHKB“信仰”:

HHKB是株式会社PFU将东京大学的和田英一名誉教授所著的1995年度WIDEプロジェクト研究报告书中提及的个人用小型键盘实现所得的产物。和田认为,这个键盘是在以下三项基本原则的指导下做成的:

  1. 键盘作为基本输入设备乃人生涯所用之物,键盘布局不能像猫咪的眼睛那样不断地变来变去。
  2. 尽量减少按键的数目,以将其大小减少到可手持移动的程度。
  3. 面向Unix程序员的按键键盘布局。

盒子很小

全家福(卖家送的廉价小物品,键盘托和键帽,拔键器)

其实想买的是黑色的键盘,白色的怕用久了会发黄。但是type-s版本没有黑色款,只有白色(坑啊)。BT版本倒是有,也看了一下,BT版本只比Pro2多了一个蓝牙功能,竟然要贵出800块钱(抢钱啊!)。网上也看大家说type-s的手感更好,于是最终入手了白色有刻。大不了过几年再买一套新的键帽呗。

尝试一下

带到办公室

和HHKB Lite2的对比

除了手感,在功能上和Lite2也有一些不同,比如多了对Mac的音量调节键和亮度调节(别看按键少了很多,其实组合起来比一个普通104键的键盘都多)。

另外我之前使用Lite2经常出现“键盘进入了另一个模式”的感觉,按什么东西都是大写的,好像shift被一直按住似的,不知道怎么调回来。每次遇到这种情况,只好拔掉USB重新插上…… 希望这个键盘没有问题……

 

终端使用技巧

我在github上有一个仓库myrc用来存放自己所有的.xxxrc文件。使用的时候将Linux对应的文件位置软连接到git仓库的路径。这样在新环境下只需要几步就可以配置出自己熟悉的样子。

我一直在不断更新这个仓库,比如.vimrc.tmux.conf,.zshrc等(在偷懒的路上越走越远)。本文分享一下最近的一些更新,不少可以每天给你的生命节省几秒。

  • 使用on-my-zsh的插件,这里有很多自动补全、alias、实用脚本等。之前使用oh-my-zsh只是用theme,简直浪费生命啊!
  • oh-my-zsh的git插件。这个插件非常变态,提供了非常多的alias,基本上所有用的到的git命令都被alias到了1-4个按键。鉴于我30%的命令都是git,这个alias不得不说是……给我续了很多秒。
  • z:这个命令可以让你在各种路径之间自由穿梭,比如在任何地方进入我的myrc项目,只要敲z rc就可以,这个插件会根据“最近最经常使用”的路径搜索一个最匹配的文件夹cd过去(曾经因为换电脑丢失了这个命令,非常痛心,后来一番搜索终于找回来了)。mac可以通过brew安装。
  • oh-my-zsh的sudo插件。按两下ESC键自动打出上一条命令,并且在开头加上sudo。比起按↑+CTRL-a两次+sudo,又省了几秒
  • oh-my-zsh的osx插件。有很多实用命令,比如man-preview git可以打开osx的preview.app查看git的man page。感觉pdf看起来要比终端的舒服一些。还有比如在Finder中打开当前终端的dir等。
  • 使用pipsi。Python开发肯定要用到virtualenv,如果要装一些命令行工具,就比较麻烦:装到virtualenv里面也不是,装到系统环境里面也不是。pipsi可以给每一个命令新建一个虚拟环境,让命令独立于开发的virtualenv和系统的python。管理依赖不再成为噩梦。比如安装我的git-ext命令: pipsi install git-ext。就会新建一个venv叫git-ext,然后将命令以及所有的依赖装到这里面。
  • vim-gh-line。这个前面介绍过,很好用。
  • vim-gist。将当前vim的buffer post到gist。同事之间交流代码片段比较实用。
  • 更多的vim插件可以参考我的vimrc,我组织的还是挺科学的,比较好读。也欢迎给我推荐vim插件,欢迎交流。
  • fpp。全名/PathPicker,接受一个输入(可以是git的输出,其他输出等)然后处理出一些文件路径供你选择,选中之后使用系统编辑器打开。比如git status | fpp会列出一个文件列表,选中一个编辑。(发现比较难解释,试过就知道了……
 

Python 实现class_property

Python的property可以让我们很方便地将一个object的函数当做一个属性来操作,可以赋值、读取。

但是不支持class,如果想使用这个特性,就要实例化对象。我去参考了celery实现的class_property,发现有一行特别难懂,花了很长时间琢磨,终于是看懂了。

celery的代码如下:

使用方法如下:

这段代码能work,而是没有任何问题。装饰在class内的一个函数上,可以将此函数的返回值作为一个class的属性,可以通过class和instance来访问,并且还支持setter。

首先,__init__()比较好理解,传入getter和setter,将其转换为classmethod然后绑定到内部的变量上,以便后来调用。

setter()方法也比较好理解,可以当做装饰器调用, 然后已有的self.__get和传入的setter重新初始化一个class_property,如果已经有getter的话,这里也不会对getter造成影响。参考下面的例子:

然后看__get____set__方法,很明显,这里使用的描述器。(关于描述器,我之前有一篇博文详细讲了描述器——理解Python对象的属性和描述器。)第一个if判断是为了确保用class_property装饰的属性通过instance也能访问到。

最后到了最让人不理解的部分了,如果要我实现的话,是直接返回getter就可以了:

return self.__get()

这样看起来也没问题:访问Logging类的时候,发现没有这个already_setup这个属性,然后试图访问描述器,描述器__get__()中返回self.__get()不正好是getter会返回的结果吗?

于是我将这行return改成了上面我的意思,结果报错:

classmethod为什么不是callable的呢?因为classmethod本来就不是callable的!在之前的文章中,我模拟了classmethod的实现:

它的原理是这样的:Class读一个属性的时候,如果Class.__dict__有该属性并且属性不是一个描述器,就返回该属性;如果该属性是一个描述器,就调用它的__get__方法。

举个例子说,下面的代码:

在调用的时候,先看Foo.__dict__里面的bar是一个描述器,那么调用就转换成:

Foo.__dict__['bar'].__get__(None, Foo)()

回到我们的class_property上来,拿最初的Logging举例。用了class_property装饰的already_setup使用起来(Logging.already_setup)就是:

Logging.__dict__['already_setup'].__get__(None, Logging)()

执行我们的class_property的__get__之后,也就是

Logging.__dict__['already_setup'].__get()

此时,橙色的部分拿到的是一个class_property处理之后的classmethod,而上面我们可以看到,classmethod并不是callable的,而是通过描述器协议,class在调用的时候会默认调用__get__,然后拿到一个和class绑定之后的func,这时候的func才是可以调用的。

celery里面原来写的return,调用链展开就是:

Logging.__dict__['already_setup'].__get.__get__(obj, type)()

其中橙色的部分依然是拿到了classmethod,即:

Logging.classmethod_get.__get__(obj, type)()

classmethod的__get__()返回的是一个unbound method,即

Logging.already_setup()

这样调用就没问题了。

所以说,这里手动调用__get__(obj, type)的原因是,描述器协议之能调用一次,如果返回的还是一个描述器,那么并不会继续调用__get__方法,需要手动调用。

 

Python脚本的编码声明

在《Python文件的标准顺序》这篇文章中,介绍了一个Python文件标准的顺序。可以看到,Unix的shebang是优先于Python的文件编码的。本文详细介绍Python文件编码的声明。注意这里指的是Python脚本本身的编码,不是在Python中处理文件的编码。

Python程序员可能对这句话并不陌生,# -*- coding: utf-8 -*-。并且也在自己的脚本中这样写了。为什么要写的这么花哨呢?其实,这是Emacs的编码声明,这样写可以被Emacs编辑器和Pyhton解释器都兼容。对于使用Vim的程序员,其实应该写成这样: vim: set fileencoding=<encoding name> :。(好吧其实并没有Emacs好看)

如何声明?

PEP263中定义了对Python源码文件编码声明。

要定义Python的源代码编码,需要在第一行或第二行编写像下面这样的“magic comment”:
# coding=<encoding name>

编码方式是以一个正则来匹配的:

所以如果写成下面这样,也能工作:

其中编码的名字必须能被Python词法分析器认识,否则会报语法错误:

如果不写,那么将使用默认的编码ASCII(python2):

但是在Python3中默认的编码是UTF-8,所以上面的代码在Python3中运行没有错误。

如何安排编码声明和shebang的顺序?

Unix系统规定,可以使用shebang指定脚本默认的编辑器。例如:

而它被如此调用(”$”是命令提示符)

该命令的输出等同于

shebang的定义如下:

计算机科学中,Shebang(也称为 Hashbang )是一个由井号叹号构成的字符序列 #! ,其出现在文本文件的第一行的前两个字符。 在文件中存在 Shebang 的情况下,类 Unix 操作系统程序载入器会分析 Shebang 后的内容,将这些内容作为解释器指令,并调用该指令,并将载有 Shebang 的文件路径作为该解释器的参数。

所以说shebang要求文件的第一二个字符是#!,而Python为了兼容shebang,定义文件编码必须在第一行或第二行。

结论就很清晰了,应该先写shebang在写Python的文件编码。

配合Unicode BOM

在windows平台中,也是兼容Unicode BOM的。在文件的开头声明 \xef\xbb\xbf表示文件是UTF-8编码。

如果同时使用了Unicode BOM和文件编码注释,则文件编码注释必须和Unicode BOM相同(UTF-8),否则抛出错误。

 

推荐一个快速在Github打开当前代码行的Vim插件

我们公司用的仓库托管是bitbucket,有时候和同事讨论需要贴代码的链接,需要在网页上扒拉来吧拉去的(代码经常是用文件夹组织的比较深),痛苦啊,今天终于解决了这个痛点。

一开始想的是,在用octotree这种插件可以不刷新快速找代码。然而即使这样还是要你手动去扒拉的,这很反人类。后来我想,用Vim找代码多方便,如果有一个Vim插件,可以调用浏览器在Bitbuck上直接打开当前的代码行就好了。最后找到了/vim-gh-line !完美。我发现有时候Github的搜索框比Google都好用。

这个插件可以使用Vundle安装:

运行BundleInstall即可。

默认的快捷键是 <leader>gh,按下就会调用浏览器打开Github。这个插件从名字就可以看出,只支持Github的,所以我fork了一个版本,添加了<leader>bb可以支持Bitbucket。向原仓库提交了一个PR support bitbucket! #5 ,感觉作者维护这个仓库挺干净的,issue和PR都关掉了,我的这个PR应该也会很快处理吧。

临时可以安装我的fork来同时支持Bitbucket和Github。

这个作者应该是个重度的Vim用户,主页上有很多Vim有关的项目。


PR已经合并并重构,可以直接安装原作者的版本了,自动判断仓库是在github还是Bitbucket。