Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running a shell script in .vimrc (and processing the output)

Tags:

shell

vim

I am trying to run a shell script from within a .vimrc file (three problems marked in the script):

function! CheckMe(file)
    let shellcmd = 'checkme '.a:file

    " Start the command and return 0 on success.
    " XXX: How do you evaluate the return code?
    execute '!'.shellcmd
    if !result
        return 0
    endif

    " Ending up here, the command returned an error.
    " XXX: Where to you get the output?
    let pair = split(output, '\S')
    let line = pair[0]
    let char = pair[1]

    " Jump to the errenous column and line.
    " XXX: Why does this not work?
    normal '/\%'.line.'l\%'.char.'c'
    return 1
endfunction

So to summarize, how do you get the result/output of the script, and why does the jump statement not work?

Additional details:

  • The shell script returns 0 on success, and 1 on failure. On a failure, the script prints two numbers (line and column number) to stdout, separated by a space character.
  • According to the Vim docs, the argument of the "normal" keyword is "executed like it is typed", but apparently that is not the case. It works fine when I type it (in the normal command mode, without leading ':'), but doesn't in the script ("E78: Unknown mark).
like image 805
knipknap Avatar asked Feb 20 '10 16:02

knipknap


2 Answers

function! CheckMe(file)
    let shellcmd = 'checkme '.a:file

    let output=system(shellcmd)
    if !v:shell_error
        return 0
    endif

    " Are you sure you want to split on non-blanks? This 
    " will result in list of blank strings.
    " My variant:
    let [line, char]=split(output)

    " Normal is not an execute: this is what it will do:
    " «'/» means «Go to mark /», produces an error E78 because /
    " is not a valid symbol for mark. Than normal stops after error occured.
    " If you need to use variables in nomal use «execute 'normal '.ncmd».
    " And you can not use «normal» to perform search
    execute '/\%'.line.'l\%'.char.'c'
    " or
    call setpos('.', [0, line, char, 0])
    return 1
endfunction

According to the Vim docs, the argument of the "normal" keyword is "executed like it is typed", but apparently that is not the case. It works fine when I type it (in the normal command mode, without leading ':'), but doesn't in the script ("E78: Unknown mark).

Just type «'/» to get this error.

like image 97
ZyX Avatar answered Oct 20 '22 17:10

ZyX


I think you want to use the system() function instead of the ! shell command.

From the linked page:

The result is a String.  Example:
            :let files = system("ls " .  shellescape(expand('%:h')))

and

The resulting error code can be found in |v:shell_error|.

So your output would come from the result of the system call and your result would come from v:shell_error. Then your jump should work.

like image 43
Dennis Williamson Avatar answered Oct 20 '22 16:10

Dennis Williamson