程序员功能

前面我们用了5讲的篇幅来讲基本编辑的基本功:第4讲是基本操作,第5讲是操作符,第6讲行编辑ex命令,第7讲可视模式,第8讲多窗口,第9讲缓冲区和标签页。

从这一讲开始,我们从通用功能向程序员常用功能挺进。首先我们从浏览代码最常用的跳转功能开始。

代码跳转

代码跳转,需要传说中的Exuberant Ctags工具,地址在:http://ctags.sourceforge.net/

当然大家根据系统不同各显神通吧。比如我是macOS,就通过Homebrew来安装了。大家手头有什么”apt install”,”dnf install”,”zypper install”之类的独门兵器就往上用吧。

目前Exuberant ctags支持41种编程语言,具体列表在:http://ctags.sourceforge.net/languages.html

如果要支持这41种语言之外的,请看扩展指南:http://ctags.sourceforge.net/EXTENDING.html

将来我们用到了再说,目前常用的语言要么是ctags已经支持了,要么是语言官方有支持了。基本上常用语言对于vim和emacs的支持还是比较全的。

代码跳转速成教程

  • 首先我们用vim打开源代码的根目录。比如我打开Google的Magenta内核的源代码根目录

  • 运行ctags重新生成索引
  1. :!ctags -R

源代码有较大变化后,就需要重新生成索引,否则索引就匹配不上了。

  • 设置要查找的tags文件的路径

    先可以通过:set tags?来查查当前值
  1. :set tags?

默认值为:

  1. tags=./tags,tags

如果想要设置的话,可以用:set tags=tags文件名的方式来设置。

我们因为是在源码根目录下刚生成,应该是能找到的,我们就直接进入下一步。

  • 为了对照方便。我们可以充分利用之前学习的多窗口功能。比如用:vsplit竖切成两半,对照着看。

  • Ctrl-] 跳转。比如我想查看mp_init()是实现啥的,光标定位过去之后,点击”Ctrl-]”,就跳转到mp_init实现的部分:

  • 如果要退回刚才的位置,功能键是Ctrl-t

  • 如果想让左右屏的内容重新同步一下,把左边关了再重切就是了

  1. :only | :vsplit

如果有重名怎么办?

对于没有重名的,上面的方式都工作得很好。但是很不幸,有时候,函数的定义是有重名的。这时候我们不方便简单地用Ctrl-]了,我们有多选的g+Ctrl-]. 如图的例子:arch_mp_send_api函数在arm64和x86上各有自己的实现,我们用g+Ctrl-]就会出现下面的选择列表:

不是非要跳到代码上才能查

如果跳到代码上查比较慢的话,我们也可以通过ex命令直接搜。

  • :tag {关键字} - 相当于Ctrl-]
  • :tjump {关键字} - 相当于g+Ctrl-]

除了全字匹配,:tag和:tjump命令还支持正则表达式搜索。

