環境
当方の環境は以下である。
zig version: 0.16.0
vim version: 9.1
Windows 11 + x86_64 + wsl2 + ubuntu24.04 + zsh
zigはどのエディタで書く?
当方はvimで書いている。それは、zigに限らず、普段使いのエディタがvimだからである。
vimのQuickFix
標準機能として存在しており、vimのversionを確認すると表示される+/-対象では無い。エラーや検索結果の該当ファイルや行、メッセージ等を一覧で表示し、Enterで実際の該当箇所に飛ぶことができる。以下コマンドで説明を呼べる。
vim
:help quickfix
QuickFixの例を確認するため、以下のファイルを書き、保存する。
zig: skel.zig
const std = @import("std");
const print = std.debug.print;
pub fn main(init: std.process.Init) !void {
}
保存時、以下のような挙動となり、QuickFixが開く。正確には、QuickFixの機能を使っているが、その該当ウィンドウが独立して持っているリストを使用している、Location Listと呼ばれるものが開く。
vim: skel.zig
:wq
zig fmt returned error
"skel.zig" 6L, 107B written
Press ENTER or type command to continue
Enterを押すと以下に遷移する。
vim: [Location List] Errors
skel.zig|4 col 13| : error: unused function parameter
1行目でEnterを押すと、上述のskel.zigの4行目に記述された、main関数の引数に指定したinitの、冒頭のiの位置にカーソルが飛ぶ。

