2
\$\begingroup\$

When I was not sure about how to do this, I asked this question on StackOverflow, the body of which is the following:

As regards line numbers, when doing normal file editing, I prefer to have the following setting

set number
set relativenumber

because the former tells me where I am, the latter helps me using j and k effectively.

However, when debugging with gdb, using the termdebug package and the :Termdebug command, I often want to set breakpoints; hence, I'd like to turn the latter option off, executing the set norelativenumber command on a global scope, so that all files I'm editing show the actual line numbers.

Reading the answer, and Vim help pages a bit more, I ended up with the following solution, which is now part of my ~/.vimrc file:

" Source the termdebug plugin
packadd termdebug

" Add mapping to load termdebug
noremap <silent> <Leader>td :call MyTermdebug()<CR>

" turn off relativenumber,
" start Termdebug,
" and create autocmd to turn relativenumber back on
function! MyTermdebug()
  call SetRelNumInAllWin(v:false)
  augroup ClosingDebugger
    au!
    autocmd BufUnload !gdb call SetRelNumInAllWin(v:true)
  augroup END
  Termdebug
endfunction

" set/unset relativenumber in all windows if flag is v:true/v:false
function! SetRelNumInAllWin(flag)
  let current_win_id = win_getid()
  tabdo windo call SetRelNum(a:flag)
  call win_gotoid(current_win_id)
endfunction

" set/unset relativenumber in current window if flag is v:true/v:false
function! SetRelNum(flag)
  if &number
    if a:flag
      set relativenumber
    else
      set norelativenumber
    end
  end
endfunction
\$\endgroup\$
1
2
\$\begingroup\$

Two things off the top of my head:

Use mode-specific mappings, so nnoremap limits the mapping to normal mode. (Great job on the use of non-recursive mappings.)

You can access options as vimscript variables with &relativenumber. SetRelNum is sort of unecessary: I would have written

tabdo windo let &relativenumber = a:flag

(And if that doesn’t work because of some odd scope rule, you can exec it with everything but a:flag in quotes. You may have to pass 0/1 instead of v:false/v:true etc.)

\$\endgroup\$
6
  • 1
    \$\begingroup\$ Concerning nore* I have just absorbed the lesson "use non-recursive mappings by default, unless you need recursion and you really know what you are doing". That oneliner you suggested is great! I'll check and adjust if needed. \$\endgroup\$ – Enlico Mar 20 '20 at 15:00
  • \$\begingroup\$ Yes, I had to use 0/1 instead of v:false/v:true. However I am thinking about a usability contraddiction in my solution. Since I want to take advantage of rnu when navigating the files, and I want to deactivate it just when I'm in the !gdb window where I run the break command, it would make sense to set and unset rnu in all windows everytime move from/to the !gdb window. \$\endgroup\$ – Enlico Mar 20 '20 at 17:16
  • 1
    \$\begingroup\$ There are some BufWinEnter style events you can look into for that \$\endgroup\$ – D. Ben Knoble Mar 20 '20 at 17:17
  • \$\begingroup\$ Yes, but I kinda remember that the termdebug buffer has something special, as regards the events. If I have issues, I'll post a question on stack overflow. \$\endgroup\$ – Enlico Mar 20 '20 at 17:25
  • 1
    \$\begingroup\$ I was wrong, using those events with the gdb window seems perfectly fine. \$\endgroup\$ – Enlico Mar 20 '20 at 19:24
1
\$\begingroup\$

I realized that deactivating rnu when I start :Termdebug is unproductive, as the option remains inactive even when I'm navigating the scripts while the !gdb window is open.

So I ended up with this solution, where rnu is off only if the cursor is in the !gdb window; as soon as the cursor moves away from it, rnu is turned on.

" mapping and function to start gdb and activate "smart" relativenumber
nnoremap <silent> <Leader>td :call TermdebugAndRelNumOff()<CR>
function! TermdebugAndRelNumOff()
  augroup ClosingDebugger
    au!
    " set/unset rnu when leaving/entering gdb window
    autocmd BufLeave  !gdb call SetRelNumInAllWin(1)
    autocmd BufEnter  !gdb call SetRelNumInAllWin(0)
    " delete the augroup (and its autocmd-s) when closing gdb
    autocmd BufUnload !gdb au! | augroup! ClosingDebugger
  augroup END
  " start Termdebug
  Termdebug
endfunction

NOTE

The use of windo has the undesirable behavior of altering the window which Ctrl+p will jump to: once I move to the !gdb window from ThisWindow, those keys will jump to the bottom-right window instead of to ThisWindow. I'm trying to address this annoying thing here.

NOTE2

Since moving away from the !gdb window makes no sense if that window is not in the current tab, and since moving to it from a tab which does not contain it is unlikely (or is it non-sense too?), I suspect that tabdo can be avoided entirely in the definition of SetRelNumInAllWin given in the question.

\$\endgroup\$

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.