简单地统计了最近三个多月过我常用的命令,这里的命令是指自己输入的而且被记录到历史文件的命令,alias不展开。
结果
(用Google的API画的图,所以你懂的)
ls
用的比想像中多,要想办法降下去。
实现
为了找出历史记录里用过的全部命令,一个完整的Shell脚本解析器是必须的,所以我用了language-sh(是我稍微修改过的版本,修改了一些类型错误,为AST节点派生Data
和Typeable
),试了一些脚本,基本满足要求。经过解析之后就得到一棵抽象语法树(类型是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
,解析时间和命令,得到一个列表,就可以进行各种查询了。