elisp简单实例: taglist
创始人
2024-05-29 00:42:25
0

从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" . #) ("taglist-map" . #)) ("taglist-mode" . #))
(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)

相关内容

热门资讯

元旦晚会的致辞 元旦晚会的致辞(精选12篇)  在平时的学习、工作或生活中,大家肯定对各类致辞都很熟悉吧,致辞是指在...
欢聚一堂的主持词 欢聚一堂的主持词  主持词要根据活动对象的不同去设置不同的主持词。在当下这个社会中,主持人的需求越来...
在中学励志报告会上的主持词 在中学励志报告会上的主持词   在人们越来越注重自身素养的今天,报告不再是罕见的东西,我们在写报告的...
惊鸿舞主持词 惊鸿舞主持词汇总  1、《Lightspeed》  男:青春,是阳光下初融的冰雪,叮咚叮咚奏响着奇幻...
主持人串词等 主持人串词等五篇  第一篇:《新款文艺汇演主持人串词》  2014年文艺汇演主持人串词  男1、女1...
初中毕业典礼主持词开场白 初中毕业典礼主持词开场白  时光弹指一挥间悄然而逝,在这个栀子花开的季节,初中学生即将毕业,初中毕业...
运动会主持词 运动会主持词范本合集5篇  根据活动对象的不同,需要设置不同的主持词。随着中国在不断地进步,越来越多...
晚会节目主持串词 晚会节目主持串词  篇一:第五届艺体节节目主持串词  第五届艺体节节目主持串词 下午衔接:各位老师,...
《为了谁》节目主持词 《为了谁》节目主持词  持人在台上所表演的主持词,则是集会的灵魂之所在。下面是小编收集整理的《为了谁...
新郎婚礼致辞 关于新郎婚礼致辞(精选5篇)  在日常学习、工作和生活中,大家都写过致辞吧,致辞是指在举行会议或某种...
乔迁的感谢词 乔迁的感谢词  尊敬的各位来宾、女士们、先生们、亲爱的父老乡亲们:  大家好!  首先我代表我的家人...
开业致辞 开业致辞(通用6篇)  在日复一日的学习、工作或生活中,大家或多或少都用到过致辞吧,致辞要求风格的雅...
80岁生日庆典主持词 80岁生日庆典主持词(精选5篇)  主持词可以采用和历史文化有关的表述方法去写作以提升活动的文化内涵...
感恩节活动主持词 2022年感恩节活动主持词  根据活动对象的不同,需要设置不同的主持词。在如今这个中国,我们对主持词...
电视剧《一起同过窗》经典的台... 电视剧《一起同过窗》经典的台词  在社会一步步向前发展的今天,很多情况下我们需要用到台词,台词是用以...
开门红主持词 开门红主持词  活动对象的不同,主持词的写作风格也会大不一样。在现在的社会生活中,主持人在活动中起到...
六一儿童节慰问活动致辞 六一儿童节慰问活动致辞(通用5篇)  在我们平凡的日常里,大家一定都接触过致辞吧,致辞具有有张有弛、...
生日主持词 关于生日主持词范文集锦五篇  主持词要注意活动对象,针对活动对象写相应的主持词。在当今社会生活中,司...
春晚节目主持人 临近春节,中央电视台毫无悬念地对外宣布70后吕逸涛,正式出任2016年猴年央视春晚总导演。消息公布后...
教师节领导简短致辞 教师节领导简短致辞(精选8篇)  在日常学习、工作和生活中,大家都不可避免地要接触到致辞吧,致辞讲求...