tagbar icon indicating copy to clipboard operation
tagbar copied to clipboard

Tagbar doesn't work on gvim for windows with python installed

Open emclimber opened this issue 5 years ago • 1 comments

Hi, When I run TagbarToggle I get the following error:

OSError: [WinError 6] The handle is invalid

But if debug mode is enabled, Tagbar work fine. In debug mode, the plugin does not use python to call ctags:

    if tagbar#debug#enabled()
        silent 5verbose let ctags_output = system(a:ctags_cmd)
        call tagbar#debug#log(v:statusmsg)
        call tagbar#debug#log('Exit code: ' . v:shell_error)
        redraw!
    else
        let py_version = get(g:, 'tagbar_python', 1)
        silent let ctags_output = s:run_system(a:ctags_cmd, py_version)
    endif

The plugin uses undocumented parameter g:tagbar_python, which allows using python for ctags calls. By default, this parameter set to 1, which launches call via python by default. This parameter is processed here:

    if has('win32') && !has('nvim') && a:version > 0 && (has('python3') || has('python2'))
        if a:version == 3 && has('python3')
            let pyx = 'py3 '
            let python_eval = 'py3eval'
        elseif a:version == 2 && has('python2')
            let pyx = 'py2 '
            let python_eval = 'pyeval'
        else
            let pyx = 'pyx '
            let python_eval = 'pyxeval'
        endif

Next, the part of the code where the ctags call is formed via Python:

        exec pyx . 'import subprocess, vim'
        exec pyx . '__argv = {"args":vim.eval("a:cmd"), "shell":True}'
        exec pyx . '__argv["stdout"] = subprocess.PIPE'
        exec pyx . '__argv["stderr"] = subprocess.STDOUT'
        exec pyx . '__pp = subprocess.Popen(**__argv)'
        exec pyx . '__return_text = __pp.stdout.read()'
        exec pyx . '__pp.stdout.close()'
        exec pyx . '__return_code = __pp.wait()'
        exec 'let l:hr = '. python_eval .'("__return_text")'
        exec 'let l:pc = '. python_eval .'("__return_code")'

Calling subprocess from gvim does not work, if "stdin" not defined. Bellow are the patches to fix this behaviour:

--- "a\\autoload\\tagbar.vim"	2020-10-24 00:17:10.000000000 +0300
+++ "b\\autoload\\tagbar.vim"	2020-10-24 21:29:14.307119000 +0300
@@ -2917,6 +2917,7 @@
         let l:pc = 0
         exec pyx . 'import subprocess, vim'
         exec pyx . '__argv = {"args":vim.eval("a:cmd"), "shell":True}'
+        exec pyx . '__argv["stdin"] = subprocess.DEVNULL'
         exec pyx . '__argv["stdout"] = subprocess.PIPE'
         exec pyx . '__argv["stderr"] = subprocess.STDOUT'
         exec pyx . '__pp = subprocess.Popen(**__argv)'
@@ -2971,7 +2972,7 @@
         call tagbar#debug#log('Exit code: ' . v:shell_error)
         redraw!
     else
-        let py_version = get(g:, 'tagbar_python', 1)
+        let py_version = get(g:, 'tagbar_python', 0)
         silent let ctags_output = s:run_system(a:ctags_cmd, py_version)
     endif
 

emclimber avatar Oct 24 '20 19:10 emclimber

Thanks for the detailed report. Care to make this fix into a PR?

alerque avatar Oct 24 '20 19:10 alerque