• 在Emacs中使用GNU Global


    背景

    在我平时用Emacs编写C代码时,经常需要进行代码的跳转,主要需求为函数定义的跳转,某个具体函数的调用查找,某个结构体的定义跳转以及结构体中具体某一项的跳转等,GNU Global就能完全满足我的这个需求,所以习惯了Emacs的人可以将Source Insight扔开了。

    GNU Global简介

    GNU Global全称为GNU Global source code tagging system,官方定义为GNU Global是一个可以跨越各种环境的代码标记系统,例如在Emacs,VI,Less Viewer,Bash Shell甚至在Web浏览器中使用。可以通过GNU Global查找局部变量,函数,宏,结构体,类并且方便的跳转到你想要的位置,在进行大型项目开发时,GNUL Global可以包含许多子目录,#ifdef语句和许多main函数,它有点向平时经常使用的ctags和etags,但是有和这两个tag工具比起来GNU Global有以下两点更为强大:
    • 和编辑器不具有强绑定关系,所以可以很方便的将其用于各种编辑环境,无论是Emacs的忠实使用者还是Vim的粉丝都可以尽情的使用它来进行代码跳转
    • 具有比较强大的查找定义和引用的能力,对于代码阅读来说这个能力已经足够了
    GNU Global具有强大的跨平台能力,无论是在Linux还是在BSD系统还是Windows都可以使用。GNU Global具有以下功能:
    • 内置6种语法分析程序(定义和引用)C,C++,Yacc,Java,PHP4和汇编
    • 通过Ctags的语法解析插件可以支持25中语言(定义和引用)Awk, Dos batch, COBOL, C, C++, C#, Erlang,Fortran, Java, JavaScript, Lisp, Lua, Pascal, Perl, PHP, Python, Ruby, Matlab, OCaml, Scheme, Tcl, TeX, Verilog, Vhdl and Vim
    • 在各种不同的编辑环境中能够以相同的方式工作,例如
      • Shell命令行
      • Bash Shell
      • Vi编辑器(Vim)
      • Less Viewer
      • Emacs编辑器(Emacs,Mule,XEmacs)
      • Web浏览器
      • Doxygen文档系统
    • 通过特殊的符号表快速查找局部变量
    • 不仅能够查找定义还可以查找引用
    • 允许重复的tags
    • 给出匹配的路径
    • 默认分层查找
    • 不仅仅实在代码级别查找,还可以在库中查找
    • 生成补全列表
    • 支持多种格式输出
    • 允许指定标记文件
    • 支持POSIX 1003.2正则表达式
    • 支持idutils作为外部搜索引擎
    • 生成的tag文件独立于各种体系结构
    • 支持随时更新tag文件
    • 支持新语言的语法解析插件
    • 支持自定义gtags.conf
    • 使用压缩格式来节省空间
    • 支持C/S环境(TRAMP)
    • 默认忽略可执行文件,隐藏文件和特殊文件
    • 内置cscope程序(gtags-cscope)
    • 内置grep命令(使用-g)
    • 能够很好的处理循环符号链

    GNU Global使用

    命令行下使用GLOBAL,在开始使用之前可以看一下FAQ
    $more /your/gtags/path/FAQ
    首先我们需要使用gtags命令来产生代码树的tag文件,例如当我想要浏览内核2.4
    的代码时,只需要执行以下命令
    $cd ~/code/kernel/
    $gtags -v
    执行完之后会发现,在kernel目录下产生了3个tag文件分别是GPATH,GRTAGS,GTAGS,
    GTAGS是定义的数据库,GRTAGS是引用的数据库,GPATH是路径的数据库。
     
    基本用法,加入下面的是我们的目录树
    /home/user/
     |
     |-ROOT/      <- the root of source tree (GTAGS,GRTAGS,...)
        |
        |- README       .....   +---------------+
        |                       |The function of|
        |                       +---------------+
        |- DIR1/
        |  |
        |  |- fileA.c   .....   +---------------+
        |  |                    |main(){        |
        |  |                    |       func1();|
        |  |                    |       func2();|
        |  |                    |}              |
        |  |                    +---------------+
        |  |
        |  |- fileB.c   .....   +---------------+
        |                       |func1(){ ... } |
        |                       +---------------+
        |- DIR2/
           |
           |- fileC.c   .....   +---------------+
                                |#ifdef X       |
                                |func2(){ i++; }|
                                |#else          |
                                |func2(){ i--; }|
                                |#endif         |
                                |func3(){       |
                                |       func1();|
                                |}              |
                                +---------------+
    此时我们在ROOT目录下执行gtags命令生成tag文件,可以使用global命令在代码中搜索
    相关函数,需要注意的是只能在生成TAG文件的目录及其子目录中搜索:
    $ cd /home/user/ROOT
    $ global func1
    DIR1/fileB.c            # func1() is defined in fileB.c
    $ cd DIR1
    $ global func1
    fileB.c                 # relative path from DIR1
    $ cd ../DIR2
    $ global func1
    ../DIR1/fileB.c         # relative path from DIR2
    使用global的-r选项获取相关引用:
    $ global -r func2
    ../DIR1/fileA.c         # func2() is referred from fileA.c
    global支持使用正则表达式来进行搜索:
    $ cd /home/user/ROOT
    $ global 'func[1-3]'
    DIR1/fileB.c            # func1, func2 and func3 are matched
    DIR2/fileC.c
    global使用-x选项来获取更多细节:
    $ global func2
    DIR2/fileC.c
    $ global -x func2
    func2              2 DIR2/fileC.c       func2(){ i++; }
    func2              4 DIR2/fileC.c       func2(){ i--; }
    global使用-a选项时可以获取绝对路径:
    $ global -a func1
    /home/user/ROOT/DIR1/fileB.c
    global使用-s选项可以搜索没有在GTAGS中定义的符号:
    $ global -xs X
    X                  1 DIR2/fileC.c #ifdef X
    global使用-g选项可以搜索指定的模式:
    $ global -xg '#ifdef'
    #ifdef             1 DIR2/fileC.c #ifdef X
    global的-O选项表明只在文本文件中搜索,-o在源文件和文本文件中搜索,
    -l选项只在当前目录搜索,使用-P选项可以搜索特定模式的路径;
     
    如果想在库中搜索相关符号,则需要在每一个GTAGSLIBPATH中执行gtags
    命令:
    $ pwd
    /develop/src/mh                 # this is a source project
    $ gtags
    $ ls G*TAGS
    GRTAGS  GTAGS
    $ global mhl
    uip/mhlsbr.c                    # mhl() is found
    $ global strlen                 # strlen() is not found
    $ (cd /usr/src/lib; gtags)      # library source
    $ (cd /usr/src/sys; gtags)      # kernel source
    $ export GTAGSLIBPATH=/usr/src/lib:/usr/src/sys
    $ global strlen
    ../../../usr/src/lib/libc/string/strlen.c  # found in library
    $ global access
    ../../../usr/src/sys/kern/vfs_syscalls.c   # found in kernel
    $ ln -s /usr/src/lib .
    $ ln -s /usr/src/sys .
    $ gtags
    $ global strlen
    lib/libc/string/strlen.c
    $ global access
    sys/kern/vfs_syscalls.c
    如果忘记了搜索的符号名,可以使用-c选项来补全:
    $ global -c kmem # maybe k..k.. kmem..
    kmem_alloc
    kmem_alloc_pageable
    kmem_alloc_wait
    kmem_free
    kmem_free_wakeup
    kmem_init
    kmem_malloc
    kmem_suballoc # This is what I need!
    $ global kmem_suballoc
    ../vm/vm_kern.c
     
    $ funcs()
    > {
    > local cur
    > cur=${COMP_WORDS[COMP_CWORD]}
    > COMPREPLY=(`global -c $cur`)
    > }
    $ complete -F funcs global
    $ global kmem_<TAB><TAB>
    kmem_alloc kmem_alloc_wait kmem_init
    kmem_alloc_nofault kmem_free kmem_malloc
    kmem_alloc_pageable kmem_free_wakeup kmem_suballoc
    $ global kmem_s<TAB>
    $ global kmem_suballoc
    ../vm/vm_kern.c

    GNU Global在Emacs中的使用

    • 安装配置Emacs
    $HOME/.emacs
    +------------------------------------------------------
    |(setq load-path (cons "/home/owner/global" load-path))
    |(autoload 'gtags-mode "gtags" "" t)
    (global-set-key (kbd "M-<f1>") 'gtags-find-file)
    
    (global-set-key (kbd "M-<f2>") 'gtags-find-tag)
    
    (global-set-key (kbd "M-<f3>") 'gtags-find-rtag)
    
    (global-set-key (kbd "M-<f4>") 'gtags-find-symbol)
    
    (global-set-key (kbd "M-<f5>") 'gtags-find-with-grep)
    • 安装好之后在emacs中可以通过M-x使用如下命令
    在浏览器中显示当前屏幕
    跳转到输入的文件处
    通过grep命令搜索
    在tag文件中搜索引用
    在tag文件中搜索符号
    在tag文件中搜索定义
    从当前表达式获得tag名并跳转
    以当前位置作为tag跳转
    在另一个窗口中打开tag跳转
    搜索文件并查询

    tag名字补全
    开启gtags mode
    显示当前文件的tag
    从栈中移动到上一个点
    从tag列表中选择一个tag
    选择一个tag
    通过某个事件选择tag
    在其他window中选择tag
    访问tag文件根目录
    gtags-display-browser 
    gtags-find-file
    gtags-find-pattern 
    gtags-find-rtag
    gtags-find-symbol
    gtags-find-tag
    gtags-find-tag-by-event 
    gtags-find-tag-from-here
    gtags-find-tag-other-window 
    gtags-find-with-grep
    gtags-find-with-idutils 
    gtags-make-complete-list
    gtags-mode 
    gtags-parse-file
    gtags-pop-stack 
    gtags-select-mode
    gtags-select-tag 
    gtags-select-tag-by-event
    gtags-select-tag-other-window 
    gtags-visit-rootdir
    ------------------------------- 问道,修仙 -------------------------------
  • 相关阅读:
    基于pandas索引的数据查找、排序和去重小结
    python中的变量引用小结
    python中日志logging模块和异常捕获traceback模块的使用
    undefined和not defined
    spring 整合dubbo session中调用用户转换异常 classcastEcxeption
    iframe占满整个屏幕
    freemarker获取url中参数
    H5的新增标签
    Redis
    类加载过程
  • 原文地址:https://www.cnblogs.com/elvalad/p/4069656.html
Copyright © 2020-2023  润新知