xolox / vim-easytags

Automated tag file generation and syntax highlighting of tags in Vim
http://peterodding.com/code/vim/easytags/
1.01k stars 109 forks source link

easytags.vim 2.4.11: Vim(let):E713: Cannot use empty key for Dictionary #16

Closed zhaocai closed 13 years ago

zhaocai commented 13 years ago

Can anyone help for the following issue? Thanks. Error Message: easytags.vim 2.4.11: Vim(let):E713: Cannot use empty key for Dictionary (at function xolox#easytags#autoload..xolox#easytags#update..103_filter_merge_tags..103_find_tagged_files..103_canonicalize, line 5)

Configuration:

set tags=./tags;,$HOME/.vim/vimtags let g:easytags_always_enabled = 1 let g:easytags_file = '~/.vim/vimtags/easytags' let g:easytags_dynamic_files = 1 let g:easytags_by_filetype = "~/.vim/vimtags/" let g:easytags_auto_highlight = 1

if has("autocmd") autocmd FileType cpp,python,java let g:easytags_include_members = 1 endif

" If you like one of the existing styles you can link them: highlight link cMember Special

" You can also define your own style if you want: highlight cMember gui=italic

" set this if you use symlinks let g:easytags_resolve_links = 1

xolox commented 13 years ago

I think the error happens because the plug-in is trying to read a corrupt tags file. If you can reproduce the issue, please execute the Vim command :call confirm(string(tagfiles())) in the same buffer where you got the error. This will pop up a list of the tags files that the plug-in is trying to read. Are there any non-expected entries in the list? Maybe the plug-in is trying to read something which is not actually a tags file (that could definitely cause an error such as the one you're seeing). Anyway, I will probably update the plug-in to just ignore invalid entries; it shouldn't error out like this.

zhaocai commented 13 years ago

I think I find the problem. ctags somehow cannot generate tags for my .vimrc file now. it produces something like this:

$ cat tags !_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ !_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ !_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ !_TAG_PROGRAM_NAME Exuberant Ctags // !_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ !_TAG_PROGRAM_VERSION 5.8 //

zhaocai commented 13 years ago

By the way, I am trying to read the Error Message: easytags.vim 2.4.11: Vim(let):E713: Cannot use empty key for Dictionary (at function xolox#easytags#autoload..xolox#easytags#update..103_filter_merge_tags..103_find_tagged_files..103_canonicalize, line 5)

Does it mean that the error happens at line 5 in function canonicalize and backtracked to xolox#easytags#autoload. If that is right, I cannot understand the error because function canonicalize is just about file names.

zhaocai commented 13 years ago

I have to add --language-force=vim option for ctags to generate tags for the .vimrc. How can I configure this.

xolox commented 13 years ago

By the way, I am trying to read the Error Message

The error message starts on the left with the function at the bottom of the call stack and ends at the right with the function in which the actual error was encountered:

The output of Exuberant Ctags is parsed from xolox#easytags#update() and apparently the result in your case contains one or more lines which are not headers (the lines that start with !_TAG_) and also don't contain a filename.

I have to add --language-force=vim option for ctags to generate tags for the .vimrc. How can I configure this.

The plug-in should be doing this automatically already, given your configuration (see the function s:prep_cmdline() if you're interested). Please open your .vimrc and execute the Vim command :verbose UpdateTags. This will print the command line that's executed in the background. If the command line disappears you can use the :messages command to view the message history.

zhaocai commented 13 years ago

Thanks for your help. :)

  1. :verbose UpdateTags

    easytags.vim 2.4.11: Executing ctags --fields=+l --c-kinds=+p --c++-kinds=+p --sort=no -f- '--language-force=vim' '/Volumes/Users/zhaocai/Developer/Vim/vimrc'. not found in 'runtimepath': "autoload/xolox/shell.vim" easytags.vim 2.4.11: Vim(let):E713: Cannot use empty key for Dictionary (at function xolox#easytags#update..105_filter_merge_tags..105_find_tagged_files..105_canonicalize, line 5) easytags.vim 2.4.11: Vim(let):E713: Cannot use empty key for Dictionary (at function xolox#easytags#autoload..xolox#easytags#update..105_filter_merge_tags..105_find_tagged_files..105_canonicalize, line 5)

Does 'not found in 'runtimepath': "autoload/xolox/shell.vim" ' tell anything to help?

  1. I tried to type in the terminal. ctags --fields=+l --c-kinds=+p --c++-kinds=+p --sort=no -f- '--language-force=vim' '/Volumes/Users/zhaocai/Developer/Vim/vimrc'

It seems the tags generated are correct.

zhaocai commented 13 years ago

I nailed down the problem to the following key mapping:

I just need to comment out this line, nnoremap z/ :if g:AutoHighlightToggle()set hlsendif

any idea about this problem? Thanks for your help!


http://vim.wikia.com/wiki/Auto_highlight_current_word_when_idle " Highlight all instances of word under cursor, when idle. " Useful when studying strange source code. " Type z/ to toggle highlighting on/off. nnoremap z/ :if g:AutoHighlightToggle()set hlsendif function! g:AutoHighlightToggle() let @/ = '' if exists('#auto_highlight') au! auto_highlight augroup! auto_highlight setl updatetime=2000 echo 'Highlight current word: off' return 0 else augroup auto_highlight au! au CursorHold * let @/ = '\V<'.escape(expand(''), '\').'>' augroup end setl updatetime=300 echo 'Highlight current word: ON' return 1 endif endfunction

zhaocai commented 13 years ago

One more thing, I notice easy tag use --sort=no option to generate ctags. why is that? I ask because (1) sort should be good for searching, especially for large tag data (2) sometimes, vim shows up message about unsorted tags error.

xolox commented 13 years ago

I nailed down the problem to the following key mapping:

I just need to comment out this line, nnoremap z/ :if g:AutoHighlightToggle()set hlsendif

any idea about this problem? Thanks for your help!

The s:AutoHighlightToggle() function you're using works by setting a very low 'updatetime' value so that the CursorHold automatic command updates the highlighting in real time (as you type). I have a mapping like this as well and although the functionality is nice it has some nasty consequences:

The easytags plug-in also uses the CursorHold automatic command: Every time the automatic command fires the plug-in checks for changes and runs Exuberant Ctags. The 'updatetime' option is global so when s:AutoHighlightToggle() lowers it to 400 milliseconds this means the easytags plug-in will also be called every 0,4 second...

I'm not sure if there is a sane way to fix this. What I can do is add a check to easytags so that if the 'updatetime' is very low, it will give a warning and temporarily disable execution.

One more thing, I notice easy tag use --sort=no option to generate ctags. why is that?

The easytags plug-in updates your tags files like this:

To answer your question: The easytags plug-in uses --sort=no as a minor performance optimization. Because the plug-in has to combine the old/new tags there's no point in having Exuberant Ctags sort its output (because to combine the old/new tags everything has to be sorted at once).

I ask because (1) sort should be good for searching, especially for large tag data (2) sometimes, vim shows up message about unsorted tags error.

  1. Whenever the easytags plug-in writes a tags file to disk it sorts everything so that Vim can use binary search to process tags files;
  2. I've gotten the same error occasionally but haven't been able to reliably reproduce it. If you find a combination of a tags file, input file and Exuberant Ctags command line that always produces this problem please contact me.

I suspect that the unsorted tags error only happens when Vim tries to read the tags file while its being written. In this case I may be able to fix this problem permanently by writing a new tags file to ~/.vim/tags/filetype.tmp and renaming it to ~/.vim/tags/filetype when done.

xolox commented 13 years ago

Just now I committed three changes based on your feedback (thanks for that!). If you're satisfied with these changes, please close this issue, otherwise maybe you have suggestions?

zhaocai commented 13 years ago

Thanks for the updates. I just tried it out. It works great except 1 problem: The g:easytags_by_filetype option does not work correctly.

My Settings: set tags=./tags; set tagrelative let g:easytags_always_enabled = 1 let g:easytags_file = "~/.vim/vimtags/easytags" let g:easytags_dynamic_files = 1 let g:easytags_by_filetype = "~/.vim/vimtags/ft" Problem details: file 'tags' is generated in the location of the editing file instead of merging into the &filetype based tag file.

I tried to debug it, but I can get it fixed in an hour. I am sure you can figure it out much quicker than I do.

and I found a small typo to fix: diff --git a/autoload/xolox/easytags.vim b/autoload/xolox/easytags.vim index 7f4c169..ed3b78a 100644 --- a/autoload/xolox/easytags.vim +++ b/autoload/xolox/easytags.vim @@ -624,7 +624,6 @@ function! s:canonicalize(filename) " {{{2 let canonical = s:resolve(fnamemodify(a:filename, ':p')) let s:cached_filenames[a:filename] = canonical return canonical

On Sep 4, 2011, at 8:03 AM, xolox wrote:

Just now I committed three changes based on your feedback (thanks for that!). If you're satisfied with these changes, please close this issue, otherwise maybe you have suggestions?

Reply to this email directly or view it on GitHub: https://github.com/xolox/vim-easytags/issues/16#issuecomment-1991001

xolox commented 13 years ago

Thanks for the updates. I just tried it out. It works great except 1 problem: The g:easytags_by_filetype option does not work correctly. The file 'tags' is generated in the location of the editing file instead of merging into the &filetype based tag file.

Sorry about that, it was an unrelated change (see issue #15) that was not backwards compatible and maybe a bit of a surprise. In the commit above (fae8ddd) I've restored the former behavior when g:easytags_dynamic_files is 1. I hope it works okay now :-)

zhaocai commented 13 years ago

It works well now. Thanks for the update :)

zhaocai commented 13 years ago

One more question about the performance of easytags. I have a kernel project which generates tags of about 10M size. I have eliminated all possible events as the following config. let g:easytags_always_enabled = 0 let g:easytags_on_cursorhold = 0 let g:easytags_events = ['BufWritePost'] But, still I experienced few seconds delay every time I save a file.

I noticed that you have the vim-shell plugin which can run cmd in the background. But it does not help this situation.

My guess is, if I do not want to get instant highlight update, the other work to update tags should be all done in the background and return to the UI without noticeable delay.

On Sep 5, 2011, at 2:59 PM, xolox wrote:

Thanks for the updates. I just tried it out. It works great except 1 problem: The g:easytags_by_filetype option does not work correctly. The file 'tags' is generated in the location of the editing file instead of merging into the &filetype based tag file.

Sorry about that, it was an unrelated change (see issue #15) that was not backwards compatible and maybe a bit of a surprise. In the commit above (fae8ddd) I've restored the former behavior when g:easytags_dynamic_files is 1. I hope it works okay now :-)

Reply to this email directly or view it on GitHub: https://github.com/xolox/vim-easytags/issues/16#issuecomment-2005578

xolox commented 12 years ago

The plug-in is slowing Vim down in your case because every time you save a file the plug-in updates the tags file, in effect reading+filtering+sorting+writing the whole 10 MB every time... Right now my plug-in doesn't have a good way to deal with this problem and solving it is kind of tricky. There are two basic options:

If the first option is not useful to you and you're okay with compiling a binary that wraps Exuberant Ctags, I may decide to publish the wrapper code (even though it's still kind of a mess). I hope this helps!

zhaocai commented 12 years ago

Hi Peter

I got another solution for this performance issue: using remote server to update tags.

Basically, a new vim window is opened to do the work asynchronously. This will update the tags without blocking current vim window. Part of the code snippets are attached for your reference.


.vimrc

let g:easytags_servername = "EASYTAGSREMOTE" let g:easytags_server_rc = "~/.vimrc_easytags"

let g:easytags_update_interval = 60 ":TODO: Sun Sep 11, 2011 12:48PM, zhaocai " better solution is to peek server busy/free status

if v:servername != g:easytags_servername for s:eventname in g:easytags_events execute 'autocmd' s:eventname '* call g:EasyTagsRemoteUpdate(' string(s:eventname) ')' endfor endif


.func

func! g:EasyTagsRemoteUpdate(event) " filetype check {{{5 if index(xolox#easytags#supported_filetypes(), &ft) < 0 return 0 endif

" first run: open server                                              {{{5
if !remote#exists_server(g:easytags_servername)
    call remote#open_remoteserver(g:easytags_servername,g:easytags_server_rc)
    let l:try_nr = 100
    while l:try_nr > 0
        try
            call remote_send(g:easytags_servername, ":colorscheme solarized<CR>")
            call remote_send(g:easytags_servername, ":let &titlestring= \"" . g:easytags_servername .  "\"<CR>")
            call remote_send(g:easytags_servername, ":set autoread<CR>")
            break
        catch /^Vim\%((\a\+)\)\=:E241/
            sleep 200m
        endtry
        let l:try_nr = l:try_nr - 1
    endwhile
endif
" first run: create local timer                                       {{{5
if !exists("g:last_easytags_update_time")
    let g:last_easytags_update_time = localtime() - g:easytags_update_interval - 1
endif

" call remote server                                                  {{{5
if (localtime() - g:last_easytags_update_time) > g:easytags_update_interval
    call remote_send(g:easytags_servername, ":view " . expand("%:p") . "<CR>")
    call remote_send(g:easytags_servername, ":UpdateTags<CR>")
    let g:last_easytags_update_time = localtime()
endif

endf

On Sep 15, 2011, at 5:22 PM, Peter Odding wrote:

The plug-in is slowing Vim down in your case because every time you save a file the plug-in updates the tags file, in effect reading+filtering+sorting+writing the whole 10 MB every time... Right now my plug-in doesn't have a good way to deal with this problem and solving it is kind of tricky. There are two basic options:

  • Use the support for dynamic tags files to create tags files for all or selected subdirectories of your kernel tree. Now you won't have highlighting for all kernel functions in every file (a disadvantage) but because the tags are distributed over a set of tags files the plug-in should update tags much faster.
  • I have a private branch of the easytags repository that contains an executable that wraps Exuberant Ctags and performs tags file updating outside of Vim. The code basically works but it has to be compiled with a C compiler and I'm not sure I'm up to distributing binaries of this program to users of the easytags plug-in (binaries are complicated to support). Also this wrapper introduces a new layer of complexity while the easytags plug-in is already very complex (too complex in fact, it's become hard to extend and refactor).

If the first option is not useful to you and you're okay with compiling a binary that wraps Exuberant Ctags, I may decide to publish the wrapper code (even though it's still kind of a mess). I hope this helps!

Reply to this email directly or view it on GitHub: https://github.com/xolox/vim-easytags/issues/16#issuecomment-2109377