zigford.org/vim-quickfix-and-powershell.md
2020-07-21 06:49:32 +10:00

106 lines
3.9 KiB
Markdown

Vim Quickfix and PowerShell
Enno wrote in with a question on how [Ale](https://github.com/w0rp/ale) set's
Vim's `makeprg` and `errorformat` options when working with PowerShell.
---
Under the hood, I'm not sure if Ale uses those Vim features for processing
command output. Thus I'm not able to capture what those settings would look
like for PowerShell.
However the question did pique my curiosity and I'm interested in what the
options would look like if you wanted to parse PowerShell without Ale.
### makeprg
**Disclaimer**
My understanding of many Vim features is limited, so take what you learn here
with a grain of salt.
`makeprg` defaults to the command `make`. That way you can enter `:make` and
have your current project compiled without leaving Vim. Alongside that, the
output is parsed using a string option `errorformat`.
In order for PowerShell to produce some syntax checking output, you can run a
small script over the code and parse it's output. Therefore I embedded the
script into the `makeprg` option like so:
set makeprg=pwsh\ -command\ \"&{
\trap{$_.tostring();continue}&{
\$c=gc\ '%';$c=[string]::join([environment]::newline,$c);
\[void]$executioncontext.invokecommand.newscriptblock($c)
\}
\}\"
This works on win32 and you can see the resulting output by opening the quickfix
window with `:copen`
Unfortunately, on Unix, the most likely default shell will eat the PowerShell
`$Variables` so they must be escaped:
set makeprg=pwsh\ -command\ \"&{
\trap{\\$_.tostring\();continue}&{
\\\$c=gc\ '%';\\$c=[string]::join([environment]::newline,\\$c);
\[void]\\$executioncontext.invokecommand.newscriptblock(\\$c)
\}
\}\"
Now that `makeprg` is good to go, time to sort out the errorformat.
###errorformat
Errorformat uses scanf type parsing (which I had to google) that is a parsing
format used by c and other languages.
I spent a couple of hours today working this out by trial-and-error. While Vim's
`:help errorformat` documentation is great, particularly by including so many
examples, I didn't take the time to read it thoroughly initially.
Here is the winning formula:
set errorformat=%EAt\ line:%l\ char:%c,%-C+%.%#,%Z%m,%-G\\s%#
Explanation:
* `%E` tells Vim to begin capturing a multi-line message
* `At\ line:%l` records the line number where %l is
* `\ char:%c` records the column number where %c is
* `%-C+%.%#` continues a multi-line message, but removes this line from the
message if it contains + followed by .\* regex
* `%Z%m` tells Vim that this is the last line of a multi-line message and uses
the whole line
* `%-G\\s%#` tells vim to discard lines that are full whitespace
###VimRC
While I'm not sure I'll use this, as I like Ale, I hope it is useful to someone
out there, you could put it in your .vimrc like this:
augroup powershell
autocmd!
autocmd BufNewFile,BufRead *.ps1,*.psm1 setlocal FileType=powershell
autocmd FileType powershell setlocal errorformat=%EAt\ line:%l\ char:%c,
\%-C+%.%#,
\%Z%m,
\%-G\\s%#
if has('win32')
autocmd FileType powershell set makeprg=pwsh\ -command\ \"&{
\trap{$_.tostring();continue}&{
\$c=gc\ '%';$c=[string]::join([environment]::newline,$c);
\[void]$executioncontext.invokecommand.newscriptblock($c)
\}
\}\"
else
autocmd FileType powershell set makeprg=pwsh\ -command\ \"&{
\trap{\\$_.tostring\();continue}&{
\\\$c=gc\ '%';\\$c=[string]::join([environment]::newline,\\$c);
\[void]\\$executioncontext.invokecommand.newscriptblock(\\$c)
\}
\}\"
endif
augroup END
Tags: powershell, vim