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

With split windows jump to tag definition goes to other window #794

Open
SerSamgy opened this issue Oct 23, 2021 · 16 comments
Open

With split windows jump to tag definition goes to other window #794

SerSamgy opened this issue Oct 23, 2021 · 16 comments

Comments

@SerSamgy
Copy link

Steps to reproduce:

  • open a file;
  • open another file in vertical split to the right;
  • return to left split window;
  • open Tagbar;
  • choose tag to jump;
  • hit ''

Expected behaviour:
Cursor on chosen tag in left split window.

Real behaviour:
Cursor on random line in right split window.

Tagbar settings:
let g:tagbar_autofocus = 1
let g:tagbar_autoclose = 1
let g:tagbar_sort = 0
let g:tagbar_case_insensitive = 1
let g:tagbar_autoshowtag = 1
let g:tagbar_position = 'rightbelow vertical' " Same behaviour with other positions

Prerequisites:
Fedora 34 x64, NVIM v0.5.1, Universal Ctags 5.9.0(p5.9.20211017.0) with optional compiled features: +wildcards, +regex, +gnulib_regex, +iconv, +option-directory, +xpath, +json, +interactive, +sandbox, +yaml, +packcc, +optscript

@raven42 raven42 added the bug label Nov 2, 2021
@raven42
Copy link
Collaborator

raven42 commented Nov 2, 2021

@SerSamgy I'm not seeing the same behavior. What version of VIM are you running? When I try this, I am getting the correct behavior as you are expecting. I've tried this with the same tagbar configuration as you have listed, and I've tried it with opening a new buffer directly with the :vsplit <file2> as well as doing just a normal :vsplit followed by opening the new file with :e <file2>

@raven42
Copy link
Collaborator

raven42 commented Nov 2, 2021

Sorry... missed that you were running nvim v0.5.1 in the initial post.

I am using vim 8.2, so not sure if that is making the difference. Might need someone who is running nvim to look at this.

Also if you can capture the tagbar logs that might be useful as well to try to root-cause the issue. You can use :TagbarDebug <logfile> to generate a log. Do this before you first load the tagbar window to make sure we get the full logs.

@jonassvedas
Copy link

I was getting a similar issue behavior but I think I narrowed down the problem.
I my case it was due to how tagbar jumps to a tag belonging to the last window that was in focus.
For example if you have 3 windows vertically split:

| left | right | tagbar |

and let's say the the left and right files are the same. Then when you move focus to the tagbar you are passing through the right window, hence tag bar will by default jump to the right window since it was the last one in focus.

A solution would be to have a shortcut that would directly get focus on the tagbar.

@CoinCheung
Copy link

Is there a shortcut to go from left split to tagbar directly?

@CoinCheung
Copy link

@raven42 I have same problem as @jonassvedas. Do you know how to jump from left to tagbar?

@raven42
Copy link
Collaborator

raven42 commented Nov 25, 2023

Ah ok. To answer these last questions, there is a way to do this with the current tagbar implementation. The :Tagbar/:TagbarOpen commands accept a flags parameter. This can be used to control the behavior of the tagbar window open functionality. The flags are discussed in the docs page, but here is the snippet just to capture it here:

