Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Request] Add preview of tag #16

Open
faisal-shah opened this issue Apr 26, 2021 · 5 comments
Open

[Request] Add preview of tag #16

faisal-shah opened this issue Apr 26, 2021 · 5 comments

Comments

@faisal-shah
Copy link

Similar to the fzf :Tags command, can you add a preview of the file positioned on the tag definition?

I'm thinking you can call fzf#run with fzf#vim#with_preview({ "placeholder": "--tag {2}:{-1}:{3}" } similar to what :Tags does. But the source lines need to have the tagfile path in addition to what you already construct.

@faisal-shah
Copy link
Author

faisal-shah commented Apr 26, 2021

I made these simple changes, and it half way works. The preview window shows up with the file, and it is centered on the search result of the Ex command. However, the Ex command getting passed to the script is messed up. It only gets the first part of the Ex command until there is a space. So, there is some formatting/escaping required here somewhere - which is beyond me at the moment.

Also, I'm just using tagfiles()[0] for now - don't know enough to properly handle the general case. Hope this helps spur you on :)

@@ -44,6 +44,7 @@ function! fzf_tags#Find(identifier)
           \ 'options': '--expect=' . expect_keys . ' --ansi --no-sort --tiebreak index --prompt "' . s:fzf_tags_prompt . '\"' . identifier . '\" > "',
           \ }
     let final_run_spec = extend(run_spec, s:fzf_layout)
+    let final_run_spec = extend(final_run_spec, fzf#vim#with_preview({ "placeholder": "--tag {2}:{-1}:{3}" }))
     call fzf#run(final_run_spec)
   endif
 endfunction
@@ -66,7 +67,7 @@ function! s:source_lines(identifier)
   \   taglist('^' . a:identifier . '$', expand('%:p')),
   \   function('s:tag_to_string')
   \ )
-  return map(s:align_lists(relevant_fields), 'join(v:val, " ")')
+  return map(s:align_lists(relevant_fields), 'join(v:val, "\t")')
 endfunction
 
 function! s:tag_to_string(index, tag_dict)
@@ -78,8 +79,9 @@ function! s:tag_to_string(index, tag_dict)
     call add(components, s:green(a:tag_dict['class']))
   endif
   if has_key(a:tag_dict, 'cmd')
-    call add(components, s:red(a:tag_dict['cmd']))
+    call add(components, s:red(a:tag_dict['cmd'] . ";\""))
   endif
+  call add(components, tagfiles()[0])
   return components
 endfunction

@faisal-shah
Copy link
Author

If I modify tagpreview.sh (in .fzf/bin) with the proper EXCMD, it works! I printed out the value of EXCMD in the shell script and sure enough it is truncated at the first space character in the ex cmd argument. I tried escaping with , to no avail ..

@zackhsi
Copy link
Owner

zackhsi commented May 2, 2021

I'd love the preview feature!

One aspect of the design is that it needs to be easily toggle-able such that the user can clearly see the full list of tags as well as their full definitions.

@faisal-shah
Copy link
Author

faisal-shah commented May 3, 2021

Ok, so I've got a minimal example working - but with some issues that stem from reusing fzf's preview.sh and tagpreview.sh (called from preview.sh):

  1. The excmd which shows the definition has to be the last field in source_lines. This is because of FZF's field index expression not implementing escape characters. The excmd can potentially have all sorts of characters in there, and there is no guarantee that the field index expression (the thing which pulls arguments out of the FZF command line using {1} {2} and so on) delimiter will not show up. The way around this is to identify the field index of the start of the excmd and specify to use that field all the way to the end of line - which is the {3..} you see in the vimscript.
  2. Since the exmcd has to be the last field, the filename path has to come before it - so the full definition is not as clear to view. The path could be quite long, which could result in the definition not being as easy to see in the list. However, now that we have a preview - that's less of a problem ya?!
  3. tagpreview.sh expects to be passed in the filename, tagfile, and excmd:
echo "usage: $0 FILENAME:TAGFILE:EXCMD"

The filename that I'm passing in below is a path that will get you to the relevant file. It could be relative or absolute, depending on the location of the tag file. If the tag file is above the working directory I noticed taglist() returns an absolute path. If the tag file is at the same level or below the working directory taglist() returns a relative path. I've tried this with multiple tag files at various places in the filesystem hierarchy... So, it seems that we need to add an option to tagpreview.sh to not muck around with file paths and to use them as is.

function! s:test_sink(identifier, selection) abort
    let l:count = split(a:selection)[0]
    execute l:count . 'tag' a:identifier
endfunction

function! s:test() abort
    let source_lines = []
    let identifier = expand('<cword>')
    let tagresults = taglist(identifier)
    let idx = 1
    for tr in tagresults
        call add(source_lines, idx . "\t" . tr['filename'] . "\t" . tr['cmd'])
        let idx = idx + 1
    endfor
    call fzf#run(fzf#wrap(fzf#vim#with_preview({
                \ 'source': source_lines,
                \ 'sink': funcref('s:test_sink', [identifier]),
                \ "placeholder": "--tag {2}:{3..}",
                \ 'window': {'height': 0.9, 'width': 0.9},
                \ 'options': ["--delimiter", "\t"],
                \ })))
endfunction
command! TestTagJump call s:test()
diff --git i/bin/tagpreview.sh w/bin/tagpreview.sh
index e07f87d..c4c1253 100755
--- i/bin/tagpreview.sh
+++ w/bin/tagpreview.sh
@@ -8,12 +8,7 @@ if [ -z "$1" ]; then
   exit 1
 fi
 
-IFS=':' read -r FILE TAGFILE EXCMD <<< "$*"
-
-# Complete file paths which are relative to the given tag file
-if [ "${FILE:0:1}" != "/" ]; then
-  FILE="$(dirname "${TAGFILE}")/${FILE}"
-fi
+IFS=':' read -r FILE EXCMD <<< "$*"
 
 if [ ! -r "$FILE" ]; then
   echo "File not found ${FILE}"

@faisal-shah
Copy link
Author

If merged, that fzf.vim PR should open the way for fzf-tags to implement the preview ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants