LoginSignup
6
4

neovimの設定をvimscriptからluaにしたときの覚書とか

Last updated at Posted at 2023-05-25

覚書なので随時追加していく系かもです

注意事項

  • 三文記事です
  • 内容はほぼ日記と覚書です
  • 基本的には公式ドキュメント嫁案件ではあります
  • なんか間違えていたら教えてくださるとありがたいです

とりあえず設定の書き方で迷ったときは…

githubでとにかく <プラグイン名/機能名> lang:lua で検索した結果をとにかく持ってきて動きを確認したりしていました

方法的にはマイコンのころからある、既存コードをコピペして使いやすく改変でしかありませんが、おおよそすでにきちんと動くコードから、luaの適切な書き方なども学ぶことができたので、とてもよかったです

vimscript から lua に変更したときに戸惑ったあれこれ

文字列結合 (lua)

luaの文字列結合は .. です、 + ではありません

local hoge = "ho" +  "ge" -- error
local fuga = "fu" .. "ga" -- OK

配列関係 (lua)

luaの配列やハッシュは テーブル というひとつの機能となっています

また、テーブルを表す文字は {} となっています

local ngtable = [] -- error
local oktable = {} -- OK

配列キーアクセス (lua)

また、配列キーにいろいろな文字を指定できますが、指定されている文字列によってはアクセス方法を変えないとならないです

local table = {
  one = 1,
  _ = "underscore",
  ["hoge-fuga"] = "hoge-fuga",
}

また、普通の連番の配列が存在する場合、 添え字(要素数)の始点は 0 ではなく、 1 です

local table = { "one", "two", "three" }
table[0] = "ONE" -- error
table[1] = "ONE" -- OK

luaでの vimscript 機能呼び出しあれこれ

set hogehoge 系 (set colorscheme など)

残念ながら vim.cmd() を使用します

諦めが必要

init.lua
local my_colorscheme = "onehalfdark"
vim.cmd("colorscheme" .. my_colorscheme)

グローバル変数 (g:xxx のようなやつ)

  • vim.g.xxx の形式で呼べます

vimscript定義?の関数の呼び出し (expand("%:h") など)

以下のいずれかで呼び出せます

  • vim.fn.expand()
  • vim.fn["expand"]()

私はもっぱら後者を使っていました

理由としては、プラグイン固有の関数呼び出しの場合に楽に呼び出せるためです

例えば ddu.vim を使用している場合は vim.fn["ddu#start"]() という形式で呼び出しを記述できます

vim固有の変数の呼び出し (&lines&columns など)

  • vim.api.nvim_eval("&lines") の形式で取得できます

個人的に作っておいて嬉しかったユーティリティ関数

echo

私が不勉強なだけの可能性が高いですが、 vim.fn["echo"] の形で echo を呼び出すことができず、 vim.cmd("echo " .. echo_message) の形式で記述することが多かったですので、ユーティリティとしてまとめておきました

また、vim設定の printfデバッグ 用の変数をグローバルに定義しており、それを参照することでデバッグモードがONの時にのみ動作するechoも別途実装しておりました

utils/init.lua
local M = {}

function M._echo(type, mes)
  vim.cmd("echo" .. type .. " '" .. mes .. "'")
end

function M.echo( mes)
  M._echo("", mes)
end
function M.echom(mes)
  M._echo("m", mes)
end

function M.echoerr(mes)
  M._echo("err", mes)
end

function M.echoe(mes)
  M.echoerr(mes)
end

-- debug preference
function M.debug_echo(mes, args)
  if vim.g.is_enable_my_debug then
    M.echom(mes)

    if args then
      for i, v in ipairs(args) do
        M.echom(i .. " : " .. v)
      end
    end
  end
end

function M.begin_debug(mes)
  M.debug_echo("begin " .. mes)
end
function M.end_debug(mes)
  M.debug_echo("end " .. mes)
end

try-catch

luaには try-catch の構文が存在しないらしく(調べ切れていない可能性が高いですが)、別途実装する必要がありましたので、こちらもユーティリティとして実装しております

なお、こちらのブログ記事がググると引っ掛かり、こちらを参考とさせていただきました(ありがとうございます)

utils/init.lua
-- local M = {}

function M.try_catch(what)
  M.debug_echo("begin try --->")
  local status, exception = pcall(what.try)
  if not status then
    M.debug_echo("#### begin catch --->")
    what.catch(exception)
    M.debug_echo("<--- end catch ####")
  else
    M.debug_echo("<--- end try")
  end
  if what.finally then
    M.debug_echo("begin finally --->")
    what.finally()
    M.debug_echo("<--- end finally")
  end

  return exception
end

こちらは使うときはこのように使えます
うれしい

usage.lua
local utils = require("utils")

utils.try_catch({
  try = function()
    -- watching target code
  end,
  catch = function()
    -- trapped code
  end,
  finally = function()
    -- finalize code
  end
})

eval しないといけない系

人によっては float window を多用していて、あるいはその表示幅や高さをいろいろ変えたいことがあると思います

一方で、ウィンドウのサイズがコロコロ変わることがある人もいます、少なくとも私のことです

それは、私が nvimnvim-qt.exe …つまり、WindowsのGUI環境で terminal を使用せずに neovim を使用していることを指しますが、この場合、ウィンドウをあちこち移動させたりすると、同様に幅がコロコロ変わります

そのため、 &lines&columns を参照したいのですが、結構長ったらしく書かないとならないので、ユーティリティとして記述しました

utils/init.lua
-- local M = {}

function M.get_vim_lines()
  return vim.api.nvim_eval("&lines")
end

function M.get_vim_columns()
  return vim.api.nvim_eval("&columns")
end

lua 設定のデバッグのしかた

:checkhealth

最強の強

