热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

emacs使用之cedet

1.利用semantic-ia-complete-symbol可以进行参数的跳转。cedet安装:在准备写Emacs才是世界上最强大的IDE系列文章时,

1. 利用  semantic-ia-complete-symbol 可以进行参数的跳转。

cedet 安装:

在准备写Emacs才是世界上最强大的IDE系列文章时,由于以前用的是cedet1.0pre6版本,速度比较慢,而且精确度也不高,所以就没有打算写它,昨天晚上在水木群里听一位网友介绍说cedet的cvs版本速度很快,而且精确度不错,所以晚上就down下cvs的版本试了一把,越试越感觉不错,就有了写cedet的想法。从头开始,先说安装吧。

cedet的安装挺简单,只要仔细看好cedet的说明就可以了,不过我昨天晚上没仔细看好说明,安装的时候碰到一个问题,所以我还是准备写一下安装过程。(如果你用apt-get, 或者emerge安装,首先要看下它们的版本,1.0pre6和其之前的版本都不要安装,语法分析会很慢的。)

首先下载cedet的cvs版本:

?View Code BASH


1
2

cvs -d:pserver:anonymous@cedet.cvs.sourceforge.net:/cvsroot/cedet login
cvs
-z3 -d:pserver:anonymous@cedet.cvs.sourceforge.net:/cvsroot/cedet co -P cedet


然后编译:

  • linux下:

    ?View Code BASH

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    cd cedet
    touch `find . -name Makefile` (cvs版本不需要这个)
    a) make

    b) make EMACS&#61;<your favorite emacs>

    c) make MAKEINFO&#61;/usr/local/bin/makeinfo

    d) make MAKEINFO&#61;echo
    如果编译过程中发生类似找不到loaddef文件&#xff0c;custom-autoload以及其他奇怪的错误&#xff0c;执行&#xff1a;
    a) make clean-autoloads
    b) make clean-all
    然后再重新编译。编译错误还有可能是make版本引起的&#xff0c;请使用GNU make&#xff0c;或者使用windows下的安装方法。

  • windows下(当然linux下这样也可以)&#xff1a;

    ?View Code BASH

    1
    2
    3
    4
    5
    6

    emacs -q --no-site-file -l cedet-build.el -f cedet-build

    在emacs中打开cedet-build.el文件&#xff0c;然后
    M-x eval-buffer
    M-x cedet-build-in-default-emacs
    编译过程中如果发生超过emacs堆栈大小的错误&#xff0c;退出emacs再重新编译即可。

说完安装&#xff0c;再说一下简单的使用&#xff0c;把下面的代码贴到你的.emacs里面&#xff1a;

?View Code LISP


1
2
3
4
5
6
7
8
9
10
11
12