:TagbarOpen [{flags}]                                            *:TagbarOpen*
    Open the Tagbar window if it is closed.

    Additional behaviour can be specified with the optional {flags} argument.
    It is a string which can contain these character flags:
    'f'   Jump to Tagbar window when opening (just as if |g:tagbar_autofocus|
          were set to 1)
    'j'   Jump to Tagbar window if already open
    'c'   Close Tagbar on tag selection (just as if |g:tagbar_autoclose| were
          set to 1, but doesn't imply 'f'), but only if the Tagbar window was
          opened using this command. If this is used the "c" flag will be
          shown in the statusline of the Tagbar window.

    For example, the following command would always jump to the Tagbar window,
    opening it first if necessary, but keep it open after selecting a tag
    (unless |g:tagbar_autoclose| is set): 
        :TagbarOpen fj

So keyboard shortcuts could be created to call the TagbarOpen command with the desired flag(s). This should definitely help the situation where a vertically split window is used for the same file. With a keyboard shortcut defined to execute :TagbarOpen fj as in the docs, then it will always focus on the tagbar window if it is open or not. Then the last window will still be the left most split and so when selecting a tag, it should use that last focused window (it does in my testing).

@SerSamgy does this accurately describe the behavior you are seeing as well for originally reporting the issue? In your case it sounded like you had two different files, so this might be a little bit different. I am still trying to help solve this original issue, just that I am unable to reproduce it given the available information.

@CoinCheung
Copy link

Hi @raven42 , thanks for answering !!

In my case I need to use tagar-toggle, rather than open. Here is the behavior that I hope a shortcut can provide:

  • when tagbar window is closeed, it opens the window and focuses to the tagbar window.

  • when tagbar window is open, and the focus is not in the tagbar window(such as in left or right splitted buffers), it will focus on the tagbar window.

  • when tagbar window is open, and the focus is in the tagbar window, it will close the tagbar window.

Is there a method to have this behavior with one shortcut?

@raven42
Copy link
Collaborator

raven42 commented Nov 26, 2023

There is no tagbar specific command that can do this, but you can have a oneliner vim command that will do this.

:if bufname('%') =~# 'Tagbar' | call tagbar#CloseWindow() | else | call tagbar#OpenWindow('fj') | endif

Or if you want to create a keymapping for this, you can add something like this to your .vimrc

nnoremap <silent> <expr> <Leader>t bufname('%') =~# 'Tagbar' ? ':call tagbar#CloseWindow()<CR>' : ':call tagbar#OpenWindow("fj")<CR>'

These commands will check if the current window name conains Tagbar and if so, call the tagbar#CloseWindow() function, else they will call the tagbar#OpenWindow() with the appropriate flags to change focus to the tagbar window.

@CoinCheung
Copy link

Hi @raven42 ,

I tried your scritp and rewrite it like this:
image

It cannot close tagbar window when the focus is on the tagbar window, and the opening strategy is correct. Is there any mistake in my script?

@raven42
Copy link
Collaborator

raven42 commented Nov 27, 2023

It looks correct. Maybe try adding a debug statement before the if statement to see what the bufname is.

echom ‘ToggleTagbar::bufname() = ‘ + bufname(‘%’)

then after hitting the key mapping a few times while focused on different windows, type

:messages

@CoinCheung
Copy link

Hi @raven42 ,

I change script like this:
image

and I open a file, and then use shortcut to open tagbar, and see the result of :messages like this:
image

By the way, I am using vim 9.0:
image

@raven42
Copy link
Collaborator

raven42 commented Nov 27, 2023

Ok looks like I'm messing up my scripting languages. Sorry about that. The proper debug is as follows:

function! ToggleTagbar()                                                                                                                                                                                                                                                                                             
    echom 'ToggleTagbar::bufname() = ' . bufname('%')                                                                                                                                                                                                                                                                
    if bufname('%') =~# 'Tagbar'                                                                                                                                                                                                                                                                                     
        call tagbar#CloseWindow()                                                                                                                                                                                                                                                                                    
    else                                                                                                                                                                                                                                                                                                             
        call tagbar#OpenWindow('fj')                                                                                                                                                                                                                                                                                 
    endif                                                                                                                                                                                                                                                                                                            
endfunction
nnoremap <silent> <Leader>t :call ToggleTagbar() <CR>

string concatenation in vimscript is with a . character, not a +.

When you try this again, if the tagbar window doesn't open with the shortcut, can you open it with :TagbarOpen fj and then make sure the focus is on the tagbar window, then hit the keymap again and capture the :messages output from that as well so we can make sure the window name detection is at least working as we expect.

With this defined in my .vimrc I am seeing the correct behavior as you've described it. The debug is showing the following for me as well. The 1st time tagbar was not open and it opened the window, the second time tagbar was the active window and it was closed.

ToggleTagbar::bufname() = /home/user/.vimrc
ToggleTagbar::bufname() = __Tagbar__.1

tagbar-toggle-function

@CoinCheung
Copy link

Hi @raven42 ,

The result is like this:
image

Seems that it use the name of my code file as bufname not tagbar. Is it something with my vimrc?
My vimrc is like this:

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => options assigned by Coin
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set wrap "Wrap lines
set breakindent " indent after line wrapped
let mapleader = ","
let g:mapleader = ","
" Height of the command bar
set cmdheight=1
set cc=80 " highlight 80th colomn
set nocompatible

set splitbelow " let splilt be located at bottom by default
autocmd VimResized * wincmd =
set termwinsize = "10x0"
set termwinscroll=40000
augroup termIgnore
    autocmd!
    autocmd TerminalOpen * set nobuflisted
    autocmd TerminalOpen * set nonu
    autocmd TerminalOpen * set clipboard=unnamedplus
    autocmd TerminalOpen * res 10
    autocmd TerminalOpen * set foldcolumn=0
   
augroup END
"" inoremap <C-m> <esc> " in vim, <C-M> equal <cr>,we cannot use <C-M>
inoremap <C-b> <esc> 
tnoremap <C-n> <C-\><C-n>

" use alt
execute "set <M-j>=\ej"
execute "set <M-k>=\ek"
tnoremap <M-j> <C-\><C-n>5<C-w>-i
tnoremap <M-k> <C-\><C-n>5<C-w>+i
execute "set <M-j>=\ej"
execute "set <M-k>=\ek"
nnoremap <M-j> <esc>5<C-w>-
nnoremap <M-k> <esc>5<C-w>+
map <leader>o :only<cr>


" markdown fence language
let g:markdown_fenced_languages = [
            \ 'vim',
            \  'css',
            \  'erb=eruby',
            \  'go',
            \  'java',
            \  'javascript',
            \  'js=javascript',
            \  'json=javascript',
            \  'ruby',
            \  'sass',
            \  'sql',
            \  'xml',
            \  'html',
            \  'cpp',
            \  'python',
            \  'bash=sh',
            \  'cmake',
            \  'proto'
            \]

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => General
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Sets how many lines of history VIM has to remember
set history=500

" Enable filetype plugins
syntax on 
filetype plugin on
filetype indent on

" Set to auto read when a file is changed from the outside
set autoread

" Fast saving
nmap <leader>w :w!<cr>

" :W sudo saves the file 
" (useful for handling the permission-denied error)
command W w !sudo tee % > /dev/null



"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => VIM user interface
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Set 7 lines to the cursor - when moving vertically using j/k
set so=7

" Avoid garbled characters in Chinese language windows OS
let $LANG='en' 
set langmenu=en
source $VIMRUNTIME/delmenu.vim
source $VIMRUNTIME/menu.vim

" Turn on the WiLd menu
set wildmenu

" Ignore compiled files
set wildignore=*.o,*~,*.pyc
if has("win16") || has("win32")
    set wildignore+=.git\*,.hg\*,.svn\*
else
    set wildignore+=*/.git/*,*/.hg/*,*/.svn/*,*/.DS_Store
endif

"Always show current position
set ruler

" A buffer becomes hidden when it is abandoned
set nohid

" Configure backspace so it acts as it should act
set backspace=eol,start,indent
set whichwrap+=<,>,h,l

" Ignore case when searching
set ignorecase

" When searching try to be smart about cases 
set smartcase

" Highlight search results
set hlsearch

" Makes search act like search in modern browsers
set incsearch 

" Don't redraw while executing macros (good performance config)
set lazyredraw 

" For regular expressions turn magic on
set magic

" Show matching brackets when text indicator is over them
set showmatch 

" How many tenths of a second to blink when matching brackets
set mat=2

" Set foldmethod
set fdm=indent
set foldlevel=20

" No annoying sound on errors
set noerrorbells
set novisualbell
set t_vb=
set tm=500



" Add a bit extra margin to the left
set foldcolumn=1

" Dismiss the tab label if buffers are to be used  
set showtabline=0
set tabline=2


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Colors and Fonts
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Enable syntax highlighting
syntax enable 
hi clear SpellBad
hi SpellBad cterm=reverse
hi Visual term=none ctermbg=239 guibg=DarkGrey ctermfg=LightGrey


set background=dark
" Enable 256 colors palette in Gnome Terminal
try
    " colorscheme NeoSolarized
    " colorscheme solarized
    colorscheme molokai
    " colorscheme desert

    let g:molokai_original = 1
    " hi Comment ctermfg=DarkCyan
    hi Comment ctermfg=244
    hi Normal guibg=black ctermbg=black
    hi Visual term=reverse ctermbg=239 guibg=DarkGrey
    hi Cursorline term=reverse ctermbg=239 guibg=DarkGrey
    hi MatchParen cterm=bold ctermfg=208 ctermbg=233 gui=bold guifg=#000000 guibg=#FD971F

catch
endtry

" Set extra options when running in GUI mode
if has("gui_running")
    set guioptions-=T
    set guioptions-=e
    set t_Co=256
    set guitablabel=%M\ %t
endif

" Set utf8 as standard encoding and en_US as the standard language
set encoding=utf8

" Use Unix as the standard file type
set ffs=unix,dos,mac


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Files, backups and undo
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Turn backup off, since most stuff is in SVN, git et.c anyway...
set nowb
set noswapfile

" set nobackup
set backup
set backupdir=/tmp/vimbackup//
if !isdirectory("/tmp/vimbackup")
    silent! execute "!mkdir /tmp/vimbackup"
endif

" set directory&vim " set varaible back to default just set var&vim


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Text, tab and indent related
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Use spaces instead of tabs

" Be smart when using tabs ;)

" Set line numbers
set expandtab
set smarttab
set shiftwidth=4
set tabstop=4
set ai "Auto indent
set si "Smart indent
set nu

" Set mouse
set mouse=r

" Set clipboard
set clipboard=unnamedplus


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Moving around, tabs, windows and buffers
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Disable highlight when <leader><cr> is pressed
map <silent> <leader><cr> :noh<cr>

" Smart way to move between windows
map <C-j> <C-W>j
map <C-k> <C-W>k
map <C-h> <C-W>h
map <C-l> <C-W>l
tnoremap <C-j> <C-W>j
tnoremap <C-k> <C-W>k

" Opens a new tab with the current buffer's path
" Super useful when editing files in the same directory
map <leader>te :tabedit <c-r>=expand("%:p:h")<cr>/

" Switch CWD to the directory of the open buffer
map cd :cd %:p:h<cr>.<cr>

" Specify the behavior when switching between buffers 
try
  set switchbuf=useopen,usetab,newtab
catch
endtry

" Return to last edit position when opening files (You want this!)
au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif


""""""""""""""""""""""""""""""
" => Status line
""""""""""""""""""""""""""""""
" Always show the status line
set laststatus=2

" Format the status line
" set statusline=\ %{HasPaste()}%F%m%r%h\ %w\ \ CWD:\ %r%{getcwd()}%h\ \ \ Line:\ %l\ \ Column:\ %c


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Editing mappings
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Remap VIM 0 to first non-blank character
map 0 ^



" Delete trailing white space on save, useful for some filetypes ;)
fun! CleanExtraSpaces()
    let save_cursor = getpos(".")
    let old_query = getreg('/')
    silent! %s/\s\+$//e
    call setpos('.', save_cursor)
    call setreg('/', old_query)
endfun

if has("autocmd")
    autocmd BufWritePre *.txt,*.js,*.py,*.wiki,*.sh,*.coffee :call CleanExtraSpaces()
endif


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Spell checking
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Pressing ,ss will toggle and untoggle spell checking
set spelllang=en
map ss :setlocal spell!<cr>

" Shortcuts using <leader>
map sn ]s
map sp [s
map <leader>sa zg
map <leader>s? z=


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Helper functions
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Returns true if paste mode is enabled
function! HasPaste()
    if &paste
        return 'PASTE MODE  '
    endif
    return ''
endfunction

" Don't close window, when deleting a buffer
command! Bclose call <SID>BufcloseCloseIt()
function! <SID>BufcloseCloseIt()
   let l:currentBufNum = bufnr("%")
   let l:alternateBufNum = bufnr("#")

   if buflisted(l:alternateBufNum)
     buffer #
   else
     bnext
   endif

   if bufnr("%") == l:currentBufNum
     new
   endif

   if buflisted(l:currentBufNum)
     execute("bdelete! ".l:currentBufNum)
   endif
endfunction




"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Plugins used by Coin
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

call plug#begin('~/.vim/plugged')

Plug 'Yggdroot/indentLine'
Plug 'scrooloose/nerdcommenter'
Plug 'majutsushi/tagbar'
Plug 'preservim/tagbar'
Plug 'vim-airline/vim-airline'
Plug 'luochen1990/rainbow'


call plug#end()


" configurations of netrw.vim
function! OpenExplore()
    exec ':ene'
    exec ':Explore'
endfunction
nmap nt :Explore<cr>
let g:netrw_banner=0
let g:netrw_liststyle=0
let g:netrw_altv = 4
let g:netrw_list_hide = '\(^\|\s\s\)\zs\.\S\+,\(^\|\s\s\)ntuser\.\S\+'



"" Configuration of NerdCommenter
let g:NERDSpaceDelims = 1
let g:NERDCompactSexyComs = 1
let g:NERDDefaultAlign = 'left'
    " let g:NERDCustomDelimiters = {'python':{'left':'###','right':'###'}}
    " let g:NERDCustomDelimiters = {'python':{'left':'#'}}
let g:NERDCommentEmptyLines = 1
let g:NERDTrimTrailingWhitespace = 1


"" Configuration of Tagbar
let g:tagbar_width = 30
let g:tagbar_autofocus = 1
" nmap tb :TagbarToggle fj<cr><c-w>=
" nmap tb :TagbarOpenAutoClose<cr><c-w>=
function! ToggleTagbar()
    echom 'ToggleTagbar::bufname() = ' . bufname('%')
    echom 'ToggleTagbar::bufname()'
    echom bufname('%')
    if bufname('%') =~# 'Tagbar' 
        call tagbar#CloseWindow() 
    else 
        call tagbar#OpenWindow('fj') 
    endif
endfunction
nmap tb :call ToggleTagbar()<cr>


"" Configuration of vim-airline
let g:airline#extensions#tabline#enabled=1
let g:airline_left_sep ='>'
let g:airline_right_sep ='<'
let g:airline#extensions#branch#displayed_head_limit =7 
"let g:airline#extensions#tabline#buffer_nr_show = 10
let g:airline#extensions#tabline#buffer_idx_mode = 1
let g:airline_section_error = ''
let g:airline_section_warning = ''
"let g:airline_theme='powerlineish'


"" rainbow
let g:rainbow_active = 1
let g:rainbow_conf = {
\   'guifgs': ['royalblue3', 'darkorange3', 'seagreen3', 'firebrick'],
\   'ctermfgs': ['lightblue', 'lightyellow', 'lightcyan', 'lightmagenta'],
\   'operators': '_,_',
\   'parentheses': ['start=/(/ end=/)/ fold', 'start=/\[/ end=/\]/ fold', 'start=/{/ end=/}/ fold'],
\   'separately': {
\       '*': {},
\       'tex': {
\           'parentheses': ['start=/(/ end=/)/', 'start=/\[/ end=/\]/'],
\       },
\       'lisp': {
\           'guifgs': ['royalblue3', 'darkorange3', 'seagreen3', 'firebrick', 'darkorchid3'],
\       },
\       'vim': {
\           'parentheses': ['start=/(/ end=/)/', 'start=/\[/ end=/\]/', 'start=/{/ end=/}/ fold', 'start=/(/ end=/)/ containedin=vimFuncBody', 'start=/\[/ end=/\]/ containedin=vimFuncBody', 'start=/{/ end=/}/ fold containedin=vimFuncBody'],
\       },
\       'html': {
\           'parentheses': ['start=/\v\<((area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)[ >])@!\z([-_:a-zA-Z0-9]+)(\s+[-_:a-zA-Z0-9]+(\=("[^"]*"|'."'".'[^'."'".']*'."'".'|[^ '."'".'"><=`]*))?)*\>/ end=#</\z1># fold'],
\       },
\       'css': 0,
\   }
\}


"" Configuration of the buffers
nmap <leader>b :bp<cr> 
nmap <leader>f :bn<cr>
"nmap <leader>d :Bdelete<cr> 
nmap <leader>d :bd<cr> 
nmap <leader>n :enew<cr> 
nmap <leader>1 <Plug>AirlineSelectTab1
nmap <leader>2 <Plug>AirlineSelectTab2
nmap <leader>3 <Plug>AirlineSelectTab3
nmap <leader>4 <Plug>AirlineSelectTab4
nmap <leader>5 <Plug>AirlineSelectTab5
nmap <leader>6 <Plug>AirlineSelectTab6
nmap <leader>7 <Plug>AirlineSelectTab7
nmap <leader>8 <Plug>AirlineSelectTab8
nmap <leader>9 <Plug>AirlineSelectTab9


" Auto complete pairs with map
inoremap <F3>, <><esc>:let leavechar=">"<cr>i
inoremap <F3>[ []<esc>:let leavechar="]"<cr>i
inoremap <F3>[[ {}<esc>:let leavechar="}"<cr>i
inoremap <F3>' ''<esc>:let leavechar="'"<cr>i
inoremap <F3>'' ""<esc>:let leavechar="""<cr>i
inoremap <F3>( ()<esc>:let leavechar=")"<cr>i
inoremap <F3>; <esc>$a;
inoremap <F3>: <esc>$a:

nmap <F3> $a {<esc>o}<esc>:let leavechar="}"<cr>O

" refresh syntax hight
autocmd FileType markdown syntax sync fromstart

@CoinCheung
Copy link

I think the problem is about key bindings. I used tb as binding and there is the problem, but when I use dd as shortcut, it is normal.

What does tb do in the tagbar buffer? Can I change it so that I can use my tb ?

@raven42
Copy link
Collaborator

raven42 commented Nov 28, 2023

Ah ok... good eye. Yes there is a keymap to the t key by default in the tagbar configuration. This will toggle the update mode.

If you want to remap this keymapping for tagbar, you can set the following:

let g:tagbar_map_togglepause = '<whatever-mapping-you-like>'

With this change, the tb shortcut is working for me. I just changed the togglepause to a capital T. (Note the screencast mode in the below image shows capital letters, but I was only hitting the t key without shift).
tagbar-toggle-function-with-tb

@CoinCheung
Copy link

@raven42 Thanks a lot !! I have no other question for now.

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

No branches or pull requests

4 participants