zoukankan      html  css  js  c++  java
  • Emacs 自动填充头文件

    目标

    1. 写 C/C++ 代码时候,可以根据自动补全头文件。注意,是补全,也就是说至少我们需要输入几个字符让它帮忙补全。
    2. 如果头文件存放在搜索路径的子目录中,可以自动列出子目录中的文件,并将这些文件添加到用于补齐的候选名单中。
    3. 补齐完成之后,可以自动判断到底应该使用 #include 还是 #include “FILE” 。

    方案

    emacser.org 上有一篇文章,其中提到了这个解决方法,主要是利用了 abbrev-mode 和 skeleton-mode 来实现,通过这个方法,我们输入 inc, 然后按空格, 会提示输入文件名称。

    代码如下:

    ?View Code LISP
     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    ;; 安装 abbrev
    (mapc
     (lambda (mode)
       (define-abbrev-table mode '(
                                   ("inc" "" skeleton-include 1)
                                   )))
     '(c-mode-abbrev-table c++-mode-abbrev-table))
     
    ;; 输入 inc , 可以自动提示输入文件名称,可以自动补全.
    (define-skeleton skeleton-include
      "generate include<>" ""
      > "#include <"
      (completing-read "Include File:"
                       (mapcar #'(lambda (f) (list f ))
                               (apply 'append
                                      (mapcar
                                       #'(lambda (dir)
                                           (directory-files dir))
                                       (list "/usr/include"
                                             "/usr/local/include"
                                             "/usr/include/g++-3")))))
      ">")

    该方法有若干局限性:

    • 头文件的搜索路径是写死的,如果某个目录不存在,上面的代码会报错,不能补全。
    • 无法补全搜索路径的子目录下的文件 ( 即前面的 AIM 2)。
    • 没有判断在 #include 一个文件的时候,是应该使用符号 <> 还是符号 “” (即前面的 AIM 3)

    解决方法并不复杂,对应如下:

    • 通过某种方法来从系统中自动获取 include 的搜索路径。比如 CEDET 提供的: semantic-gcc-get-include-paths 函数。
    • 重定义 minibuffer-mode 下的按键 “/”。将其绑定到一个用于搜索和展开某个目录,并更新 minibuffer-completion-table 的函数(minibuffer-completion-table 是 minibuffer-mode 中补全的候选 list)。
    • 在 skeleton-include 中不使用 <> 或者 “。我们可以使用一个特殊的标记,然后在 skeleton-include 的结尾,根据头文件的路径判断到底应该使用什么符号。

    整理以后的代码实现如下:

    ?View Code LISP
     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    
    ;; 输入 inc , 可以自动提示输入文件名称,可以自动补全.
    ;; Provided by yangyingchao@gmail.com
    (mapc
     (lambda (mode)
       (define-abbrev-table mode '(
                                   ("inc" "" skeleton-include 1)
                                   )))
     '(c-mode-abbrev-table c++-mode-abbrev-table))
     
    (defconst yc/inc-dir-list
      (append (semantic-gcc-get-include-paths "c++") '("./")) "nil")
    (defvar inc-minibuffer-compl-list nil "nil")
     
    (defun yc/update-minibuffer-complete-table ( )
      "Complete minibuffer"
      (interactive)
      (let ((prompt (minibuffer-prompt))
            (comp-part (minibuffer-contents-no-properties)))
        (when (and (string= "Include File:" prompt)
                   (> (length comp-part) 0))
          (setq minibuffer-completion-table
                (append minibuffer-completion-table
                        (let ((inc-files nil)
                              (dirname nil)
                              (tmp-name nil))
                          (mapc
                           (lambda (d)
                             (setq dirname (format "%s/%s" d comp-part))
                             (when (file-exists-p dirname)
                               (mapc
                                (lambda (x)
                                  (when (not (or (string= "." x)
                                                 (string= ".." x)))
                                    (setq tmp-name (format "%s/%s" comp-part x))
                                    (add-to-list 'inc-files tmp-name)))
                                (directory-files dirname))))
                           yc/inc-dir-list)
                          inc-files)))))
      (insert "/"))
     
    (let ((map minibuffer-local-completion-map))
      (define-key map "/" 'yc/update-minibuffer-complete-table))
     
    (defun yc/update-inc-marks ( )
      "description"
        (let ((statement (buffer-substring-no-properties
                          (point-at-bol) (point-at-eol)))
              (inc-file nil)
              (to-begin nil)
              (to-end nil)
              (yc/re-include
               (rx "#include" (+ ascii) "|XXX|" (group (+ ascii)) "|XXX|")))
          (when (string-match yc/re-include statement)
            (setq inc-file (match-string 1 statement))
            (if (file-exists-p (format "./%s" inc-file))
                (setq to-begin "\"" to-end "\"")
              (setq to-begin "<" to-end ">")
              )
            (move-beginning-of-line 1)
            (kill-line)
            (insert (format "#include %s%s%s" to-begin inc-file to-end))
            (move-end-of-line 1))))
     
    (define-skeleton skeleton-include
      "generate include<>" ""
      > "#include |XXX|"
      (completing-read
       "Include File:"
       (mapcar
        (lambda (f) (list f ))
        (apply
         'append
         (mapcar
          (lambda (dir)
            (directory-files
             dir nil
             "\\(\\.h\\)?"))
          yc/inc-dir-list))))
      "|XXX|"
      (yc/update-inc-marks))

    使用和效果

    使用方法很简单:

    1. 将上述的代码添加到 Emacs 的配置文件后,打开一个 C/C++ 程序,
    2. 输入 inc 然后按下空格,然后在 minibuffer 中输入部分头文件的名字,并通过 TAB 来补全。
    3. 如果头文件位于子目录中,则输入目录名后输入 “/” 。这样子目录中的内容也会添加到补齐的候选名单中,然后就又可以继续他过 TAB 补全了。
    4. 确认 minibuffer 中填写的内容无误后,回车, skeleton-include 将自动更新标记符号。

    截图:

    下面是几张截图:

    Include 系统文件
    Include 自定义文件
    全部完成后截图
  • 相关阅读:
    进度条
    html5 表单新增事件
    html5 表单的新增type属性
    html5 表单的新增元素
    html5 语义化标签
    jq 手风琴案例
    codeforces 702D D. Road to Post Office(数学)
    codeforces 702C C. Cellular Network(水题)
    codeforces 702B B. Powers of Two(水题)
    codeforces 702A A. Maximum Increase(水题)
  • 原文地址:https://www.cnblogs.com/babe/p/2441586.html
Copyright © 2011-2022 走看看