统计自己的命令历史

December 19, 2013

简单地统计了最近三个多月过我常用的命令,这里的命令是指自己输入的而且被记录到历史文件的命令,alias不展开。

结果

(用Google的API画的图,所以你懂的)

ls用的比想像中多,要想办法降下去。

实现

Gist

为了找出历史记录里用过的全部命令,一个完整的Shell脚本解析器是必须的,所以我用了language-sh(是我稍微修改过的版本,修改了一些类型错误,为AST节点派生DataTypeable),试了一些脚本,基本满足要求。经过解析之后就得到一棵抽象语法树(类型是Command),其中的Statement节点上的第一子节点就是我想要的命令名(贪方便,返回列表而不是Maybe String):

getCommand :: Statement -> [String]
getCommand (Statement (x:_) _ _) = [pretty x]
getCommand _ = []

但是那些Statement节点在AST里藏得很深,而且里面还有递归的节点,要遍历好像很难。所以我用syb来遍历AST:

collectCommand :: Data a => a -> [String]
collectCommand = everything (++) ([] `mkQ` getCommand)

遍历呢?我只要关注怎样从Statement里得到命令(getCommand),遍历都被everything处理了,泛型编程万岁。

然后就是读~/.bash_history,解析时间和命令,得到一个列表,就可以进行各种查询了。