从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是一种对象,它的表示是例如: #
;;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" . #
(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)
上一篇:C++编程语言STL之unordered_map介绍
下一篇:85.链表总结