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 自定义文件
    全部完成后截图
  • 相关阅读:
    BZOJ_2802_[Poi2012]Warehouse Store_堆+贪心
    BZOJ_1025_[SCOI2009]游戏_DP+置换+数学
    BZOJ_3672_ [Noi2014]购票_CDQ分治+斜率优化
    BZOJ_3671_[Noi2014]随机数生成器_set+贪心
    BZOJ_1998_[Hnoi2010]Fsk物品调度_并查集+置换
    BZOJ_1119_[POI2009]SLO_置换+贪心
    「JOI Open 2016」摩天大楼(笛卡尔树dp+优化)
    【GDOI2020模拟01.16】树上的鼠 (博弈+长链剖分优化dp)
    【GDOI2020模拟01.16】划愤(nim积+行列式)
    Codeforces [Hello 2020] 1284F New Year and Social Network(图论匹配推理+lct)
  • 原文地址:https://www.cnblogs.com/babe/p/2441586.html
Copyright © 2011-2022 走看看