Simple example of elisp: taglist

Switching from vim to emacs, I have been feeling lost because of the lack of tablist plug-ins in vim. I
got a taglist in emacs from the Internet. Its functions are very simple, and there is no explanation.
It is used as a simple example of elisp for reference. It’s not bad for beginners to get started. I added a lot of comments to it to help understand.
To be honest, I feel that this hundred lines of code is quite deep. Only when you experience it slowly can you debug it.
Thank you for the open source spirit of the original author!

Usage:
Save the following part as taglist.el, and add
(requre 'taglist)
to init.el.
People who can write elisp code should have no problem using it.
$cat taglist.el

;; full high-energy code

;;Define a list, 3 types of face (highlight syntax)
;;Regular expression matches 3 groups,
;;The first group contains words without leading spaces, the second group consists of L and numbers, and the third group has no spaces The remainder of
(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)))

;;Define a local-map and define 2 shortcut keys.
;;map is an object, or a list, its car is "keymap", and its cdr is an alist
;;alist is composed of (CHAR.DEFINITION)
(defvar taglist-map
  (let ((map (make-sparse-keymap))) ; clear map
    (define-key map (kbd "RET") 'taglist-jump) ; define RET key
    (define-key map (kbd " q") 'taglist-kill) ; define q key
    map)) ; return map,

;; Take it easy
(defvar taglist-mode-hook nil)
(defvar taglist-window nil)
(defvar taglist-sum 0)
;; define a main mode, enable a local-map, enable a font-lock (defun taglist-window nil
) (defvar taglist-sum 0) ;; 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))

;;Define taglist function
;; Obtain current buffer and line number, create tags list buffer
;; Obtain tags and fill them
;; Split window and associate buffer to window, select window
;; set to taglist-mode
(defun taglist nil
  ( interactive)
  (require 'speedbar)
  (require 'imenu)
  ;; Clear cache
  (setq imenu--index-alist nil)
  (let ((buffer (current-buffer)) ; current-buffer function returns an object
        (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))); pass parameter buffer name for speedbar to generate tag
     ""
     line-num); line number
    (goto-char (point-min))
    (forward-line (1- taglist-sum))
    (setq taglist-window (split-window-vertically)) ; split-window returns a window object
    (set-window-buffer taglist-window "*tags list*"); Set the buffer corresponding to the window
    (select-window taglist-window)
    (taglist-mode))); set the main mode
;; essence, high energy!
;; fill tags in the buffer, prefix is ​​the prefix, line-num is the line number ,tags is a list
;;marker is an object, its expression is for example: #<marker at 679 in taglist.el>
;;tags is a composite list, and its final print form is:
;; 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
;;
; 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)) ;if tag The first item of data is marker
        (let ((tag-line ; Get the line number of the tag
               (with-current-buffer buffer ; cdar is first car, then cdr
                 (line-number-at-pos (cdar tags))))) ;Return the body in the buffer
          (insert (format "\t%s L%-5d%s%s\n"
                          (buffer-name buffer)
                          tag-line
                          prefix
                          (caar tags))); Insert a line of data, buffer name, line number, name
          (when (>= line-num tag-line)
            (setq taglist-sum
                  (1+ taglist-sum)))) ; Count the number of taglist a
      (let* ((dir-string (caar tags)); Part 2 of if , when it is not a marker, get the directory string
             (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); call itself first, process the next layer
                           (concat "+-" prefix)
                           line-num)))
    (setq tags (cdr tags)))); process sibling nodes

;; When there is a tag-list window and it is not the only window, delete the window and delete the buffer
(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*"))
;; jump:
;;get current line content
;;extract match , the first item is buffer, the second item is 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)

おすすめ

転載: blog.csdn.net/hejinjing_tom_com/article/details/129350488