Is it possible to fix the 'help-curwin' command / function from vim help tips?

Viewed 116

I do not understand vim script very well, just enough to tinker with my vimrc. So I am looking for someone's help to understand what can be done here.

I use this HelpCurWin command from the vim help page 'tips.txt', tag 'help-curwin'. The command is designed to open a given help page in the current window instead of opening a new split. This part works fine. Here is the code:

" Command to open help page in current window.
command -bar -nargs=? -complete=help HelpCurwin
      \ execute s:HelpCurwin(<q-args>)
let s:did_open_help = v:false
function s:HelpCurwin(subject) abort
  let mods = 'silent noautocmd keepalt'
  if !s:did_open_help
    execute mods .. ' help'
    execute mods .. ' helpclose'
    let s:did_open_help = v:true
  endif
  if !getcompletion(a:subject, 'help')->empty()
    execute mods .. ' edit ' .. &helpfile
  endif
  return 'help ' .. a:subject
endfunction

Here is a slightly diferent version from the nvim documentation (I tried both):

" Command to open help page in current window.
command -bar -nargs=? -complete=help HelpCurwin
      \ execute s:HelpCurwin(<q-args>)
let s:did_open_help = v:false
function s:HelpCurwin(subject) abort
  let mods = 'silent noautocmd keepalt'
  if !s:did_open_help
    execute mods .. ' help'
    execute mods .. ' helpclose'
    let s:did_open_help = v:true
  endif
  " Fix from nvim documentation.
  if !empty(getcompletion(a:subject, 'help'))
    execute mods .. ' edit ' .. &helpfile
  endif
  return 'help ' .. a:subject
endfunction

As I was saying the main goal of opening the help page in the current window is achieved, but, there are 3 side effects I noticed:

  1. When I open a specific help page, the default 'help.txt' page will automatically be added to the buffer list,
  2. The 'help.txt' page will not be added to the list as an "unlisted" buffer which clutters the tabline, and the buffer list,
  3. Even if I issue :HelpCurwin with no page specified, the 'help.txt' page will be listed as a regular buffer and not get syntax highlighting (even though the filetype is correctly set).

Those are not critical issues, but it is bugging me, and I would be grateful if anyone could help me fix it, or, if impossible, explain me why.

EDIT: I forgot to specify that I am personally using this function mostly from vertically split windows, so I am looking to improve it primarily for that use case.

1 Answers

Here's a solution I came up with that is a bit less hacky (IMO) than the recommended solution and doesn't suffer from the problem of polluting the buffer list.

" Open help in the current window with :Help
command! -bar -nargs=? -complete=help Help call s:HelpHere(<q-args>)

function! s:HelpHere(subject) abort

  " remember the state of the windows
  let l:window_id = win_getid()
  let l:window_width = winwidth(0)
  let l:num_windows = winnr('$')
  
  " open the help window
  execute 'help ' .. a:subject

  " close the original window if a new help window was opened, and
  " if it should have opened immediately above the original window
  if l:num_windows < winnr('$') && (l:num_windows == 1 || l:window_width >= 80)
    call win_execute(l:window_id, 'close')
  endif

endfunction

The new :Help command is implemented by the function s:HelpHere. This function just passes its argument to the standard :help command, then closes the original window if :help created a new window.

Most of the time, this simulates opening the help window in the window that :Help was invoked from.

However, if the standard :help command is invoked from a narrow window, then it will create a new window on top of potentially several vertically split windows, so closing the original window doesn't simulate what we want. In this case, my :Help command doesn't close the original window and just preserves the default behavior of :help.

Related