How to programmatically create/update a TAGS file with emacs?
Asked Answered
H

7

20

Is there any plugin for emacs to automatically update the TAGS file in my C project (for example on buffer save or access) or create a new one if there is no TAGS file present?

I am running on Windows (without Cygwin), so all the fancy shell scripting does not help. I was hoping for a native emacs solution not using any external scripting.

I already tried build-tags.el and etags-table.el but none of these really worked (the way I wanted).

Any other ideas?

Hazelwood answered 14/2, 2009 at 3:15 Comment(0)
P
10

Here is how I generate a TAGS file for a C project:

  1. M-x cd YOUR_DIRECTORY
  2. M-x compile
  3. find . -name "*.[chCH]" -print | etags -

That will create a TAGS file in the current directory for all sub directories and files.

Here is a emacs function that does the exact same thing:

(defun compile-tags ()
  "compile etags for the current project"
  (interactive)
  (cd "YOUR_DIRECTORY")
  (compile "find . -name \"*.[chCH]\" -print | etags -"))

NOTE: if you are on windows you'll need to install cygwin and make sure c:\cygwin\bin is in your path so that you get find in your path. Also make sure the emacs bin directory is in your path so that you can get etags as well.

Pragmaticism answered 14/2, 2009 at 8:13 Comment(1)
You can also use the native windows version of gnu utils including find and so on. I find them faster than cygwin. gnuwin32.sourceforge.netAtthia
L
10

etags-update may help in your case. I didn't test it, but according to the readme:

etags-update.el is a Emacs global minor mode that updates your TAGS when saving a file.

I found it on the Emacswiki page for building TAGS files

Limbourg answered 23/4, 2010 at 12:54 Comment(0)
K
4

Why not add an execution of ctags to your build script? You really only need a new tags file when you compile (at the most). I tend to just write a scheduled task to build the tags file every night. Seems to work pretty well.

Kookaburra answered 14/2, 2009 at 3:37 Comment(5)
I want the TAGS file updated as soon as new symbols are introduced in the source. I extensively use TAGS browsing capabilities when developing to jump from file to file. Once a night is not often enough. Personal build script mods are not possible in our multi developer environment.Hazelwood
How do you build your code? Wrap that command with a script that does the build, then runs the ctags command.Kookaburra
I disagree -- you want tags immediately after editing the buffer.Kirksey
@Steve Rowe: Yeah, I could probably script something together. But I dont like it. @jrockway: I agree. I NEED it immediately and not necessarily want to build every time.Hazelwood
@Hazelwood What about writing some fancy save hook for .c and .h Files?Giulietta
S
2

I use combination of semantic + gnu global for my day-to-day work. GNU Global's databases are updated once per day, while semantic use them for basic navigation, and re-parse changed files on the fly.

You can find more about these packages in my article about Cedet

Stoecker answered 14/2, 2009 at 6:59 Comment(1)
URL not found on server!Nitrite
L
2

Try out my `ctags.el'[1] module.

Configuration example:

(setq tags-revert-without-query t)
(global-set-key (kbd "<f5>") 'ctags-create-or-update-tags-table)

Then just press <f5> to update or create your TAGS file. That function look for a file TAGS in the current and its parent directories, if a TAG file is not found it ask you where create a new one.

It is a new library and probably has bugs, etc, so any help is welcome.

[1] https://bitbucket.org/semente/ctags.el/

Launalaunce answered 18/6, 2011 at 12:43 Comment(0)
A
1

This might get you close (untested):

(defvar my-auto-update-tags-alist
  (list '("/some/path/to/TAGS" "command_to_build_tags")
        '("/another/path/to/TAGS" "another_build_command")))

(defun my-auto-update-tags ()
  "Automatically update TAGS files"
  (tags-table-check-computed-list)
  (let ((filename (buffer-file-name))
        build-cmd)
    (mapc (lambda (tag-file)
            (set-buffer tag-file)
            (when (member filename (tags-table-files))
              (setq build-cmd (cdr (assoc tag-file my-auto-update-tags-alist)))
              (when build-cmd
                (call-process build-cmd nil 0))))
          tags-table-computed-list)))

(add-hook 'after-save-hook 'my-auto-update-tags)

It will only work (did I mention it's untested?) on files that are in TAGS files already. If you add a new file you'd have to regenerate the TAGS file the first time yourself. The call-process part should work asynchronously, so it might be a few moments until the TAGS file is actually rebuilt (if this even works ;)

Amur answered 14/2, 2009 at 12:53 Comment(1)
Would you make an effort to test it?Metameric
D
1

Install find-and-ctags (https://github.com/redguardtoo/find-and-ctags), then insert below code into ~/.emacs,

(defun my-setup-develop-environment ()
  (interactive)

  ;; you can use `find-and-ctags-current-full-filename-match-pattern-p' instead
  (when (find-and-ctags-current-path-match-pattern-p "/MYPROJ")
    (setq-local tags-table-list
                (list (find-and-ctags-run-ctags-if-needed "~/workspace/MYPROJ" ; project directory
               '(("-not -size +64k" "--exclude=*.min.js") ; (find-opts ctags-opts)
                                                            ;; you may add more find-opts ctags-opts pair HERE to run find&ctags again to APPEND to same TAGS file
                                                            ;; ctags-opts must contain "-a" to append
                                                            ;; (find-opts "-a")
                                                            )))))

  ;; for other projects
  ;; insert NEW `when' statements here
  )
(add-hook 'prog-mode-hook 'my-setup-develop-environment) ; prog-mode require emacs24+
(add-hook 'lua-mode-hook 'my-setup-develop-environment) ; lua-mode does NOT inherit from prog-mode

;; OPTIONAL
(add-hook 'after-save-hook 'find-and-ctags-auto-update-tags)

It works on windows, all you need is replace "~/workspace/MYPROJ" with "C:/workspace/MYPROJ". CTags executable could be any version, because produced TAGS contains only relative path.

Davao answered 29/6, 2016 at 10:5 Comment(2)
This is somewhat similar to my approach, I think. Are you forcibly replacing the existing TAGS file each time? If so, you can make it better by comparing the old and new TAGS file after generation, and only clobbering it if they differ, so that Emacs won't see a change. Furthermore you can decide whether to bother generating tags by running an initial find using the same criteria but also -newer than the current TAGS file. If there is no newer file, don't do anything. I pipe the -newer command through head -1 so that it aborts as soon as it finds a single matching file.Niccolite
Yes, I forcibly change TAGS every time. My project is web frontend project. "-newer" is a good idea. I will definitely try it. Could you show me some code sample?Davao

© 2022 - 2024 — McMap. All rights reserved.