Vim技能修炼教程(10)

来源:互联网 发布:福州海牛网络压力大吗 编辑:程序博客网 时间:2024/06/07 21:30

程序员功能

前面我们用了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重新生成索引
:!ctags -R

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

  • 设置要查找的tags文件的路径
    先可以通过:set tags?来查查当前值
:set tags?

默认值为:

tags=./tags,tags

如果想要设置的话,可以用:set tags=tags文件名的方式来设置。
我们因为是在源码根目录下刚生成,应该是能找到的,我们就直接进入下一步。

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

kernel init

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

mp init

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

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

:only | :vsplit

如果有重名怎么办?

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

arch_mp_send_api

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

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

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

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

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

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

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

  # pri kind tag               file  1 F   m    init              kernel/include/app.h               struct:app_descriptor               app_init  init;  2 F   m    init              kernel/lib/unittest/include/unittest.h               struct:unitest_testcase_registration               unitest_testcase_init_fn_t      init;  3 F   m    init              system/ulib/ddk/include/ddk/driver.h               struct:mx_driver_ops               mx_status_t (*init)(void** out_ctx);  4 F   m    init              system/ulib/mxio/private.h               struct:__anon440               bool init;  5 F   f    init              third_party/uapp/dash/src/init.c               init() {  6 F   v    init              third_party/uapp/dash/src/mkinit.c               char init[] = "\  7 F   m    init              third_party/ulib/cryptolib/include/lib/crypto/cryptolib.h               struct:clHASH_vtab               void (* const init)(struct clHASH_CTX*);  8 F   f    init              third_party/ulib/qrcodegen/qrcode.cpp               class:qrcodegen::ReedSolomonGenerator               Error ReedSolomonGenerator::init(size_t degree) {  9 FS  f    init              system/core/acpisvc/main.c               static ACPI_STATUS init(void) { 10 FS  f    init              system/uapp/gpt/gpt.c               static gpt_device_t* init(const char* dev, bool warn, int* out_fd) { 11 FS  f    init              third_party/uapp/dash/src/mksyntax.c               init(void) 12     f    Init              kernel/arch/x86/hypervisor.cpp               class:PerCpu               status_t PerCpu::Init(const VmxInfo& info) { 13     f    Init              kernel/arch/x86/hypervisor.cpp               class:VmcsPerCpu               status_t VmcsPerCpu::Init(const VmxInfo& vmx_info) { 14     f    Init              kernel/dev/pcie/pcie_bridge.cpp               class:PcieBridge               status_t PcieBridge::Init(PcieUpstreamNode& upstream) { 15     f    Init              kernel/dev/pcie/pcie_device.cpp               class:PcieDevice               status_t PcieDevice::Init(PcieUpstreamNode& upstream) { 16     f    Init              kernel/kernel/vm/vm_aspace.cpp               class:VmAspace               status_t VmAspace::Init() { 17     f    Init              kernel/lib/magenta/io_mapping_dispatcher.cpp               class:IoMappingDispatcher               status_t IoMappingDispatcher::Init(const char* dbg_name, 18     f    Init              kernel/lib/mxtl/arena.cpp               class:mxtl::Arena               status_t Arena::Init(const char* name, size_t ob_size, size_t count) { 19     f    Init              kernel/lib/mxtl/arena.cpp               class:mxtl::Arena::Pool               void Arena::Pool::Init(const char* name, mxtl::RefPtr<VmMapping> mapping, 20     f    Init              system/dev/bus/virtio/block.cpp               class:virtio::BlockDevice               mx_status_t BlockDevice::Init() { 21     f    Init              system/dev/bus/virtio/gpu.cpp               class:virtio::GpuDevice               mx_status_t GpuDevice::Init() { 22     f    Init              system/dev/bus/virtio/ring.cpp               class:virtio::Ring               mx_status_t Ring::Init(uint16_t index, uint16_t count) {-- More --

小结

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