redguardtoo / counsel-etags

Fast, energy-saving, and powerful code navigation solution
174 stars 15 forks source link

counsel-etag does not update TAGS file #45

Closed nils-schween closed 5 years ago

nils-schween commented 5 years ago

Hello everyone,

I would love to use counsel-etags to regularly tag my cplusplus files. I tried to make it work for a small example and I failed. First of my counsel-etags settings

(use-package counsel-etags
  :ensure t
  :init
  ;; (eval-when-compile
    ;; Silence missing function warnings
    ;; (declare-function counsel-etags-virtual-update-tags "counsel-etags.el")
    ;; (declare-function counsel-etags-guess-program "counsel-etags.el")
    ;; (declare-function counsel-etags-locate-tags-file "counsel-etags.el"))
  :bind (
         ("M-." . counsel-etags-find-tag-at-point)
         ("M-t" . counsel-etags-grep-symbol-at-point)
         ("M-s" . counsel-etags-find-tag))
  :config
  ;; Ignore files above 800kb
  (setq counsel-etags-max-file-size 800)
  ;; Ignore build directories for tagging
  (add-to-list 'counsel-etags-ignore-directories '"build*")
  (add-to-list 'counsel-etags-ignore-directories '".vscode")
  (add-to-list 'counsel-etags-ignore-filenames '".clang-format")
  ;; Don't ask before rereading the TAGS files if they have changed
  (setq tags-revert-without-query t)
  ;; Don't warn when TAGS files are large
  (setq large-file-warning-threshold nil)
  ;; How many seconds to wait before rerunning tags for auto-update
  (setq counsel-etags-update-interval 10)
  ;; Setup auto update now
  (add-hook 'prog-mode-hook 
            (lambda ()
              (add-hook 'after-save-hook
                        'counsel-etags-virtual-update-tags 'append 'local)))
  )

Then I created a folder test_cpp and a file test_cpp.cpp. Furthermore I issued the command touch TAGS inside this folder.

Then I began to forward declare some functions before the main function. I jumped to the end of my file and implemented the actual definition of these functions. My code looks like this

#include <iostream>

int add( int , int ); 
int substract (int, int );
int multiplication (int , int);
double division(int , int);

int main()    
{

  std::cout << "This is substraction:" << "\n";
  std::cout << substract(5, 4) << "\n";

  std::cout << add(4,5) << "\n";
  std::cout << multiplication(5, 4) << "\n";
  std::cout << division(5,4);

  return 0;
}

int add (int x, int y ){
  return x+y;
}

int substract (int x, int y){
  return x-y;
}

int multiplication(int x, int y) {
  return x*y;
}

double division(int x, int y){
  return x/y;
}

Since a TAGS file existed and the update interval was set to 10, I expected the TAGS file to be updated every 10 seconds and every time I saved the code file. But the TAGS file does not change at all. Am I doing something wrong?

Thank you for your help, Nils

redguardtoo commented 5 years ago

syntax error in your code. Delete your ignore pattern setup. Do as my step by step guide at least once.

nils-schween commented 5 years ago

Thank you for your fast answer and I am sorry. I had copied the setup and did not recognize the difference to your readme.md.

I did as you said, I commented out the ignore pattern and I ran your step-by-step example. It works for the fn() function and the printf() function. But if a add another function to it, it will not be stored in the TAGS file. No matter how long I wait, or how often I save the hello.c file.

redguardtoo commented 5 years ago

I tested latest version. It's working.

Try start from this setup.

(setq counsel-etags-update-interval 10)
(add-hook 'prog-mode-hook
  (lambda ()
    (add-hook 'after-save-hook
              'counsel-etags-virtual-update-tags 'append 'local)))

Just use it, don't try to optimize further.

nils-schween commented 5 years ago

Hi @redguardtoo, I did as you said and reduced my counsel-etags' setup to the proposed minimun. It still did not work. I decided to track down the error and it took me a while, but I figured out, that it is related to use of use-package. To demonstrate this, I post a preliminary first and working setup:

(use-package counsel-etags
  :ensure t
  :bind (("M-." . counsel-etags-find-tag-at-point)
            ("M-t" . counsel-etags-grep-symbol-at-point)
            ("M-s" . counsel-etags-find-tag))
  :init
  (add-hook 'prog-mode-hook
        (lambda ()
          (add-hook 'after-save-hook
            'counsel-etags-virtual-update-tags 'append 'local)))
  :config
  ;; Ignore files above 800kb
  ;; (setq counsel-etags-max-file-size 800)
  ;; Don't ask before rereading the TAGS files if they have changed
  (setq tags-revert-without-query t)
  ;; Don't warn when TAGS files are large
  (setq large-file-warning-threshold nil)
  ;; How many seconds to wait before rerunning tags for auto-update
  (setq counsel-etags-update-interval 10)

  ;; ignored files and directories
  (add-to-list 'counsel-etags-ignore-directories "build")
  (add-to-list 'counsel-etags-ignore-directories ".vscode")
  (add-to-list 'counsel-etags-ignore-filenames ".clang-format")
  )

use-package makes a difference between code executed before a package is loaded ( everything after the :init keyword) and code which is executed after a package is loaded ( everything after the :config keyword). If the add-hook function with argument prog-mode-hook is executed after the package counsel-etags is loaded, it does not work as intended. Thus, the add-hook function has to transferred into the :init part of the use-package configuration.

I looked through the documentation of use-package and found an even more elegant way to execute the hook:

(use-package counsel-etags
  :ensure t
  :hook (prog-mode . (lambda ()
               (add-hook 'after-save-hook
                 'counsel-etags-virtual-update-tags 'append 'local)))
  :bind (("M-." . counsel-etags-find-tag-at-point)
         ("M-t" . counsel-etags-grep-symbol-at-point)
         ("M-s" . counsel-etags-find-tag))
  :config
  ;; Ignore files above 800kb
  ;; (setq counsel-etags-max-file-size 800)

  ;; Don't ask before rereading the TAGS files if they have changed
  (setq tags-revert-without-query t)
  ;; Don't warn when TAGS files are large
  (setq large-file-warning-threshold nil)
  ;; How many seconds to wait before rerunning tags for auto-update
  (setq counsel-etags-update-interval 10)
  ;; Ignore build directories for tagging
  (add-to-list 'counsel-etags-ignore-directories "build")
  (add-to-list 'counsel-etags-ignore-directories ".vscode")
  (add-to-list 'counsel-etags-ignore-filenames ".clang-format")

  )

I don't know how the keyword :hook is implemented, but since it was done by jwiegley, it's probably the way to go.

@redguardtoo could you imagine to copy the last code snippet into your readme.md ? It would be perfect for everyone who uses use-package to find it under the heading "Installation".

One more thing: It would be create to mention, that a TAGS file has to be created manually in the root folder and that the automatic update process starts after the first call of counsel-etags-find-tag.

Thank you very much for your help!

redguardtoo commented 5 years ago

Sure. Actually, you first setup is better. It ensures the add-hook code is executed only once when prog-mode is loaded.

nils-schween commented 5 years ago

@redguardtoo: thanks a lot! I close the issue.