RTFSC 是程序员打怪升级路上避不开的功课,那营造一个舒适的环境来提升上课的体验就很有必要了。
比如阅读 AOSP 这种大型源码,用什么姿势来阅读才能丝般顺滑,让 F**king Source Code 也变得不那么可恶呢?
阅读源码的工具我尝试过以下几类:
如果你还在寻觅适合你自己的解决方案,大可以花一点时间将以上几种都尝试一遍,哪个称手用哪个,也可以像我一样,针对不同的项目使用不同的工具。想直观了解 OpenGrok 的同学可以直接先看看一些使用 OpenGrok 的在线源码查看网站,看看它能否满足你的需求,其中的一些列在 OpenGrok installations。
译自官方 Wiki。
OpenGrok 提供如下特性:
path:Makefile defs:target
*
表示多个字符,?
表示单个字符
按惯例先上图吧,万一你一眼就发现不是你的菜呢(截图来自官网)。
搜索功能和源码树:
如下以 Windows 下为例,Mac OS X 与 Linux 下与此类似,很多步骤能使用 brew 或者 apt-get 会更方便。
-P
表示为 source root 目录下的每个一级子目录生成一个工程。
-S
表示搜索并添加 “external” source repositories。
-v
表示打印操作的进度信息。
-s
表示指定 source root。
-d
表示指定 data root。
-W
表示指定将配置写到该文件。
还有更多配置选项可以使用 java -jar /path/to/opengrok.jar
查看。
比如我使用的完整命令行:
java -jar D:\Programs\opengrok-0.13-rc4\lib\opengrok.jar -P -S -v -s D:\Programs\opengrok-0.13-rc4\projects -d D:\Programs\opengrok-0.13-rc4\data -W D:\Programs\opengrok-0.13-rc4\data\configuration.xml
每次需要建立或更新索引的时候敲这么长一个命令当然很不爽,使用 doskey 或者 Cmder 里的 alias 命令将其 alias 为 opengrok-index 命令会省力不少,再不济把这命令存成个 bat 文件也行啊。
为大型源码建立索引可能需要漫长的时间,这时候可以去干点别的事了。
我曾经为如何在 OpenGrok 里配置多项目苦恼了好久——一开始我是把 Android 源码的根目录当作 source root 的,可想而知 OpenGrok 把 Android 分成了好多个子项目,而这时我也没法再添加新的工程了。
后来才发现建一个专用的 source root,然后把各种项目源码根目录软链接过来,让 OpenGrok 为 source root 下的每个 symbol 一级子目录建立一个项目才是正确的使用方法。
Windows 下建立软链接的方法是使用 mklink /J android D:\sources\android_5.1
,Mac OS X 和 Linux 下可以使用 ln -s /path/to/source project_name
。
在 Vim 里使用
没错,还有人做了支持在 Vim 里使用 OpenGrok 的插件,如果你是 Vim 控+折腾狂魔,可以一试,这里仅给出插件地址:
反正像我这种智商是折腾不动了,就安心在浏览器里用了。
在源码里做笔记
配合 Chrome 插件 Diigo,还能给源码加标签,写注释等等。
参考:https://www.zhihu.com/question/33505693/answer/132224974
There was an error!
CONFIGURATION parameter has not been configured in web.xml! Please configure your webapp.
Unable to determine source root path. Missing configuration?
java.io.FileNotFoundException: Unable to determine source root path. Missing configuration?
at org.opensolaris.opengrok.web.PageConfig.checkSourceRootExistence(PageConfig.java:1562)
at org.apache.jsp.index_jsp._jspService(index_jsp.java:222)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:443)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:385)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:329)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.opensolaris.opengrok.web.StatisticsFilter.doFilter(StatisticsFilter.java:55)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.opensolaris.opengrok.web.AuthorizationFilter.doFilter(AuthorizationFilter.java:83)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
这一般是由于更新或切换了 OpenGrok 版本,但却没有将 tomcat 的 webapps 目录下的 source 文件夹替换为对应版本。
古人教会了我们工欲善其事,必先利其器的智慧,但我们也不能沉迷和徘徊于各种利器之间,选择一样自己感觉最称手的工具,把它用熟练,少再在这上面花时间折腾,毕竟把有限的生命投入到无限的 RTFSC 才是正道不是么。