So this is a continuation of my adventures into creating my first plugin ;-)

Today's issue is that I want to execute some shell command, and redirect the output to a separate window that respects my window layout. Everything about the execution of the shell command is done, and my only question is about how to make my function respect my window layout

Assume my current vim windows looks like this

 ___________ ___________
|           |           |
|           |  cursor   |
|           |  and code |
|           |           |
|           |           |
|           |           |
|           |           |

When I run my command the layout changes to this

 ___________ ___________
|           |           |
|           |  cursor   |
|           |  and code |
|                       |
| result of compilation |
|                       |

Where I would prefer if the output instead produced this

 ___________ ___________
|           |           |
|           |  cursor   |
|           |  and code |
|           |___________|
|           |           |
|           | result of |
|           |compilation|

My current code is mostly taken from this question about the same issue in Python. I have commented out everything that contains the compilation.

function! SaveAndExecuteJelly()
  " SOURCE [reusable window]: https://github.com/fatih/vim-go/blob/master/autoload/go/ui.vim
  " save and reload current file
  silent execute "update | edit"
  " let [jelly_code, jelly_args] = GetJellyCodeAndArgs()
  " let jelly_command = s:jelly_command .' '. jelly_code .' '. jelly_args
  " echo jelly_command
  " get file path of current file
  let s:current_buffer_file_path = expand("%")
  let s:output_buffer_name = "Jelly"
  let s:output_buffer_filetype = "output"
  " reuse existing buffer window if it exists otherwise create a new one
  if !exists("s:buf_nr") || !bufexists(s:buf_nr)
    silent execute 'botright new ' . s:output_buffer_name
    let s:buf_nr = bufnr('%')
  elseif bufwinnr(s:buf_nr) == -1
    silent execute 'botright new'
    silent execute s:buf_nr . 'buffer'
  elseif bufwinnr(s:buf_nr) != bufwinnr('%')
    silent execute bufwinnr(s:buf_nr) . 'wincmd w'
  silent execute "setlocal filetype=" . s:output_buffer_filetype
  setlocal bufhidden=delete
  setlocal buftype=nofile
  setlocal noswapfile
  setlocal nobuflisted
  setlocal winfixheight
  setlocal cursorline " make it easy to distinguish
  setlocal nonumber
  setlocal norelativenumber
  setlocal showbreak=""
  " clear the buffer
  setlocal noreadonly
  setlocal modifiable
  %delete _
  " add the console output
  " silent execute ".!python " . shellescape(s:current_buffer_file_path, 1)
  " let result = system(jelly_command)
  let result = '234168'
  call append(0, result)
  execute '$delete _'
  " resize window to content length
  " Note: This is annoying because if you print a lot of lines then your code buffer is forced to a height of one line every time you run this function.
  "       However without this line the buffer starts off as a default size and if you resize the buffer then it keeps that custom size after repeated runs of this function.
  "       But if you close the output buffer then it returns to using the default size when its recreated
  "execute 'resize' . line('$')
  " make the buffer non modifiable
  setlocal readonly
  setlocal nomodifiable
  "  Go to previous (last accessed) window.
  execute "normal! \<c-w>\<c-p>"
  • 1
    You specifically use botright command that does what you don't want.
    – Maxim Kim
    Jul 18, 2021 at 16:40
  • @MaximKim This solved the issue! This shows what happens when you copy code you do not quite understand. A second issue is that it seems this code creates two buffers instead of one new. Do you have any idea? Otherwise, just leave the "remove botright as an answer" =) Jul 18, 2021 at 16:45
  • 1
    Not sure what exactly you mean by 2 buffers -- you better ask another separate question about it, clarifying all details there.
    – Maxim Kim
    Jul 18, 2021 at 16:50

1 Answer 1


Remove :botright as it does:

:bo[tright] {cmd}
        Execute {cmd}.  If it contains a command that splits a window,
        it will appear at the bottom and occupy the full width of the
        Vim window.  When the split is vertical the window appears at
        the far right and occupies the full height of the Vim window.
        Doesn't work for |:execute| and |:normal|.

These command modifiers can be combined to make a vertically split window
occupy the full height.  Example: >
    :vertical topleft split tags
Opens a vertically split, full-height window on the "tags" file at the far
left of the Vim window.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.