QuickFixが動く仕組み
順に追っていく。
vim: skel.zig
:filetype
filetype detection:ON plugin:ON indent:ON
これにより、ファイルタイプの同定後に、プラグイン処理が走ることが分かる。
vim: skel.zig
:verbose autocmd * *.zig
--- Autocommands ---
filetypedetect BufNewFile
*.zig setf zig
Last set from /usr/share/vim/vim91/filetype.vim line 2025
filetypedetect BufRead
*.zig setf zig
Last set from /usr/share/vim/vim91/filetype.vim line 2025
Press ENTER or type command to continue
実際に、新規ファイル作成か既存ファイル読み込み時に、拡張子が.zigであるなら、filetypeをzigに設定している。setf(iletpye)と似た設定にset filetypeが存在するが、setfの場合は重複設定を回避する機能が備わっている。
vim: skel.zig
:set filetype?
filetype=zig
確かにfiletypeがzigと設定されていることが分かる。
vim: skel.zig
:verbose autocmd BufWritePre
vim-zig BufWrite
<buffer=1>
if get(g:, 'zig_fmt_autosave', 1) | call zig#fmt#Format() | endif
Last set from /usr/share/vim/vim91/ftplugin/zig.vim line 61
Press ENTER or type command to continue
保存時に処理が走っているので、BufWritePreを確認する。filetypeのpluginがonなのでftplugin/zig.vimから設定が読み込まれていることが分かる。
vim: /usr/share/vim/vim91/ftplugin/zig.vim(抜粋、コメント追記)
抜粋のため、行番号も記載した。
59 augroup vim-zig
60 autocmd! * <buffer> "このバッファのみ、vim-zigのautocmdを全て削除
61 autocmd BufWritePre <buffer> if get(g:, 'zig_fmt_autosave', 1) | call zig#fmt#Format() | endif "このバッファのみ、バッファ書き込み直前(:wで保存時など)に、g:zig_fmt_autosave=0の設定が無ければ、autoload/zig/fmt.vimのFormat()処理を実行
62 augroup END
まとめると、保存時にautoload/zig/fmt.vimのFormat()を実行する。
vim: /usr/share/vim/vim91/autoload/zig/fmt.vim(抜粋) 注:BSDライセンス
抜粋のため、行番号も記載した。
9 function! zig#fmt#Format() abort
"・・・省略・・・
18 let cmdline = 'zig fmt --stdin --ast-check'
19 let current_buf = bufnr('')
"・・・省略・・・
21 " The formatted code is output on stdout, the errors go on stderr.
22 if exists('*systemlist')
23 silent let out = systemlist(cmdline, current_buf)
"・・・省略・・・
37 let err = v:shell_error
"・・・省略・・・
55 elseif get(g:, 'zig_fmt_parse_errors', 1)
56 let errors = s:parse_errors(expand('%'), out)
57
58 call setloclist(0, [], 'r', {
59 \ 'title': 'Errors',
60 \ 'items': errors,
61 \ })
"・・・省略・・・
66 " Open the loclist, but only if there's at least one error to show.
67 execute 'silent! lwindow ' . win_height
68 endif
"・・・省略・・・
72 if err != 0
73 echohl Error | echomsg "zig fmt returned error" | echohl None
74 return
75 endif
"・・・省略・・・
80 endfunction
"・・・省略・・・
82 " parse_errors parses the given errors and returns a list of parsed errors
83 function! s:parse_errors(filename, lines) abort
84 " list of errors to be put into location list
85 let errors = []
86 for line in a:lines
87 let tokens = matchlist(line, '^\(.\{-}\):\(\d\+\):\(\d\+\)\s*\(.*\)')
88 if !empty(tokens)
89 call add(errors,{
90 \"filename": a:filename,
91 \"lnum": tokens[2],
92 \"col": tokens[3],
93 \"text": tokens[4],
94 \ })
95 endif
96 endfor
97
98 return errors
99 endfunction
まとめると、zig fmt --stdin --ast-checkコマンドを実行し、エラーを構文解析してLocation Listに入れ、表示している。
zsh
実際にコマンドを叩くと、確かに同一のエラーが表示される。
% zig fmt --stdin --ast-check < skel.zig
<stdin>:4:13: error: unused function parameter
pub fn main(init: std.process.Init) !void {
^~~~
%
続いて、skel.zigの保存時に開くLocation Listについて確認する。
vim: [Location List] Errors
:set filetype?
filetype=qf
Location ListはQuickFixの機能を使用していることが分かる。
vim: [Location List] Errors
:messages
"skel.zig" 6L, 119B
zig fmt returned error
"skel.zig" 6L, 119B written
Press ENTER or type command to continue
zig fmtが実行されていたことが分かる。
vim: [Location List] Errors
:verbose set errorformat?
errorformat=%*[^"]"%f"%*\D%l: %m,"%f"%*\D%l: %m,%-Gg%\?make[%*\d]: *** [%f:%l:%m,%-Gg%\?make: *** [%f:%l:%m,%-G%f:%l: (Each undeclared identifier is reported only once,%-G%f:%l: for each
function it appears in.),%-GIn file included from %f:%l:%c:,%-GIn file included from %f:%l:%c\,,%-GIn file included from %f:%l:%c,%-GIn file included from %f:%l,%-G%*[ ]from %f:%l:%c,%-G%
*[ ]from %f:%l:,%-G%*[ ]from %f:%l\,,%-G%*[ ]from %f:%l,%f:%l:%c:%m,%f(%l):%m,%f:%l:%m,"%f"\, line %l%*\D%c%*[^ ] %m,%D%*\a[%*\d]: Entering directory %*[`']%f',%X%*\a[%*\d]: Leaving direct
ory %*[`']%f',%D%*\a: Entering directory %*[`']%f',%X%*\a: Leaving directory %*[`']%f',%DMaking %*\a in %f,%f|%l| %m
%f:%l:%c:%mに該当する。
カーソル行のハイライトが明るい黄色でエラーメッセージが読めない
QickFixは色んなことができそうでとてもわくわくするのだが、如何せん、ハイライトが明るい黄色でエラーのメッセージ部が白色なので、読めないにゅんちゅ。そこで、以下のコマンドでハイライト一覧から色が一致する設定を探した。
vim
:verbose highlight
"・・・省略・・・
QuickFixLine xxx links to Search
Last set from /usr/share/vim/vim91/colors/default.vim line 15
"・・・省略・・・
色が一致しQuickFixに関係する設定として、QuickFixLineが見つかった。Searchの設定を流用しているようだ。そこで、Searchを確認する。
vim
:verbose highlight Search
Search xxx term=reverse ctermbg=11 guibg=Yellow
Last set from /usr/share/vim/vim91/colors/default.vim line 15
Press ENTER or type command to continue
11というのは、ANSIカラーに対応した数字であり、明るい黄色を指す。以下の表はANSIエスケープシーケンスでSGR(Select Graphic Rendition)コマンドの値を示す。SGRのフォーマットはESC[値mであり、実際にESCは文字コード:0x1bのため例えば8進数表記で\033と記述する(例:\033[93m)。ANSIカラーは0~7の8色だが、vimでは明るい色にも連番を振っているため、例えば11であれば8以上なので明るい色であり、11-8=3で黄色を指すということになる。
| name | fg | bg | vim |
|---|---|---|---|
| Black | 30 | 40 | 0 |
| Red | 31 | 41 | 1 |
| Green | 32 | 42 | 2 |
| Yellow | 33 | 43 | 3 |
| Blue | 34 | 44 | 4 |
| Magenta | 35 | 45 | 5 |
| Cyan | 36 | 46 | 6 |
| White | 37 | 47 | 7 |
| Bright Black (Gray) | 90 | 100 | 8 |
| Bright Red | 91 | 101 | 9 |
| Bright Green | 92 | 102 | 10 |
| Bright Yellow | 93 | 103 | 11 |
| Bright Blue | 94 | 104 | 12 |
| Bright Magenta | 95 | 105 | 13 |
| Bright Cyan | 96 | 106 | 14 |
| Bright White | 97 | 107 | 15 |
ここで、背景が明るい黄色で文字が白色だと読めないため、以下のように個人設定ファイルにコマンドを追記し、今回対象となるctermの背景のみ暗い黄色に上書き設定する。
vim: ~/.vimrc
highlight Search ctermbg=3
それでは再度、該当ソースファイルを開き保存することで、QuickFixを確認する。

読めるようになったにゅんちゅ!

