18
votes

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?

7

7 Answers

10
votes

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

10
votes

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.

4
votes

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.

2
votes

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/

2
votes

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

1
votes

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 ;)

1
votes

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.