(add-to-list &#39;load-path "path-of-cedet/common")
(require &#39;cedet)
(require &#39;semantic-ia);; Enable EDE (Project Management) features
(global-ede-mode 1)(semantic-load-enable-excessive-code-helpers)
(semantic-load-enable-semantic-debugging-helpers);; Enable SRecode (Template management) minor-mode.
(global-srecode-minor-mode 1)


现在开始享受cedet吧。


  • 1 前言
  • 2 简介
    • 2.1 EDE
    • 2.2 Semantic
    • 2.3 SRecode
    • 2.4 Cogre
    • 2.5 Speedbar
    • 2.6 EIEIO
  • 3 安装
  • 4 semantic配置
    • 4.1 功能介绍
      • 4.1.1 semantic-load-enable-minimum-features
      • 4.1.2 semantic-load-enable-code-helpers
      • 4.1.3 semantic-load-enable-gaudy-code-helpers
      • 4.1.4 semantic-load-enable-excessive-code-helpers
      • 4.1.5 semantic-load-enable-semantic-debugging-helpers
    • 4.2 基本配置
    • 4.3 代码跳转
    • 4.4 代码补全
  • 5 EDE配置
  • 6 其它
    • 6.1 可视化书签
    • 6.2 pluse
    • 6.3 h/cpp切换
    • 6.4 代码折叠
      • 6.4.1 semantic-tag-folding
      • 6.4.2 senator-fold-tag
  • 7 Todo


1 前言

网上关于如何用emacs&#43;cedet做C&#43;&#43; IDE的文章已经很多了&#xff0c;可是大都只列出了配置文件和效果&#xff0c;没有讲清楚具体的配置过程&#xff1b;一篇讲得比较具体的文章(http://alexott.net/en/writings/emacs-devenv/EmacsCedet.html ,这篇文章是被cedet官方推荐的)还是英文的。刚接触cedet的用户经常照抄了别人的配置却发现不能补全&#xff0c;而且配置文件是别人的想改还无法下手。本文中我尽量详细解释各个语句的作用&#xff0c;希望能给初次接触的人提供点帮助。

cedet于2010年2月26日发布了1.0pre7&#xff0c;强烈建议以前用过cedet觉得速度慢而放弃的同学试试1.0pre7&#xff0c;这个版本速度比以前有很大很大提高。



2 简介

cedet是一堆完全用elisp实现的emacs工具的集合&#xff0c;主要有&#xff1a;

2.1 EDE

用来管理项目&#xff0c;它可以把emacs模拟得像一个IDE那样&#xff0c;把一堆文件作为一个project来管理。

2.2 Semantic

Semantic应该是cedet里用得最多的组件了&#xff0c;代码间跳转和自动补全这两大功能都是通过semantic来实现的。

2.3 SRecode

SRecode是一个模板系统&#xff0c;通过一些预定义的模板&#xff0c;可以很快地插入一段代码。个人觉得这个功能跟msf-abbrev和yasnippet的功能有些类似。

2.4 Cogre

全称叫”Connected Graph Editor”&#xff0c;主要和图形相关&#xff0c;比如可以用它来为C&#43;&#43;类生成UML图。

2.5 Speedbar

Speedbar可以单独创建一个frame&#xff0c;用于显示目录树&#xff0c;函数列表等等。这个组件已经包含在emacs官方发布包中。

2.6 EIEIO

EIEIO是一个底层库&#xff0c;它为elisp加入了OO支持。cedet的其它组件都依赖于EIEIO。



3 安装

安装就不多说了&#xff0c;这儿详细说明了如何下载安装。

要注意的是通过cvs下载必须要编译后才能用&#xff0c;而官方发布后的包可以直接解压不编译也是能用。

安装完后首先当然要load它(确保安装的路径已经在load-path中了)&#xff1a;

?View Code LISP

(require &#39;cedet)



4 semantic配置

先介绍一下最常用的semantic。

4.1 功能介绍

一般装插件的思路&#xff0c;都是先load然后enable某个minor mode。cedet基本上也遵循这个规则&#xff0c;不过有点区别是semantic定义了很多个mode&#xff0c;要是挨个去enable&#xff0c;用户可能就要骂娘了&#xff0c;所以cedet的作者Eric定义了几个方便使用的函数&#xff0c;这些函数会自动帮你enable某些minor mode&#xff0c;大概有这么几个&#xff1a;

?View Code LISP

1
2
3
4
5

(semantic-load-enable-minimum-features)
(semantic-load-enable-code-helpers)
(semantic-load-enable-guady-code-helpers)
(semantic-load-enable-excessive-code-helpers)
(semantic-load-enable-semantic-debugging-helpers)

简单介绍一下各个函数的功能&#xff1a;

4.1.1 semantic-load-enable-minimum-features

这个函数开启了最基本的三个特性&#xff1a;

  • semantic-idle-scheduler-mode 

    enable这个mode让cedet在emacs空闲的时候自动分析buffer内容&#xff0c;比如正在编辑的buffer内容改变后。这个mode一般应该是需要enable的&#xff0c;如果没有enable这个mode&#xff0c;那只有手工触发才会让cedet重新分析。

  • semanticdb-minor-mode 

    semanticdb是semantic用来保存分析后的内容的&#xff0c;所以也是应该enable的。

  • semanticdb-load-ebrowse-caches 

    这个feature我不是很确定&#xff0c;大概的意思好像是semantic可以利用ebrowse的结果。这个feature大概就是把ebrowse生成的文件load给semantic使用。(要是谁了解这个feature具体意义请告诉我下)

4.1.2 semantic-load-enable-code-helpers

这个函数除enable semantic-load-enable-minimum-features外&#xff0c;还包括&#xff1a;

  • imenu 

    这个feature可以让imenu显示semantic分析出的类&#xff0c;函数等tags。如图&#xff1a;

    imenu显示semantic分析出的类

  • semantic-idle-summary-mode 

    打开这个mode之后&#xff0c;光标停留在一个类/函数等tag上时&#xff0c;会在minibuffer显示出这个函数原型&#xff0c;如图&#xff1a;

    用ssemantic在minibuffer显示函数原型

  • senator-minor-mode 

    senator开启之后&#xff0c;会在emacs上增加一个senator的菜单&#xff0c;可以通过菜单在当前文件的各个tag之间前后移动&#xff0c;跳转&#xff1b;还可以在里面方便地打开/关闭某个feature&#xff1b;还有另外一些实用的功能&#xff0c;看看菜单大概就能明白&#xff1a;

    senator菜单

  • semantic-mru-bookmark-mode 

    cedet有tag跳转的功能&#xff0c;但是经常跳转完后还需要跳回刚才的位置&#xff0c;这时候就需要mru-bookmark-mode了。打开这个mode之后&#xff0c;每次跳转semantic都会把位置当作书签一样记录下来&#xff0c;以后可以通过M-x semantic-mrub-switch-tags&#xff08;绑定到按键C-x B上&#xff09;来选择跳回以前的任意一个位置。

4.1.3 semantic-load-enable-gaudy-code-helpers

这个函数除enable semantic-load-enable-code-helpers之外&#xff0c;还包括&#xff1a;

  • semantic-stickyfunc-mode 

    这个mode会根据光标位置把当前函数名显示在buffer顶上&#xff0c;如图&#xff1a;

    在head-line上显示函数名

    这个mode我觉得用处不大&#xff0c;因为基本上可以用which-func-mode代替。而且我习惯打开tabbar-mode&#xff0c;这个mode会覆盖tabbar-mode&#xff0c;所以我是不打开它的。

  • semantic-decoration-mode 

    打开这个mode后&#xff0c;semantic会在类/函数等tag上方加一条蓝色的线&#xff0c;源文件很大的时候用它可以提示出哪些是类和函数的头。如图&#xff1a;

    semantic标记函数头

  • semantic-idle-completions-mode 

    这个mode打开后&#xff0c;光标在某处停留一段时间后&#xff0c;semantic会自动提示此处可以补全的内容。比如下面这段代码&#xff1a;

    semantic自动补全当前光标内容

    如果把光标停留在”this->”的后面&#xff0c;稍隔一会会提示&#xff1a;

    semantic自动补全当前光标内容

    如果提示的函数不是需要的&#xff0c;按TAB键可以在各个可能的函数之间循环&#xff0c;按回车就可以确定了。

4.1.4 semantic-load-enable-excessive-code-helpers

这个函数除enable semantic-load-enable-gaudy-code-helpers之外&#xff0c;还包括&#xff1a;

  • semantic-highlight-func-mode 

    打开这个mode的话&#xff0c;semantic会用灰的底色把光标所在函数名高亮显示&#xff0c;如下图中&#xff0c;函数Delete被高亮了&#xff0c;而LexicalCast没被高亮&#xff1a;

    semantic高亮当前函数

  • semantic-idle-tag-highlight-mode 

    用过XCode或eclipse的人应该会喜欢高亮光标处变量的功能&#xff1a;就是在函数内部&#xff0c;光标停留在一个变量上&#xff0c;整个函数内部用这个变量的地方都高亮了。在emacs里只要打开semantic-idle-tag-highlight-mode&#xff0c;光标在变量处停留一会&#xff0c;就会把相同的变量全都高亮&#xff0c;比如下图中的变量mAddr&#xff1a;

    semantic智能高亮当前符号

    semantic的这个tag-highlight虽然智能&#xff0c;可是我感觉它显示得太慢了&#xff0c;所以我是用另一个插件highlight-symbol来高亮的&#xff0c;这儿有它的介绍。

  • semantic-decoration-on-*-members 

    把private和protected的函数用颜色标识出来&#xff0c;如图&#xff1a;

    semantic用颜色区分方法的访问权限

  • which-func-mode 

    这个其实就是emacs自带的which-function-mode&#xff0c;把光标当前所在的函数名显示在mode-line上。

4.1.5 semantic-load-enable-semantic-debugging-helpers

这个函数会enable几个和调试semantic相关的特性&#xff1a;

  • semantic-highlight-edits-mode 

    打开这个mode后&#xff0c;emacs会把最近修改过的内容高亮出来&#xff0c;如下图中begin就是刚输入的&#xff0c;所以用灰底色高亮了&#xff1a;

    semantic高亮最近修改

    隔一段时间后高亮会自动取消&#xff0c;不会一直高亮着让整个buffer看起来混乱。

    其实emacs自带也有高亮修改内容的mode&#xff1a;highlight-changes-mode&#xff0c;它会用红色的字体高亮所有修改的内容&#xff0c;但是不会自动取消&#xff0c;所以修改多了整个buffer就会乱七八糟糕。用semantic这个就好多了。

  • semantic-show-unmatched-syntax-mode 

    这个mode会把semantic解析不了的内容用红色下划线标识出来&#xff0c;比如下面这个文件是从emacs源代码中来的&#xff1a;

    semantic用红色下划线标记不匹配的语法

  • semantic-show-parser-state-mode 

    打开这个mode&#xff0c;semantic会在modeline上显示出当前解析状态&#xff0c;这是关闭mode的样子&#xff1a;

    这是打开mode的样子&#xff1a;

    能看出modeline上文件名前的横线多了一条&#xff0c;其实倒数第二条就是用来显示当前semantic解析状态的&#xff1a;未解析时显示为”!”&#xff0c;正在解析时显示”&#64;”&#xff0c;解析完后显示”-”&#xff0c;如果buffer修改后未重新解析显示为”^”。

    semantic会在空闲时自动解析&#xff0c;另外可以打开senator-minor-mode&#xff0c;按[C-c , ,]或者在senator菜单中选[Force Tag Refresh]强制它马上解析。

4.2 基本配置

了解了上面这些feature&#xff0c;就可以根据需要配置了&#xff0c;为了使用semantic&#xff0c;至少需要开启semantic-load-enable-minimum-features定义的三个基础feature&#xff0c;其余的feature就可以根据自己的需要开启了。比如我的配置是&#xff1a;

?View Code LISP

1
2
3
4
5

;; (semantic-load-enable-minimum-features)
(semantic-load-enable-code-helpers)
;; (semantic-load-enable-guady-code-helpers)
;; (semantic-load-enable-excessive-code-helpers)

(semantic-load-enable-semantic-debugging-helpers)

因为imenu,idle-summary-mode,senator-mode,mru-bookmark-mode都是我需要的。特别是senator&#xff0c;有时候我会碰到semantic等很久也不自动解析文件的问题&#xff0c;这时候就需要在senator菜单里[Force Tag Refresh]一下了&#xff0c;并且senator还可以通过菜单方便地打开和关闭某些mode&#xff0c;用起来还是很方便的。

(semantic-load-enable-guady-code-helpers)和(semantic-load-enable-excessive-code-helpers)定义的那些feature&#xff0c;对我来说用处不大&#xff0c;而且我感觉打开的话还会让emacs反应变慢&#xff0c;所以我就不启用了。

(semantic-load-enable-semantic-debugging-helpers)的几个feature我都比较喜欢&#xff0c;所以我也启用了。

有了这些基本配置&#xff0c;在emacs打开C和C&#43;&#43;文件的时候&#xff0c;semantic就会自动解析文件。不过有个问题&#xff0c;一个cpp文件中肯定会include很多头文件&#xff0c;要想解析这个cpp的内容&#xff0c;头文件的信息是必要的&#xff1b;但是头文件可能和cpp放在一起&#xff0c;也可能放在系统某个目录下&#xff0c;semantic怎么才能找到这个头文件一起解析呢&#xff1f;

semantic是这样处理的&#xff1a;1、如果当前目录中能找到&#xff0c;就直接在当前文件中读取头文件。2、如果当前目录下没有&#xff0c;就上系统INCLUDE目录中去找&#xff08;在Linux下&#xff0c;我们一般使用gcc编译器&#xff0c;semantic会自动调用gcc&#xff0c;取得gcc的INCLUDE目录&#xff0c;比如/usr/include,/usr/local/include等&#xff0c;但是Windows下就不行了&#xff09;。

BTW&#xff1a;很多文档中提到需要load semantic-gcc&#xff0c;不过我没有load它&#xff0c;在Linux下semantic仍然能自动把gcc的INCLUDE目录加进来。

semantic这种找法肯定会造成大量的头文件找不到的(找不到头文件还怎么解析啊)&#xff0c;有两个问题需要解决&#xff1a;1、很多工程中都会把头文件和实现文件分开放置&#xff0c;比如头文件放在include(或者inc,public,common等)目录中&#xff0c;实现文件放在src目录中&#xff0c;这些目录semantic是不能自己找的&#xff1b;2、在Windows下怎么能让semantic去找编译器的INCLUDE目录。

既然semantic不能自动查找找&#xff0c;那就只能我们告诉semantic了&#xff0c;办法是调用semantic-add-system-include函数&#xff0c;这个函数会根据mode把路径加入到semantic-dependency-system-include-path里去。下面是我的配置&#xff1a;

?View Code LISP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

;; (setq semanticdb-project-roots (list (expand-file-name "/")))
(defconst cedet-user-include-dirs(list ".." "../include" "../inc" "../common" "../public""../.." "../../include" "../../inc" "../../common" "../../public"))
(defconst cedet-win32-include-dirs(list "C:/MinGW/include""C:/MinGW/include/c&#43;&#43;/3.4.5""C:/MinGW/include/c&#43;&#43;/3.4.5/mingw32""C:/MinGW/include/c&#43;&#43;/3.4.5/backward""C:/MinGW/lib/gcc/mingw32/3.4.5/include""C:/Program Files/Microsoft Visual Studio/VC98/MFC/Include"))
(require &#39;semantic-c nil &#39;noerror)
(let ((include-dirs cedet-user-include-dirs))(when (eq system-type &#39;windows-nt)(setq include-dirs (append include-dirs cedet-win32-include-dirs)))(mapc (lambda (dir)(semantic-add-system-include dir &#39;c&#43;&#43;-mode)(semantic-add-system-include dir &#39;c-mode))include-dirs))

因为我在Windows下可能用MinGW和VC6&#xff0c;所以我把它们的include目录都加进来了&#xff0c;要是你用别的编译器&#xff0c;就改成自己的目录好了。

另外&#xff0c;我找了一些一般项目中经常用到的头文件目录名(include,inc,common,public)&#xff0c;把它们也加进来了&#xff0c;这样对于一般的项目来说基本上都能解析正确&#xff08;比如我们在项目中见到头文件放在include目录实现文件放在src目录的方式&#xff0c;对src目录下一个cpp文件&#xff0c;通过“../include”这个路径就能找到对应的头文件&#xff09;。如果你的项目中还用了其它一些目录名&#xff0c;也可以配置在这儿。

上面配置中那一行(require ’semantic-c nil ‘noerror)是必须的&#xff0c;因为semantic的大部分功能是autoload的&#xff0c;如果不在这儿load semantic-c&#xff0c;那打开一个c文件时会自动load semantic-c&#xff0c;它会把semantic-dependency-system-include-path重设为/usr/include&#xff0c;结果就造成前面自定义的include路径丢失了。

顺便说一下semanticdb-project-roots的配置&#xff0c;很多地方都说要把它配置成”/”&#xff0c;但是我在Linux/Mac/Windows都试验过&#xff0c;不配这一行并没什么影响。

解析文件是semantic基本高级功能的基础&#xff0c;正确地解析了文件我们才能实现&#xff1a;代码跳转和代码补全。

4.3 代码跳转

有了前面的配置&#xff0c;semantic自动就解析c/c&#43;&#43;文件&#xff0c;解析完后跳转就容易了&#xff1a;光标放在函数上&#xff0c;执行M-x semantic-ia-fast-jump&#xff0c;马上就跳转到函数的定义上了。如果跳不过去&#xff0c;那就检查一下前面配置的INCLUDE路径&#xff0c;是不是当前文件include的所有头文件都能在INCLUDE中找到。如果检查了很多遍都不好用&#xff0c;那就换个项目或者别的文件试试&#xff0c;确实存在semantic对某些文件支持不太好的情况&#xff0c;比如boost。

semantic-ia-fast-jump这个功能如此常用&#xff0c;我就把它绑定到f12上去了。

?View Code LISP

(global-set-key [f12] &#39;semantic-ia-fast-jump)

另外&#xff0c;前面我们说过跳转过去了我们还需要跳回来&#xff0c;在打开mru-bookmark-mode的情况下&#xff0c;按[C-x B]&#xff0c;emacs会提示你跳回到哪个地方&#xff0c;一般默认的就是上一次semantic-ia-fast-jump的位置&#xff0c;所以回车就可以回去了。

不过看代码时候我经常需要跳转后马上就跳回来&#xff0c;要按[C-x B] [RET]这么多键实在有点麻烦&#xff0c;所以我写了个函数不提示直接就跳回上次的位置&#xff0c;并把它绑定到shift&#43;f12上了&#xff1a;

?View Code LISP

1
2
3
4
5
6
7
8
9
10
11
12

(global-set-key [S-f12](lambda ()(interactive)(if (ring-empty-p (oref semantic-mru-bookmark-ring ring))(error "Semantic Bookmark ring is currently empty"))(let* ((ring (oref semantic-mru-bookmark-ring ring))(alist (semantic-mrub-ring-to-assoc-list ring))(first (cdr (car alist))))(if (semantic-equivalent-tag-p (oref first tag)(semantic-current-tag))(setq first (cdr (car (cdr alist)))))(semantic-mrub-switch-tags first))))

除了semantic-ia-fast-jump可以跳转之外&#xff0c;其实semantic中还有两个函数也有类似的功能&#xff1a;

  • semantic-complete-jump-local
  • semantic-complete-jump

看名字很容易看出来&#xff0c;前一个只能在当前buffer内跳转&#xff0c;后一个可以跳转到其它文件。不过这两个命令都需要用户手工输入要跳转的Tag名&#xff0c;不能像semantic-ia-fast-jump那样自动识别当前光标处单词&#xff0c;所以浏览代码时还是semantic-ia-fast-jump舒服。

cedet还有个功能在函数和声明和实现间跳转&#xff0c;一般的&#xff0c;函数声明放在h文件中&#xff0c;函数的实现放在cpp文件中&#xff0c;光标在函数体的时候通过M-x semantic-analyze-proto-impl-toggle可以跳到函数声明去&#xff0c;在声明处再执行的话就会再跳回函数体&#xff0c;我把它绑定到M-S-F12上了&#xff1a;

?View Code LISP

(define-key c-mode-base-map [M-S-f12] &#39;semantic-analyze-proto-impl-toggle)

不是这个功能不是十分准确&#xff0c;一般在cpp中函数实现处想跳到函数声明处正常&#xff0c;但是从声明处跳到实现处的话cedet不一定能找到cpp文件的位置。

4.4 代码补全

semantic中有4个用来代码补全的命令&#xff1a;

  • senator-complete-symbol
  • senator-completion-menu-popup
  • semantic-ia-complete-symbol
  • semantic-ia-complete-symbol-menu

senator-complete-symbol和semantic-ia-complete-symbol这两个函数是新开一个buffer提示可能的补全内容&#xff1b;而senator-completion-menu-popup和semantic-ia-complete-symbol-menu会弹出一个补全菜单。

至于功能&#xff0c;以senator开头的两个函数是调用senator补全&#xff0c;另外两个是调用semantic-ia补全。至于senator和semantic-ia的区别&#xff0c;http://alexott.net/en/writings/emacs-devenv/EmacsCedet.html#sec9是这样解释的&#xff1a;

“semantic-ia调用semantic-analyze-possible-completions函数来取得可能的补全内容&#xff0c;它能为用户提供精确的补全列表&#xff1b;而senator用了一个更简单的的函数来获取补全内容&#xff0c;所以有可能会提供错误的结果。”

也就是说semantic-ia的补全更智能一些。

至于semantic-ia这两个补全选哪一样就看各人喜好了&#xff0c;我喜欢用semantic-ia-complete-symbol-menu&#xff0c;因为看起来更直观一些&#xff0c;像这样&#xff1a;

semantic的补全菜单

我喜欢把它绑定到[Alt&#43;n]上&#xff1a;

?View Code LISP

(define-key c-mode-base-map (kbd "M-n") &#39;semantic-ia-complete-symbol-menu)

不过semantic-ia-complete-symbol-menu只能用于GUI下&#xff0c;要是在终端下&#xff0c;就只能用semantic-ia-complete-symbol了。(终端下想要semantic-ia-complete-symbol一样的结果可以用别的插件&#xff0c;比如auto-complete或者company-mode)

如果启用了semantic-idle-completions-mode&#xff0c;不用按键只需要光标在.或者->后面停一会semantic就会自动开始补全了。

如果你用cedet不能补全&#xff0c;检查一下semantic是不是已经启用了&#xff0c;我的emacs上经常出现第一次打开c&#43;&#43;-mode时semantic没自动启用的情况。看semantic是否正常有个直观的方法就是senator&#xff0c;如果启用了senator-minor-mode&#xff0c;打开c&#43;&#43;文件时emacs会出现Senator菜单&#xff0c;如果没有Senator菜单你可以关掉再重新打开试试&#xff0c;要是仍然不出现菜单那就得检查配置是不是有问题。

如果确认semantic启用了仍然不能补全&#xff0c;就需要检查INCLUDE路径的配置&#xff0c;通过C-h v semantic-dependency-system-include-path RET检查INCLUDE路径&#xff0c;确保当前cpp中直接或间接include的头文件都能在INCLUDE路径中找到。



5 EDE配置

EDE是用来管理project的工具&#xff0c;用下面的代码启用它&#xff1a;

?View Code LISP

(global-ede-mode t)

EDE会在emacs中加一个叫做“Project”的菜单&#xff1a;

EDE的Project菜单

通过菜单可以创建project&#xff0c;往project里添加/移除文件&#xff1b;还可以编译project&#xff0c;不过好像只能通过已有的Makefile编译。

另外EDE还可以通过Speedbar显示整个project的目录树(见右边的Speedbar)&#xff1a;

用Speedbar显示project的目录树

EDE可以支持四种类型的project&#xff1a;

  • Automake
  • 手工写的Makefile
  • C&#43;&#43; Root project
  • Simple project

并且EDE能解析Autoconf/Automake&#xff0c;如果打开一个文件时在当前或者上级目录中能找到Makefile.am文件&#xff0c;EDE会自动解析文件(认为这是一个Automake的project)&#xff0c;识别出Makefile.am中定义的target和编译需用到的文件&#xff1b;打开目录树的话EDE能由Makefile.am中涉及到的文件生成目录树&#xff08;上图的目录树就是EDE通过Makefile.am自动生成的&#xff09;。

为了让semantic找到C/C&#43;&#43;的头文件&#xff0c;前面是通过调用semantic-add-system-include把系统中可能出现的INCLUDE目录都告诉semantic的来实现的。其实semantic还可以通过EDE识别project中特定的INCLUDE目录&#xff0c;方法是在.emacs文件中定义C&#43;&#43; Root project&#xff0c;比如&#xff1a;

?View Code LISP

1
2
3
4
5
6
7
8
9
10
11

(setq libutil-project(ede-cpp-root-project "libutil":file "~/projects/libutil/configure.in":system-include-path &#39;("/home/meteor1113/projects/include""/home/meteor1113/projects/common""/home/meteor1113/projects/libutil/pub")))
(setq test-project(ede-cpp-root-project "test":file "~/test/Makefile":system-include-path &#39;("/test/include""/usr/include/boost-1.42")))

上面定义了两个project&#xff0c;并且设定了各个project各自的INCLUDE目录。

不过这种方式有两个缺点&#xff1a;

  • 不能支持常见的Makefile/Makefile.am型project。
  • 我不愿意为每个project都定义这样一个project&#xff0c;对于每天都要自己写代码的项目生成个C&#43;&#43; Root project还可以接受&#xff0c;有时候只是临时阅读一下其它项目&#xff0c;要是还要为它写个EDE的project配置就太麻烦了。

所以这个功能我也一直没用过&#xff0c;有问题的请参考官方文档。我觉得把所有可能的目录都加进system-include里更方便。



6 其它

6.1 可视化书签

emacs有自带的书签功能(c-x r m, c-x r b, c-x r l)&#xff0c;不过对于用了多年VC6的我来说还是更习惯让一个书签能高亮显示出来。cedet里就带了一个可视化的书签&#xff0c;通过下面的语句可以启用它&#xff1a;

?View Code LISP

(enable-visual-studio-bookmarks)

之后就可以通过下面几个按键操作书签了&#xff1a;

  • F2 在当前行设置或取消书签
  • C-F2 查找下一个书签
  • S-F2 查找上一个书签
  • C-S-F2 清空当前文件的所有书签

看这个效果&#xff1a;

cedet的可视化标签

有点遗憾的是这个书签功能只能在当前buffer的书签间跳转。

6.2 pluse

使用semantic-ia-fast-jump跳转时&#xff0c;cedet有个很酷的效果&#xff1a;在跳转到的行上实现一个淡入淡出的效果。具体的分析和使用看这儿。

6.3 h/cpp切换

cedet的contrib目录下有一些实用的小功能&#xff0c;比如eassist.el就提供了一个在C&#43;&#43;的头文件和实现文件间跳转的小功能。

要使用这个功能首先要load它&#xff1a;

?View Code LISP

(require &#39;eassist nil &#39;noerror)

之后就可以通过命令M-x eassist-switch-h-cpp来切换了&#xff0c;我喜欢把它绑定到M-F12上&#xff1a;

?View Code LISP

(define-key c-mode-base-map [M-f12] &#39;eassist-switch-h-cpp)

这个功能是依赖semantic的&#xff0c;也就是说通过cpp找头文件时它也会上配置好的INCLUDE路径中去查找&#xff0c;不过如果通过头文件找cpp文件&#xff0c;好像只能找和头文件所在的同一目录了。

eassist-switch-h-cpp有个BUG&#xff1a;它是通过文件扩展名来匹配的(通过eassist-header-switches可配置)&#xff0c;默认它能识别h/hpp/cpp/c/C/H/cc这几个扩展名的文件&#xff1b;但是C&#43;&#43;的扩展名还可能会有别的&#xff0c;比如c&#43;&#43;,cxx等&#xff0c;对一个扩展名为cxx的文件调用eassist-switch-h-cpp的话&#xff0c;它会创建一个新buffer显示错误信息。所以我把eassist-header-switches配置为&#xff1a;

?View Code LISP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

(setq eassist-header-switches&#39;(("h" . ("cpp" "cxx" "c&#43;&#43;" "CC" "cc" "C" "c" "mm" "m"))("hh" . ("cc" "CC" "cpp" "cxx" "c&#43;&#43;" "C"))("hpp" . ("cpp" "cxx" "c&#43;&#43;" "cc" "CC" "C"))("hxx" . ("cxx" "cpp" "c&#43;&#43;" "cc" "CC" "C"))("h&#43;&#43;" . ("c&#43;&#43;" "cpp" "cxx" "cc" "CC" "C"))("H" . ("C" "CC" "cc" "cpp" "cxx" "c&#43;&#43;" "mm" "m"))("HH" . ("CC" "cc" "C" "cpp" "cxx" "c&#43;&#43;"))("cpp" . ("hpp" "hxx" "h&#43;&#43;" "HH" "hh" "H" "h"))("cxx" . ("hxx" "hpp" "h&#43;&#43;" "HH" "hh" "H" "h"))("c&#43;&#43;" . ("h&#43;&#43;" "hpp" "hxx" "HH" "hh" "H" "h"))("CC" . ("HH" "hh" "hpp" "hxx" "h&#43;&#43;" "H" "h"))("cc" . ("hh" "HH" "hpp" "hxx" "h&#43;&#43;" "H" "h"))("C" . ("hpp" "hxx" "h&#43;&#43;" "HH" "hh" "H" "h"))("c" . ("h"))("m" . ("h"))("mm" . ("h"))))

基本上所有C/C&#43;&#43;的扩展名都包含了&#xff0c;同时ObjectiveC也可以用了。

6.4 代码折叠

6.4.1 semantic-tag-folding

从我开始用emacs开始就听大虾们说hs-minor-mode可以实现代码折叠&#xff0c;所以我的.emacs里一直把hs-minor-mode打开的&#xff0c;可是用了5年之后我发现还是不习惯它的按键&#xff0c;另外也不是很喜欢它显示的样子&#xff0c;5年来Hide/Show这个菜单对我来说基本上是个摆设。

我期待像eclipse那样可以通过鼠标在直接点击就可以打开和折叠代码&#xff0c;这个功能在cedet也实现了(可惜这么长时间一直没发现它)&#xff0c;就是semantic-tag-folding.el(也在cedet的contrib目录下)。

?View Code LISP

1
2

(require &#39;semantic-tag-folding nil &#39;noerror)
(global-semantic-tag-folding-mode 1)

看这个图&#xff1a;

cedet的代码折叠

只要用鼠标点击左侧的小三角图标就可以打开或折叠代码了。箭头向下的空心三角表示这段代码可以被折叠&#xff0c;箭头向右的实心三角表示这段代码被打折过了。

为了方便键盘操作&#xff0c;我把按键绑定到了[C-c , -]和[C-c , &#43;]上(绑定这么复杂的
按键主要是为了和senator兼容&#xff0c;后面会讲到senator实现代码折叠)&#xff1a;

?View Code LISP

1
2

(define-key semantic-tag-folding-mode-map (kbd "C-c , -") &#39;semantic-tag-folding-fold-block)
(define-key semantic-tag-folding-mode-map (kbd "C-c , &#43;") &#39;semantic-tag-folding-show-block)

同时它还提供了两个函数可以同时打开和折叠整个buffer的所有代码&#xff0c;分别是
semantic-tag-folding-fold-all和semantic-tag-folding-show-all&#xff0c;我把它们
绑定到了[C-_]和[C-&#43;]上&#xff1a;

?View Code LISP

1
2

(define-key semantic-tag-folding-mode-map (kbd "C-_") &#39;semantic-tag-folding-fold-all)
(define-key semantic-tag-folding-mode-map (kbd "C-&#43;") &#39;semantic-tag-folding-show-all))

打开semantic-tag-folding-mode后&#xff0c;用gdb调试时不能点左侧的fringe切换断点了&#xff0c;所以我把C-?定义为semantic-tag-folding-mode的切换键&#xff0c;在gdb调试时临时把semantic-tag-folding关掉&#xff1a;

?View Code LISP

(global-set-key (kbd "C-?") &#39;global-semantic-tag-folding-mode)

不过&#xff0c;semantic-tag-folding在终端下会有一点点小问题&#xff1a;终端下semantic-tag-folding在函数前面加了个“&#43;”或“-”号&#xff0c;看下面这个图&#xff1a;

终端下的semantic-tag-folding

虽然功能不受影响(除了不能用鼠标操作外&#xff0c;快捷键和GUI下是一样的)&#xff0c;不过代码不能对齐了还是令我有些不爽&#xff0c;所以终端下我是禁用semantic-tag-folding的&#xff0c;最终我的配置如下&#xff1a;

?View Code LISP

1
2
3
4
5
6
7

(when (and window-system (require &#39;semantic-tag-folding nil &#39;noerror))(global-semantic-tag-folding-mode 1)(global-set-key (kbd "C-?") &#39;global-semantic-tag-folding-mode)(define-key semantic-tag-folding-mode-map (kbd "C-c , -") &#39;semantic-tag-folding-fold-block)(define-key semantic-tag-folding-mode-map (kbd "C-c , &#43;") &#39;semantic-tag-folding-show-block)(define-key semantic-tag-folding-mode-map (kbd "C-_") &#39;semantic-tag-folding-fold-all)(define-key semantic-tag-folding-mode-map (kbd "C-&#43;") &#39;semantic-tag-folding-show-all))

需要注意的是&#xff0c;semantic-tag-folding依赖于语法解析&#xff0c;也就是说必须等semantic解析完文件之后才能使用。如果找开文件在fringe处找不到空心三角&#xff0c;可以[Force Tag Refresh]下&#xff0c;或者检查下semantic是否配置正确。

6.4.2 senator-fold-tag

终端下不用semantic-tag-folding了&#xff0c;最好能有替代方案吧&#xff1a;首先可以用回hs-minor-mode&#xff0c;此外cedet的senator也提供了一种代码折叠方案。

只要启用了senator-minor-mode(emacs中会出现Senator菜单)&#xff0c;就可以通过M-x senator-fold-tag和M-x senator-unfold-tag来折叠和打开代码了&#xff0c;GUI和终端下都可以使用。

默认地&#xff0c;senator-fold-tag绑定到[C-c , -]&#xff0c;senator-unfold-tag绑定到[C-c , &#43;]上(所以前面我把semantic折叠的快捷键也绑定到这两个键上&#xff0c;这样GUI和终端下快捷键就一致了)。不过senator里好像没有对应的fold-all和show-all方法。



7 Todo

以上只是cedet里我用到的一些功能&#xff0c;其实cedet还有很多优秀的功能&#xff0c;比如通过模板自动生成代码(SRecode)&#xff1b;通过代码画UML图以及通过UML图生成代码(Cogre)等&#xff1b;另外semantic除了可以自己解析代码外还可以借助ctags,global,ebrowse来解析。更多的功能需要进一步发掘。

最后&#xff0c;欢迎参观我的cedet配置: http://github.com/meteor1113/dotemacs/blob/master/init-site.el







推荐阅读
  • 直接从网上下载redis当然你也可以直接从别的地方拿过来直接放在redis中[root@iZ2zedckzf8nczp6xshv4mZ]#wgethttp:download ... [详细]
  • 201720181 20155315 《信息安全系统设计基础》实验四 外设驱动程序设计
    实验内容学习资源中全课中的“hqyj.嵌入式Linux应用程序开发标准教程.pdf”中的第十一章在Ubuntu完成资源中全课中的“hqyj.嵌入式Linux应用程序开发标准教程.p ... [详细]
  • CentOS7系统目录LINUX有四种基本文件系统类型普通文件:如文本文件、C语言元代码、SHELL脚本、二进制的可执行文件等,可用cat、less、 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 源码安装Nginx 解决报错
    CentOS8源码安装Nginx编译安装注意事项如果安装时不是使用的默认路径,则必须要修改PATH环境变量,以能够识别此程序的二进制文件路径 ... [详细]
  • 32位ubuntu编译android studio,32位Ubuntu编译Android 4.0.4问题
    问题一:在32位Ubuntu12.04上编译Android4.0.4源码时,出现了关于emulator的错误,关键是其Makefile里的 ... [详细]
  • 如何在Vue项目中安装和使用VUX组件?
    vux2模板fork自webpack模板,基本和官方同步。1、默认为webpack2模板npminstallvue-cli-g如果还没安装vueinitairyla ... [详细]
  • 1.      准备工作: 程序:MinGW-3.1.0-1.exe     windows下的gcc,编译c语言的工具下载地址: http:umn.dl.sourceforge. ... [详细]
  • 操作系统RetHat9.0,存储设备华为3comEX1000在linux上建立能够识别盘阵的方法有三种1、HBA卡;2、TOE卡;3、is ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • 设备模型三(潜谈sysfs)
    前言引出一个问题:假设sysaxx,xx是kobja的属性文件,当对xx进行写操作时,即echo‘1’sysaxx实际上,调用了kobja的ktype中定义的接口函 ... [详细]
  • 序言n前言nn第一章概述1n1.1简单插件实例——创建带孔板有限元模型2n1.2Abaqus图形界面程序开发的意义10nn第二章Python语言基础11 ... [详细]
author-avatar
as16as1
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有