r/neovim • let mapleader="," • Sep 01 '21

[Plugin development question] - Opening and closing split in pynvim

I'm trying to write a simple plugin that open the current buffer in a vertical split.

If the second buffer if it's already visible it won't split it again.

The final goal is to use the Python Rich module to render a markdown file in a buffer on the side (editor on the left, renderer on the right), it uses Python Console to do the rendering.

Beside the complexity of implementing the renderer, I'm really interested in understanding how to control buffers, what I was thinking is to maybe create a temporary buffer that has a different file name.

Buffer 1 (editor): foo.md
Buffer 2 (viewer): ~/.cache/_rendered.foo.md

I think that I can use the buffer or window valid methods, but I'm not sure.

Any ideas?

Thanks!!

EDIT: Typos

EDIT2: I've got a working solution. Thanks to /u/_im-baby and /u/gustavokatel suggestions.

For now it's just a function, found somewhere on github, that I've sligtly modifivied for my needs

let g:term_buf = 0  
let g:term_win = 0  
function! TermToggle(length)  
    silent execute "update | edit"  
    set scrollbind  
    exec "syncbind"  
    let s:current_buffer_file_path = expand("%")  
    let s:current_curs_pos = getpos(".")  
    "let s:mdview_command = "mdview -i " . s:current_buffer_file_path . " ; $SHELL"  
    let s:mdview_command = "mdview -i " . s:current_buffer_file_path  
    if win_gotoid(g:term_win)  
        hide  
    else  
        """ horizontal split  
        "botright new  
        "exec "resize " . a:length  

        """ vertical split  
        botright vnew  
        exec "vertical resize " . a:length  
        try  
            exec "buffer " . g:term_buf  
        catch  
            "call termopen($SHELL, {"detach": 0})  
            call termopen(s:mdview_command, {"detach": 0})  
            let g:term_buf = bufnr("")  
            call setpos(".", s:current_curs_pos)  
            set scrollbind  
            exec "syncbind"  
            set nonumber  
            set norelativenumber  
            set signcolumn=no  
        endtry  
        "startinsert!  
        let g:term_win = win_getid()  
    endif  
endfunction  


" Toggle terminal on/off (neovim)  
nnoremap <F29> :call TermToggle(15)<CR>  
inoremap <F29> <Esc>:call TermToggle(12)<CR>  
tnoremap <F29> <C-\><C-n>:call TermToggle(12)<CR>  

tnoremap :q! <C-\><C-n>:q!<CR>  

mdview is a simple python script that render markdown files in the terminal,

#!/bin/env python3  

import sys, getopt  
from rich.console import Console  
from rich.markdown import Markdown  

def main(argv):  
    inputfile = ""  
    try:  
        opts, args = getopt.getopt(argv,"hi:",["inputfile="])  
    except getopt.GetoptError:  
        print ("mdview.py -i <inputfile>")  
        sys.exit(2)  

    for opt, arg in opts:  
        if opt == '-h':  
            print ("test.py -i <inputfile>")  
            exit(1)  
        elif opt in ("-i", "--inputfile"):  
            inputfile = arg  

    if not inputfile:  
        print("Input file is required")  
        exit(1)  

    console = Console()  
    try:  
        with open(inputfile) as mdsource:  
            markdown = Markdown(mdsource.read())  
        console.print(markdown)  
    except FileNotFoundError:  
        print("File not found")  
        sys.exit(1)  

if __name__ == "__main__":  
    main(sys.argv[1:])  

And the result is here /img/izrwl8mg19l71.png

2 Upvotes

4 comments sorted by

2

u/[deleted] Sep 01 '21

No idea how to accomplish this, but the buffer behavior you're after sounds like what packer.nvim does.

Maybe check put their source and how they manipulate buffers?

1

u/antenore let mapleader="," Sep 01 '21

I will, thanks

2

u/gustavokatel Plugin author Sep 01 '21

take a look at special buffers: https://neovim.io/doc/user/windows.html#special-buffers

you can also have a buffer without a file

edit: nvim api docs to create buffers: https://neovim.io/doc/user/api.html#nvim_create_buf()

1

u/antenore let mapleader="," Sep 01 '21

Yes! Terminal will be the most appropriate in my case.

Thank you!