比如,用:tjump init,全字匹配能得到的结果如下:

  1. # pri kind tag file
  2. 1 F m init kernel/include/app.h
  3. struct:app_descriptor
  4. app_init init;
  5. 2 F m init kernel/lib/unittest/include/unittest.h
  6. struct:unitest_testcase_registration
  7. unitest_testcase_init_fn_t init;
  8. 3 F m init system/ulib/ddk/include/ddk/driver.h
  9. struct:mx_driver_ops
  10. mx_status_t (*init)(void** out_ctx);
  11. 4 F m init system/ulib/mxio/private.h
  12. struct:__anon440
  13. bool init;
  14. 5 F f init third_party/uapp/dash/src/init.c
  15. init() {
  16. 6 F v init third_party/uapp/dash/src/mkinit.c
  17. char init[] = "\
  18. 7 F m init third_party/ulib/cryptolib/include/lib/crypto/cryptolib.h
  19. struct:clHASH_vtab
  20. void (* const init)(struct clHASH_CTX*);
  21. 8 F f init third_party/ulib/qrcodegen/qrcode.cpp
  22. class:qrcodegen::ReedSolomonGenerator
  23. Error ReedSolomonGenerator::init(size_t degree) {
  24. 9 FS f init system/core/acpisvc/main.c
  25. static ACPI_STATUS init(void) {
  26. 10 FS f init system/uapp/gpt/gpt.c
  27. static gpt_device_t* init(const char* dev, bool warn, int* out_fd) {
  28. 11 FS f init third_party/uapp/dash/src/mksyntax.c
  29. init(void)

我们换成:tjump /init,则包含init所有的内容都能搜出来,要显示好多屏:

  1. # pri kind tag file
  2. 1 F m init kernel/include/app.h
  3. struct:app_descriptor
  4. app_init init;
  5. 2 F m init kernel/lib/unittest/include/unittest.h
  6. struct:unitest_testcase_registration
  7. unitest_testcase_init_fn_t init;
  8. 3 F m init system/ulib/ddk/include/ddk/driver.h
  9. struct:mx_driver_ops
  10. mx_status_t (*init)(void** out_ctx);
  11. 4 F m init system/ulib/mxio/private.h
  12. struct:__anon440
  13. bool init;
  14. 5 F f init third_party/uapp/dash/src/init.c
  15. init() {
  16. 6 F v init third_party/uapp/dash/src/mkinit.c
  17. char init[] = "\
  18. 7 F m init third_party/ulib/cryptolib/include/lib/crypto/cryptolib.h
  19. struct:clHASH_vtab
  20. void (* const init)(struct clHASH_CTX*);
  21. 8 F f init third_party/ulib/qrcodegen/qrcode.cpp
  22. class:qrcodegen::ReedSolomonGenerator
  23. Error ReedSolomonGenerator::init(size_t degree) {
  24. 9 FS f init system/core/acpisvc/main.c
  25. static ACPI_STATUS init(void) {
  26. 10 FS f init system/uapp/gpt/gpt.c
  27. static gpt_device_t* init(const char* dev, bool warn, int* out_fd) {
  28. 11 FS f init third_party/uapp/dash/src/mksyntax.c
  29. init(void)
  30. 12 f Init kernel/arch/x86/hypervisor.cpp
  31. class:PerCpu
  32. status_t PerCpu::Init(const VmxInfo& info) {
  33. 13 f Init kernel/arch/x86/hypervisor.cpp
  34. class:VmcsPerCpu
  35. status_t VmcsPerCpu::Init(const VmxInfo& vmx_info) {
  36. 14 f Init kernel/dev/pcie/pcie_bridge.cpp
  37. class:PcieBridge
  38. status_t PcieBridge::Init(PcieUpstreamNode& upstream) {
  39. 15 f Init kernel/dev/pcie/pcie_device.cpp
  40. class:PcieDevice
  41. status_t PcieDevice::Init(PcieUpstreamNode& upstream) {
  42. 16 f Init kernel/kernel/vm/vm_aspace.cpp
  43. class:VmAspace
  44. status_t VmAspace::Init() {
  45. 17 f Init kernel/lib/magenta/io_mapping_dispatcher.cpp
  46. class:IoMappingDispatcher
  47. status_t IoMappingDispatcher::Init(const char* dbg_name,
  48. 18 f Init kernel/lib/mxtl/arena.cpp
  49. class:mxtl::Arena
  50. status_t Arena::Init(const char* name, size_t ob_size, size_t count) {
  51. 19 f Init kernel/lib/mxtl/arena.cpp
  52. class:mxtl::Arena::Pool
  53. void Arena::Pool::Init(const char* name, mxtl::RefPtr<VmMapping> mapping,
  54. 20 f Init system/dev/bus/virtio/block.cpp
  55. class:virtio::BlockDevice
  56. mx_status_t BlockDevice::Init() {
  57. 21 f Init system/dev/bus/virtio/gpu.cpp
  58. class:virtio::GpuDevice
  59. mx_status_t GpuDevice::Init() {
  60. 22 f Init system/dev/bus/virtio/ring.cpp
  61. class:virtio::Ring
  62. mx_status_t Ring::Init(uint16_t index, uint16_t count) {
  63. -- More --

小结

  • !ctags -R 生成索引
  • :set tags=路径 设定ctags生成的tags文件的路径
  • Ctrl-] 跳转到唯一的或者是第一个匹配的代码
  • g+Ctrl-] 提供多选列表
  • :tag {关键字} : ex命令版的Ctrl-]
  • :tjump {关键字}: ex命令版的g+Ctrl-]
  • :tag或:tjump /{关键字} :正则表达式搜索

Vim技能修炼教程(10) - 代码跳转的更多相关文章

  1. Vim技能修炼教程(11) - 代码折叠

    上一讲我们是程序员篇的第一讲,关于代码跳转.代码跳转是一个付出很少收获很大的功能.这一节我们开始一个收获很多,但是付出也相对多一点功能:代码折叠. 代码折叠 折叠的类型 折叠有下面几种类型: * Ma ...

  2. Vim技能修炼教程(2) - 语法高亮速成

    语法高亮速成 我们继续在人间修行Vim技能之旅.上一次我们学习了如何通过vundle安装插件,这次我们迅速向写插件的方向挺进. 我们先学习一个最简单的语法高亮插件的写法. 语法高亮基本上是由三部分组成 ...

  3. Vim技能修炼教程(13) - 变量

    VimScript变量 上节我们介绍了Python和Ruby来编写Vim插件的方式. 不过,Python和Ruby并不是所有的Vim都支持的功能,如果以最小依赖的原则来说,还是原汁原味的Vimscri ...

  4. Vim技能修炼教程(8) - 多窗口

    多窗口 如果一个vim只能开一个窗口,那肯定是有点low.尤其是写代码的时候,打开多个文件是经常的需求. 速成教程 横着切成两个 :split 文件名 上下切换窗口 Ctrl-W加上上下键,可以实现上 ...

  5. Vim技能修炼教程(7) - 可视模式

    可视模式 可视模式是与正常模式.插入模式一起并列的模式.它的作用就像图形化编辑器下用鼠标来选择一个块. 在vim下,使用正常模式和ex命令,连搜带跳行的,未必就比用鼠标慢. 我们先做一个例子找找感觉, ...

  6. Vim技能修炼教程(4) - 基本功

    基本功 前面我们学会了插件管理器和如何实现语法高亮,相信大家已经从中体会到了vim插件的强大功能.现在,是时候回来补一补基本功了. Vi有三种主要模式,正常模式,插入模式和可视化模式.正常我们推荐的方 ...

  7. Vim技能修炼教程(3) - 语法高亮进阶

    语法高亮进阶 首先我们复习一下上节学到的三个命令: * syntax match用于定义正则表达式和规则的对应 * highlight default定义配色方案 * highlight link将正 ...

  8. Vim技能修炼教程(1) - 使用vundle管理插件

    世界上有两个伟大的编辑器:一个是emacs,一个是vi.它们从诞生以来,一直在Unix/Linux世界得到最广泛的支持. 尽管过了几十年,在Windows平台上和跨平台上有层出不穷的后起之秀不断挑战它 ...

  9. Vim技能修炼教程(16) - 浮点数计算函数

    浮点数计算函数 这一节的所有函数,只有在vim编译时支持了+float时才有效. 三角函数 sin() : sine正弦函数 cos() : cosine余弦函数 tan() : tangent正切函 ...

随机推荐

  1. python3执行js之pyexecjs

    执行js的三种方法:1.阅读js代码,将之转成python2.找到js代码,用python第三方库执行相关代码 python2-pyv8 python3-pyexecjs3.用selenium驱动浏览 ...

  2. Swift开发之泛型实例

    一.Swift泛型 泛型能够让开发者编写自定义需求已经任意类型的灵活可用的的函数和类型.能够让我们避免重复的代码.用一种清晰和抽象的方式来表达代码的意图. func swapTwoStrings(_ ...

  3. MysQL使用一与Python交互

    与python交互 在熟练使用sql语句的基础上,开始使用python语言提供的模块与mysql进行交互 这是我们在工作中大事要做的事 先学会sql是基础,一定要熟练编写sql语句 安装引入模块 安装 ...

  4. testng基础知识:注解的执行顺序

    1. 单类,无继承父子关系 code: public class basicTest { @BeforeSuite(alwaysRun = true) public void beforeSuite_ ...

  5. BZOJ 2761: [JLOI2011]不重复数字 hash哈希

    题目就不贴了 点我看题 题意:这题题意很简明,就是给一个序列,把序列里相同的删掉,然后输出,按原数列顺序. 思路:这题之前QZZ和ZN大神犇叫我去做,辣时还不会hash,就留着了.最近某夏令营学会了h ...

  6. 百度云如何免费扩容至2055G?

    百度云如何免费扩容至2055G? 上篇说到整一个新的百度账号,那么5G的百度云内存肯定满足不了我们收集癖的需求.那么就来了解一下怎么扩容吧. 主要是在手机端实现的 用这个新的百度账号在手机APP上登录 ...

  7. quickSort - 编程细节

    quicksort 快速排序 有几个细节比较重要 今天听到一个清华的大佬的话,他曾经是NOI, 在大一就得到了我梦寐以求的ACM金奖,他这样说, 他们在打NOI的时候,每天要求做10道题, 连续做60 ...

  8. python 匹配中文和英文

    在处理文本时经常会匹配中文名或者英文word,python中可以在utf-8编码下方便的进行处理. 中文unicode编码范围[\u4e00-\u9fa5] 英文字符编码范围[a-zA-Z] 此时匹配 ...

  9. 【Python】简单实现爬取小说《天龙八部》,并在页面本地访问

    背景 很多人说学习爬虫是提升自己的一个非常好的方法,所以有了第一次使用爬虫,水平有限,依葫芦画瓢,主要作为学习的记录. 思路 使用python的requests模块获取页面信息 通过re模块(正则表达 ...

  10. 我的Android学习路线(二)

    这两天的主要工作: 优化了一下布局界面,原本使用的是相对布局,直观省力,但是考虑了一下还是使用更加主流的线性布局. 完善了一下计算器的功能,比如加入小数运算. 使用线性布局的思路可以用下面的伪代码表示 ...