8

TLDR: I've got a large tags file that loads multiple times per session, making it unusable. Can't find the source of issue or how to disable it -- main goal is to jump to tags, but completion would be nice

I recently posted on the emacs subreddit and a user recommended that I join this group because it's also friendly towards newbies.

I've been using emacs as a C++ IDE, and I'm slowly correcting things that are annoying. I'm essentially using redguardtoo's emacs.d file.

I have a tag file that is 225MB (1.6M Tags). My intent for the tag is not necessarily completion (using company), but more for jumping around source code. I'm working with an unfamiliar code base and often need to see macro or class definitions.

When I start typing, at random times, I'll see a message in the minibuffer

Making tag completion table for [tag file]...0-100%

Then, a popup listbox shows up with autocompletion options.

Because this tag file is so large, and it doesn't seem like the tag loading is asynchronous, it freezes emacs for around a minute. This also happens multiple times per a session (with the same file, and with other files in the same directory that use the same tag file)!


Questions

  1. Does anyone know what's initializing the loading of the tag table for completion and how to disable it? I did a grep on my emacs.d directory for "Making tag completion" and found nothing (note, IIRC the loading tags was present regardless of using company or auto-complete
  2. Completion would be nice, but I'd settle just for the ability to jump to the tag location. Is there a way to get this?
  3. What is the mindset to take when approaching problems like this? I'd like to be able to troubleshoot further on my own next time.

Additional info

Enabled minor modes (C-h m)

Enabled minor modes: Abbrev Auto-Composition Auto-Compression
Auto-Encryption Blink-Cursor Column-Number Company Desktop-Save
Display-Time Electric-Indent Electric-Pair Evil Evil-Local
Evil-Matchit Evil-Surround Fic File-Name-Shadow Flyspell-Lazy
Font-Lock Ggtags Global-Auto-Revert Global-Company Global-Eldoc
Global-Evil-Matchit Global-Evil-Surround Global-Font-Lock Global-Linum
Global-Page-Break-Lines Global-Pointback Global-Undo-Tree Helm
Helm-Match-Plugin Helm-Occur-Match-Plugin Line-Number Linum Menu-Bar
Mouse-Wheel Override-Global Pointback Recentf Savehist Shell-Dirtrack
Subword Tooltip Undo-Tree Which-Function Window-Numbering Winner Yas
Yas-Global

package-activated-list is equal to