プラグイン関係のエラーもおおよそこれに表示されます

例えば、必要となっている実行バイナリや、必須となっているプラグインがインストールされていないなどを適切にエラーとして表示してくれます

まずはこれを見ろのレベルで多用します

:message

一番下の行に現れるエラーの内容を表示できます

nvim -V9<filename>

が、 :message だけだと何の因果でこの事象が発生してるかが分からないことが大半です

そのため、おおよそ vim にも存在すると思いますが、 -V という実行ログをファイルに保存するオプションがNeovimには存在します

これが使えるだけで問題解決力が段違いに上がります

:map [key_name] / :imap [key_name] / :nmap [key_name]

現在のNeovimの設定ロード状態でマッピングされているキーを表示できます

[key_name] を指定しない場合は、現在設定されているマッピングの一覧を確認でき、設定した場合は、そのキーに今どのような動作が定義されているのかを確認することができます

e.g. :imap <CR>

こちらの記事で知りました、ありがとうございます…!

めっちゃどうでもいいけど git から設定をcloneするときに ~/AppData/Local/nvim~/.cache~/.config 配下に配置したくない人向けのそういう設定つくるやつ

主対象者: 私

理由: Windows(pwsh) で neovim を使用する場合、設定が ~/.config ではなく ~/AppData/Local/nvim になることがあったりして管理が面倒くさい

こういう設定用スクリプトを記述して、実行すれば自動的に任意の設定フォルダを参照するようにしています (pwsh向けのスクリプトなのでそこだけお気を付けください)

setup.ps1
Write-Output "make dir: ~/.config/nvim"

if (!(Test-Path '~/.config')) {
    mkdir ~/.config
    Write-Output "success mkdir ~/.config"
}

if (!(Test-Path '~/.config/nvim')) {
    mkdir ~/.config/nvim
    Write-Output "success mkdir ~/.config"
}

Write-Output "make dir: ~/AppData/Local/nvim"

if (!(Test-Path '~/AppData/Local/nvim')) {
    mkdir ~/AppData/Local/nvim
    Write-Output "success mkdir ~/AppData/Local/nvim"
}

Write-Output "remove nvim preference files what already exists"

if (Test-Path '~/.config/nvim/init.vim') {
    Remove-Item ~/.config/nvim/init.vim
}
if (Test-Path '~/.config/nvim/ginit.vim') {
    Remove-Item ~/.config/nvim/ginit.vim
}

if (Test-Path '~/AppData/Local/nvim/init.vim') {
    Remove-Item ~/AppData/Local/nvim/init.vim
}

if (Test-Path '~/AppData/Local/nvim/ginit.vim') {
    Remove-Item ~/AppData/Local/nvim/ginit.vim
}

if (Test-Path '~/.config/nvim/init.lua') {
    Remove-Item ~/.config/nvim/init.lua
}
if (Test-Path '~/.config/nvim/ginit.lua') {
    Remove-Item ~/.config/nvim/ginit.lua
}

if (Test-Path '~/AppData/Local/nvim/init.lua') {
    Remove-Item ~/AppData/Local/nvim/init.lua
}

if (Test-Path '~/AppData/Local/nvim/ginit.lua') {
    Remove-Item ~/AppData/Local/nvim/ginit.lua
}

Write-Output "write reference preference"

$preferencePathStr = [System.IO.Path]::GetDirectoryName($PSScriptRoot.ToString())

$preferencePathStr = $preferencePathStr.Replace('\', '/' )
$luaPathStr = $preferencePathStr + "/lua"

Write-Output $preferencePathStr

# ~/.config/nvim に設定作ってくれるやつ
Set-Content -Path ~/.config/nvim/init.lua  -Value "vim.opt.runtimepath:append(',${preferencePathStr}')"                 -Encoding UTF8
Add-Content -Path ~/.config/nvim/init.lua  -Value "vim.opt.runtimepath:append(',${luaPathStr}')"                        -Encoding UTF8
Add-Content -Path ~/.config/nvim/init.lua  -Value "vim.g.preference_path = vim.fn.expand('${preferencePathStr}')"       -Encoding UTF8
Add-Content -Path ~/.config/nvim/init.lua  -Value "vim.cmd([[luafile ${preferencePathStr}/init.lua]])"                  -Encoding UTF8
Set-Content -Path ~/.config/nvim/ginit.lua -Value "vim.cmd([[luafile ${preferencePathStr}/ginit.lua]])"                 -Encoding UTF8

# ~/AppData/Local/nvim に設定作ってくれるやつ
Set-Content -Path ~/AppData/Local/nvim/init.lua  -Value "vim.opt.runtimepath:append(',${preferencePathStr}')"           -Encoding UTF8
Add-Content -Path ~/AppData/Local/nvim/init.lua  -Value "vim.opt.runtimepath:append(',${luaPathStr}')"                  -Encoding UTF8
Add-Content -Path ~/AppData/Local/nvim/init.lua  -Value "vim.g.preference_path = vim.fn.expand('${preferencePathStr}')" -Encoding UTF8
Add-Content -Path ~/AppData/Local/nvim/init.lua  -Value "vim.cmd([[luafile ${preferencePathStr}/init.lua]])"            -Encoding UTF8
Set-Content -Path ~/AppData/Local/nvim/ginit.lua -Value "vim.cmd([[luafile ${preferencePathStr}/ginit.lua]])"           -Encoding UTF8

# luaの実行パスを通すやつ (あんまり意味ないかもしれない)
[System.Environment]::SetEnvironmentVariable("LUA_PATH",        $luaPathStr, "User")
[System.Environment]::SetEnvironmentVariable("LUA_EXE_PATH",    $luaPathStr, "User")

Write-Output "finished and all correct"

参考にしたやつ一覧

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4