天津外贸营销型网站建设京东建站模板
从vim 转到emacs 下,一直为缺少vim 中的tablist 插件而感到失落.
 从网上得到的一个emacs中的taglist, 它的功能很简陋,而且没有任何说明,
 把它做为elisp的简单实例,供初学者入门倒不错,我给它加了很多注释,帮助理解,
 说实话,感觉这百行代码还是挺有深度的,慢慢体会,调试才会有收获.
 感谢原作者的开源精神!
用法:
 把后边的部分存诚taglist.el,在init.el中添加
 (requre 'taglist)
 就可以了.
 能写elisp代码的人应该对使用不会有问题.
 $cat taglist.el
;; 全程高能代码
;;定义一个列表, 3种face(高亮语法)
 ;;正则表达式匹配3个分组,
 ;;第1分组不带前导空格的词,第2分组L和数字构成,第3分组不带空格的剩余部分
 (defvar taglist-keywords
   (list (list "^\t\\([^ ]*\\) \\(L[0-9]+\\) *\\(.*\\)$" 1 font-lock-keyword-face)
         (list "^\t\\([^ ]*\\) \\(L[0-9]+\\) *\\(.*\\)$" 2 font-lock-comment-delimiter-face)
         (list "^\t\\([^ ]*\\) \\(L[0-9]+\\) *\\(.*\\)$" 3 font-lock-function-name-face)))
;;定义一个local-map,定义了2个快捷键.
 ;;map 是一个对象,或者说是一个列表,其car是"keymap",其cdr是一个alist
 ;;alist由(CHAR.DEFINITION)构成
 (defvar taglist-map
   (let ((map (make-sparse-keymap))) ;清空map
     (define-key map (kbd "RET") 'taglist-jump) ;定义RET键
     (define-key map (kbd "q") 'taglist-kill) ;定义q键
     map)) ;返回map,
;;稍微轻松一下
 (defvar taglist-mode-hook nil)
 (defvar taglist-window nil)
 (defvar taglist-sum 0)
 ;;定义一个主模式,启用一个local-map,启用一个font-lock
 (defun taglist-mode nil
   (interactive)
   (kill-all-local-variables)
   (use-local-map taglist-map)
   (setq major-mode 'taglist-mode)
   (setq mode-name "Tag-List")
   (setq font-lock-defaults
         (list 'taglist-keywords))
   (run-mode-hooks 'taglist-mode-hook))
;;定义taglist 函数
 ;; 获取当前缓冲区及行号,创建tags list缓冲区
 ;; 获取tags 并填充
 ;; 分割窗口并关联buffer到window,选择window
 ;; 设置为taglist-mode
 (defun taglist nil
   (interactive)
   (require 'speedbar)
   (require 'imenu)
   ;; Clear cache
   (setq imenu--index-alist nil)
   (let ((buffer (current-buffer)) ;current-buffer函数返回一个对象
         (line-num (line-number-at-pos)))
     ;; Create a buffer
     (if (get-buffer "*tags list*")
         (kill-buffer "*tags list*"))
     (set-buffer (get-buffer-create "*tags list*"))
     ;; Call speedbar tags
     (setq taglist-sum 0)
     (taglist-fill-tags
      buffer
      (cddr (speedbar-fetch-dynamic-tags
             (buffer-file-name buffer))); 传参缓冲区名字,供speedbar生成tag
      ""
      line-num); 行号
     (goto-char (point-min))
     (forward-line (1- taglist-sum))
     (setq taglist-window (split-window-vertically)) ;split-window 返回一个window对象
     (set-window-buffer taglist-window "*tags list*");设置window对应的缓冲区
     (select-window taglist-window)
     (taglist-mode)));设置主模式
 ;;精华所在,高能!
 ;;在缓冲中填充tags, prefix为前缀,line-num为行号,tags是列表
 ;;marker是一种对象,它的表示是例如: #<marker at 679 in taglist.el>
 ;;tags 是复合列表,其最后的打印形式为:
 ;;    taglist.el L0    Variables
 ;;    taglist.el L6    +-taglist-keywords
 ;;    taglist.el L23   +-taglist-sum
 ;;    taglist.el L72   taglist-fill-tags
 ;;    taglist.el L108  taglist-kill
 ;;    taglist.el L119  taglist-jump
 ;;tags 其文本表示形式为:
 ;; Result: (("Variables" ("taglist-keywords" . #<marker at 90 in taglist.el>) ("taglist-map" . #<marker at 482 in taglist.el>)) ("taglist-mode" . #<marker at 803 in taglist.el>))
 (defun taglist-fill-tags (buffer tags prefix line-num)
   (while tags
     (if (integer-or-marker-p (cdar tags)) ;若tag 数据第1项为marker
         (let ((tag-line                      ;获取tag的行号
                (with-current-buffer buffer ;cdar 是先car,再cdr
                  (line-number-at-pos (cdar tags)))));返回buffer中的body
           (insert (format "\t%s L%-5d%s%s\n"
                           (buffer-name buffer)
                           tag-line
                           prefix
                           (caar tags)));插入一行数据,缓冲名,行号,名称
           (when (>= line-num tag-line)
             (setq taglist-sum
                   (1+ taglist-sum)))) ;统计taglist个数a
       (let* ((dir-string (caar tags)); if的第2部分,非marker时,获取目录字串
              (marker (get-text-property 0 'org-imenu-marker dir-string))
              (tag-line 0))
         (if marker
           (setq tag-line
                 (with-current-buffer buffer
                   (line-number-at-pos marker))))
         (insert (format "\t%s L%-5d%s%s\n"
                         (buffer-name buffer)
                         tag-line
                         prefix
                         (caar tags)))
         (when (>= line-num tag-line)
           (setq taglist-sum
                 (1+ taglist-sum)))
         (taglist-fill-tags buffer
                            (cdar tags);第归调用自己,处理下一层
                            (concat "+-" prefix)
                            line-num)))
     (setq tags (cdr tags))));处理兄弟节点
;;当存在tag-list窗口且不是唯一窗口,则删除窗口并删除缓冲
 (defun taglist-kill nil
   (interactive)
   (if (and taglist-window
            (window-live-p taglist-window)
            (not (one-window-p)))
       (delete-window taglist-window))
   (setq taglist-window nil)
   (kill-buffer "*tags list*"))
 ;; 跳转:
 ;;获取当前行内容
 ;;提取匹配项,第一项为buffer,第二项为number
 (defun taglist-jump nil
   (interactive)
   (let ((string-line (buffer-substring
                (line-beginning-position)
                (line-end-position))))
     (string-match "^\t\\([^ ]*\\) L\\([0-9]+\\)[^0-9]" string-line)
     (taglist-kill)
     (switch-to-buffer (match-string 1 string-line))
     (goto-char (point-min))
     (forward-line (1- (string-to-number (match-string 2 string-line))))))
 (provide 'taglist)