(ace-jump-mode ag s dash anaconda-mode f dash s dash json-rpc auto-compile packed bbdb bookmark+ browse-kill-ring buffer-move clean-aindent-mode cmake-mode coffee-mode color-theme company cpputils-cmake crontab-mode csharp-mode diminish dired+ dired-details dropdown-list dsvn elnode kv db kv fakir kv dash noflet creole kv noflet s noflet dash web s dash emmet-mode erlang evil-args evil goto-chg undo-tree evil-search-highlight-persist exec-path-from-shell expand-region f dash s fakir kv dash noflet fancy-narrow flymake-coffee flymake-easy flymake-css flymake-easy flymake-haml flymake-easy flymake-jslint flymake-easy flymake-lua flymake-python-pyflakes flymake-easy flymake-ruby flymake-easy flymake-sass flymake-easy flymake-shell flymake-easy flyspell-lazy fringe-helper ggtags git-gutter git-timemachine gitconfig-mode gitignore-mode goto-chg haskell-mode helm-descbinds helm async helm-gtags helm async hl-sexp htmlize ibuffer-vc idomenu iedit json-mode json-snatcher json-reformat json-reformat json-rpc json-snatcher kv legalese less-css-mode lua-mode magit git-rebase-mode git-commit-mode markdown-mode maxframe mic-paren move-text multi-term mwe-log-commands noflet org-fstree packed page-break-lines paredit pointback pomodoro pretty-mode project-local-variables quack rainbow-delimiters regex-tool rinari jump inflections findr ruby-compilation inf-ruby inf-ruby robe inf-ruby ruby-compilation inf-ruby rvm sass-mode haml-mode scratch scss-mode session sr-speedbar string-edit dash switch-window tagedit dash s textile-mode undo-tree unfill w3m web s dash wgrep ws-butler yaml-mode yasnippet
  • 1
    For jumping to definition/references, you can use GNU Global with ggtags/helm-gtags. Guarantee to work on large project like Linux kernel without any delay. You may want to look at my C/C++ guide. I covered code navigation (jump to definition/references), code completion, compiling and debugging support. I already created a demo configuration for playing with, so you only need to walk through the features without configuring anything. – Tu Do Oct 31 '14 at 15:55
  • Your guides were the ones that got me started with emacs (especially w/ C++)! Our build system is very complicated and #include "..." can live in various places that are not known until build time. So, ggtags wouldn't be able to generate tags for many of the files. Currently, our build tools allow us to make etags to generate emacs compatible tags, but there is no make ggtags equivalent. So, I'm stuck with etags for now. Any ideas? – cheezy Oct 31 '14 at 16:20
  • Hmm I see. The situation is more complicated now. You mentioned ggtags cannot generate tags, but did you use plain gtags on the command line at project root? You should try this and invoke ggtags again. There should not be make ggtags because the real command is gtags; ggtags is just a package name of Emacs that use it. Another option is that you can use ctags; ggtags can also recognize ctags tags and it's also fast. You can generate ctags tags when invoking ggtags-create-tags and it asks for using ctags client. – Tu Do Oct 31 '14 at 16:42
  • Anyway, if gtags could not know about such details, I don't think the built-in etags (comes with Emacs), or ctags (I linked above) would be able to do it. I think you only use ggtags to create tags at current directory, not project root. Run the command gtags at project root, or when ggtags asks for where to generate, navigate to project root and you will be fine. – Tu Do Oct 31 '14 at 16:49
  • I verified your statement (all the tag programs can only generate from project root down the tree). make etags works because it calls etags once it evaluates where all the .h files live. – cheezy Oct 31 '14 at 17:44
2

For your use case, there's still hope though. Since you use etags, it can be used with helm-etags-select, the Helm built-in command. To use it, simply follow theses steps:

  • First, run the command to generate TAGS file.
  • Second, use find-tag to feed it to Emacs; if the TAGS file is too large and Emacs asks you to confirm, just accept it. Your whole TAGS file will be loaded in Emacs and there's no more reloading.
  • Finally, just execute helm-etags-select on any symbol on your Emacs. If there exists only one definition in your project, jump instantly; otherwise, display a Helm buffer for you to choose from.

For completion, since you have a large tag database, you would not want to use auto-complete or company popup because it would freeze your Emacs. In that case, you can use helm-company; it replaces company popup with Helm buffer. You can simply add it to your c-mode-hook or c++-mode-hook:

(defun helm-company-setup ()
   (local-set-key (kbd "C-i") 'helm-company)
   (local-set-key (kbd "<tab>") 'helm-company))

(add-hook 'c-mode-hook 'helm-company-setup)
(add-hook 'c++-mode-hook 'helm-company-setup)
  • 2
    it worked well! using helm and disabling the tags backend for company significantly improved performance. Your guide on helm switched me over from ido btw! – cheezy Nov 5 '14 at 4:54
  • Great to hear that :) – Tu Do Nov 5 '14 at 5:02
  • 1
    @Dmitry well when you have thousands of candidates need listing, then it blocks Emacs. – Tu Do Nov 23 '14 at 5:03
  • 1
    @TuDo That's not a good explanation. While fetching so many candidates may take some time, displaying them (and navigating the list, searching, etc) is very snappy even with 8000 items. I just don't have a project/backend combination that would return more, to test. – Dmitry Nov 23 '14 at 15:18
  • 1
    Update: 30000 is also snappy, the only perceptible delay happens before the popup opens. – Dmitry Nov 23 '14 at 23:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.