如何学习好的的代码

我有一个需求,当学习一门新语言的时候,经常想看看一些库或者函数的 best practice。官方文章只告诉你如何调用,没有说什么时候调用,前后的 context 是什么,怎么组织代码。而在 github 搜索这个函数的代码片段的时候,出来的结果经常十几页,其中大量重复的结果,并且大部分代码质量并不怎么样,所以我的需求是:

  1. 搜索范围只限定在我觉得的质量不错的项目中。
  2. 能显示上下文, 最好还能 index,查看定义和跳转。

sourcegraph 的自搭 container 就不错,支持 Golang, Java, Python, Javascript, Ruby (比 OpenGrok 好太多,也方便太多)。就是上面所说的需求2要付费(damn)。

Mac 上跑起来

sourcegraph 上演示用的命令是:

1
2
3
4
5
docker run \
--publish 7080:7080 --rm \
--volume $HOME/.sourcegraph/config:/etc/sourcegraph \
--volume $HOME/.sourcegraph/data:/var/opt/sourcegraph \
sourcegraph/server:2.5.17

然后这是无法在 Mac 上直接跑的,貌似 volume 在$HOME 下都没法使用(见 issue)。
所以稍稍改一下:

1
2
3
4
5
docker run \
--publish 7080:7080 --rm \
--volume /data/sourcegraph/config:/etc/sourcegraph \
--volume /data/sourcegraph/data:/var/opt/sourcegraph \
sourcegraph/server:2.5.17

然后登陆 http://:7080, 进入 Admin -> Configuration, 开始配置

注意,默认的 maxReposToSearch 太小,我把这改成200。

其次,这里有很多方式添加搜索的项目,可以输入 Github token 来检索你自己的仓库(自己的破代码有什么好搜索的),也可以添加如图第三方代码。我们这里选 “Add other reposity”,”repos.list” 会添加一个空白的 url, path 让你填写,然后会提示重启server, server 会自己 clone 代码,indexing。

批量添加代码库

这里我挑选的列表是 rsc/corpus —— Russ Cox 收集的 Golang 项目列表,能入 Russ 大佬法眼的代码,质量是有保证的。

仔细观察,Russ 是建了一个 bot,添加选好的 github 项目到 corpus 里。所以 commit message 很规范:

我们只要提取 commit message 中的项目地址,转换成 sourcegraph 配置需要的 url 和 path,就行啦~

这里用 Github API 得到 commit 信息,jq(方便好用的命令行 json 工具) 来过滤出 message。

1
curl https://api.github.com/repos/rsc/corpus/commits\?per_page\=130 |jq '.[] | {message: .commit.message}' | grep addproject |  grep -o 'github.com/\w\+/\w\+' > repos.txt

biu, 就得到项目列表了(截止写文章时候,86个):

然后就是列表转配置,简单的几行 Golang 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
func main() {
patt := `
{
"url": "https://github.com/%s.git",
"path": "%s"
},
`
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
path := strings.TrimPrefix(scanner.Text(), "github.com/")
fmt.Printf(patt, path, path)
}

if scanner.Err() != nil {
// handle error.
}
}

编译成 converter, cat repos.txt | ./converter | pbcopy, 复制到 sourcegraph 配置里(别忘了删掉配置json最后多出来的逗号)。

完成!项目需要 clone 一会,就会显示在 explore 里了:

也可以用来搜索想要的代码片段了。

小练习:用 Github API 添加自己标记过星的项目。

PS: 这样哐哐猛造会 git clone 一大堆代码,很快 docker-machine 的空间就造光了,记得调大一点。/data 属于 tmpfs 区,是被加载到内存里的(见这里),所以要修改 --virtualbox-memory,默认1024M。 --virtualbox-disk-size 是用来存放 local image 的,也可以调大一点。

1
2
3
4
5
6
7
8
9
10
11
12
13
docker@default:~$ df -h # after docker-machine ssh
Filesystem Size Used Available Use% Mounted on
tmpfs 2.6G 206.6M 2.4G 8% /
tmpfs 1.5G 0 1.5G 0% /dev/shm
/dev/sda1 17.9G 44.7M 16.9G 0% /mnt/sda1
cgroup 1.5G 0 1.5G 0% /sys/fs/cgroup
Users 465.1G 327.2G 137.9G 70% /Users
/dev/sda1 17.9G 44.7M 16.9G 0% /mnt/sda1/var/lib/docker
/dev/sda1 17.9G 44.7M 16.9G 0% /mnt/sda1/var/lib/docker/plugins

$ docker-machine rm default
$ docker-machine create -d virtualbox --virtualbox-disk-size "20000" --virtualbox-memory "3072" default
# remember to eval new docker env