etags - Build a TAG for Multiple R Packages
04 May 2016Here is what tried to build a TAG for multiple R packages. It enable me to jump to a location where the function/variable is defined and modify if I want to.
Useful variable and functions
- ess-r-package-library-path
- default path to find packages, should be a list
- ess-r-package-root-file
- if the folder has DESCRIPTION file, then the folder is a R package.
- (ess-build-tags-for-directory DIR TAGFILE)
- build tag on DIR to TARGET.
- tags-table-list
- List of file names of tags tables to search.
- (visit-tags-table FILE &optional LOCAL)
- Tell tags commands to use tags table file.
;; new variable
(defvar ess-r-package-library-tags nil
"A TAG file for multiple R packages.")
(setq ess-r-package-library-path '("~/tmp/feather/R" "~/tmp/RPostgres/"))
(setq ess-r-package-library-tags "~/tmp/all_tags")
(dolist (pkg-path ess-r-package-library-path)
(let ((pkg-name (ess-r-package--find-package-name pkg-path)))
(unless (and pkg-name pkg-path
(file-exists-p (expand-file-name ess-r-package-root-file pkg-path)))
(error "Not a valid package. No '%s' found in `%s'." ess-r-package-root-file pkg-path))
(ess-build-tags-for-directory pkg-path ess-r-package-library-tags)
))
Note the workhorse is ess-build-tags-for-directory
which does what
it means. The core of this function use find
and etags
program.
The find
program will find files with extension .cpp, R, nw etc, and
then feed to (using pipe) to the etags
program which generate a TAG
table. These two steps are demonstrated in the following snippet,
which is grabbed from the source code of
ess-build-tags-for-directory
.
(setq find-cmd (format "find %s -type f -size 1M \\( -regex \".*\\.\\(cpp\\|jl\\|[RsrSch]\\(nw\\)?\\)$\" \\)" (car ess-r-package-library-path)))
(setq regs (delq nil (mapcar (lambda (l)
(if (string-match "'" (cadr l))
nil ;; remove for time being
(format "/%s/\\%d/"
(replace-regexp-in-string "/" "\\/" (nth 1 l) t)
(nth 2 l))))
imenu-generic-expression)))
(setq tags-cmd (format "etags -o %s --regex='%s' -" "~/lala"
(mapconcat 'identity regs "' --regex='")))
(setq sh-cmd (format "%s | %s" find-cmd tags-cmd))
(shell-command sh-cmd)
Note when they are used in Emacs, the tags-table-list variable is
appended with the path to the new TAG table. So that the user can use
xref-find-definitions
(M-.
) to jump (if the point is under a word) or
select which function/variable to jump to. The users then check the
function/variable definition, or modify it if it is necessary. Then
call xref-pop-marker-stack
(M-,
) to jump back.