WindowsでのWezterm+Neovimでの環境構築で躓いたこと

# 動機とターゲット

linuxでlunarvimを使っていて使い勝手が良かったので、windowsでも導入しようと思ったが、よくわからなかったので、代わりにneovimを導入することにした。

ターゲット:Windowsで手っ取り早くNeovimの環境を構築したい方、かなり入門向け

# 環境情報

```
nvim --version

PS C:\Users\user\AppData\Local\nvim> nvim --version
NVIM v0.9.5
Build type: RelWithDebInfo
LuaJIT 2.1.1703942320
```

記事執筆日時:2024/02/22

# 環境構築手順

[非常に丁寧なドキュメント](https://coralpink.github.io/commentary/index.html)がありますので、それに従って導入した。ドキュメントでは[packer.nvim](https://github.com/wbthomason/packer.nvim)を用いているが、

>NOTICE:
>
>This repository is currently unmaintained. For the time being (as of >August, 2023), it is recommended to use one of the following plugin >managers instead:**

とあり、[lazy.nvim](https://github.com/folke/lazy.nvim)と、[pckr.nvim](https://github.com/lewis6991/pckr.nvim)の使用が推奨されています。筆者は、lazy.nvimを使った。

# ディレクトリ構造

途中だが、以下のよう
    
```
Users\user\.config
└── wezterm
    ├── wezterm.lua
    ├── format.lua
    ├── keybinds.lua
    └── status.lua

Users\user\AppData\Local\nvim
├── lua
│   ├── extensions
│   │   ├── init.lua
│   │   ├── nvim-treesitter.lua
│   │   └── onnord.lua
│   ├── keybinds.lua
│   └── options.lua
└── init.lua

```

# 躓いたことと注意するところ

## 1. weztermのright-status

https://coralpink.github.io/commentary/wezterm/right-status.html?highlight=Get#get-parameter

weztermの`status.lua`のright-statusの部分を編集していたら、

```lua
  local function GetHostAndCwd(elems, pane)
  local uri = pane:get_current_working_dir()

  if not uri then
    return
  end

  local cwd_uri = uri:sub(8)
```
で、uriが文字列でない値を受け取ってしまっていたため、subメソッドが使えないというエラーが出たので、

```lua
  --local uri = pane:get_current_working_dir()まで同じ
  
  if not uri or type(uri) ~= 'string' then
    return
  end
```
とした。

<details><summary>status.luaの全体のコード</summary>

```lua
local wezterm = require 'wezterm'

local DEFAULT_FG = { Color = '#9a9eab' }
local DEFAULT_BG = { Color = '#333333' }

-- Define header elements
local HEADER_HOST = { Foreground = { Color = '#75b1a9' }, Text = '' }
local HEADER_CWD = { Foreground = { Color = '#92aac7' }, Text = '' }
local HEADER_DATE = { Foreground = { Color = '#ffccac' }, Text = '󱪺' }
local HEADER_TIME = { Foreground = { Color = '#bcbabe' }, Text = '' }
local HEADER_BATTERY = { Foreground = { Color = '#dfe166' }, Text = '' }
local HEADER_KEY_NORMAL = { Foreground = DEFAULT_FG, Text = '' }
local HEADER_LEADER = { Foreground = { Color = '#ffffff' }, Text = '' }
local HEADER_IME = { Foreground = DEFAULT_FG, Text = 'あ' }

local SPACE_1 = ' '
local SPACE_3 = '   '

-- Helper function to add header elements
local function AddElement(elems, header, str)
  table.insert(elems, { Foreground = header.Foreground })
  table.insert(elems, { Background = DEFAULT_BG })
  table.insert(elems, { Text = header.Text .. SPACE_1 })

  table.insert(elems, { Foreground = DEFAULT_FG })
  table.insert(elems, { Background = DEFAULT_BG })
  table.insert(elems, { Text = str .. SPACE_3 })
end

-- Helper function to add icon elements
local function AddIcon(elems, icon)
  table.insert(elems, { Foreground = icon.Foreground })
  table.insert(elems, { Background = DEFAULT_BG })
  table.insert(elems, { Text = SPACE_1 .. icon.Text .. SPACE_3 })
end

-- Helper function to get host and current working directory
local function GetHostAndCwd(elems, pane)
  local uri = pane:get_current_working_dir()

  -- Check if uri is a string and contains the expected format
  if not uri or type(uri) ~= 'string' then
    return
  end

  local cwd_uri = uri:sub(8)
  local slash = cwd_uri:find '/'

  if not slash then
    return
  end

  local host = cwd_uri:sub(1, slash - 1)
  local dot = host:find '[.]'

  AddElement(elems, HEADER_HOST, dot and host:sub(1, dot - 1) or host)
  AddElement(elems, HEADER_CWD, cwd_uri:sub(slash + 1))
endlement(elems, HEADER_CWD, cwd_uri:sub(slash + 1))
end

-- Helper function to get date
local function GetDate(elems)
  AddElement(elems, HEADER_DATE, wezterm.strftime '%a %b %-d')
end

-- Helper function to get time
local function GetTime(elems)
  AddElement(elems, HEADER_TIME, wezterm.strftime '%H:%M')
end

-- Helper function to get battery information
local function GetBattery(elems, window)
  if not window:get_dimensions().is_full_screen then
    return
  end

  for _, b in ipairs(wezterm.battery_info()) do
    AddElement(elems, HEADER_BATTERY, string.format('%.0f%%', b.state_of_charge * 100))
  end
end

-- Helper function to get keyboard status
local function GetKeyboard(elems, window)
  if window:leader_is_active() then
    AddIcon(elems, HEADER_LEADER)
    return
  end

  AddIcon(elems, window:composition_status() and HEADER_IME or HEADER_KEY_NORMAL)
end

-- Helper function to update left status
local function LeftUpdate(window, pane)
  local elems = {}

  GetKeyboard(elems, window)

  window:set_left_status(wezterm.format(elems))
end

-- Helper function to update right status
local function RightUpdate(window, pane)
  local elems = {}

  GetHostAndCwd(elems, pane)
  GetDate(elems)
  GetTime(elems)
  GetBattery(elems, window)

  window:set_right_status(wezterm.format(elems))
end

wezterm.on('update-status', function(window, pane)
  LeftUpdate(window, pane)
  RightUpdate(window, pane)
end)

```
</details>

## 2.starshipの導入

https://coralpink.github.io/commentary/wezterm/shell.html?highlight=starship#starship

コマンドプロンプトをカスタマイズする[starship](https://github.com/starship/starship)の導入はWindowsだと一癖あるので注意。

手順はGithubのreadmeにある通りだが、cmdだと[clink](https://chrisant996.github.io/clink/clink.html)を入れ、新しく`%LocalAppData%\clink\starship.lu`を作る必要がある。少しややこしいが、これでちゃんと動く。

## 3. パッケージマネージャとして、`packer.nvim`の代わりに`lazy.nvim`を使う。

[lazy.nvim](https://github.com/folke/lazy.nvim)の導入はreadme通りで簡単。`init.lua`なり、nvimに認識されるファイルに以下を書く。

```lua
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({
    "git",
    "clone",
    "--filter=blob:none",
    "https://github.com/folke/lazy.nvim.git",
    "--branch=stable", -- latest stable release
    lazypath,
  })
end
vim.opt.rtp:prepend(lazypath)
```

`packer.nvim`と`lazy.nvim`では使用するプラグインの書き方が違う。例えば、`onenord.nvim`を導入する場合、

前者なら

```lua
require('packer').startup(function()
  use 'wbthomason/packer.nvim'  -- Packer自体の管理

  use {
    'rmehri01/onenord.nvim',  -- プラグインのリポジトリ
    config = function() require 'extensions.onenord' end, 
  },

  -- 他のプラグイン設定
end)
```

となるところ、後者は

```lua
local plugins = {
  {
    'rmehri01/onenord.nvim',  -- プラグインのリポジトリ
    config = function() require 'extensions.onenord' end, 
  },
  -- 他のプラグイン設定
}

require("lazy").setup(plugins)
```
となる。

nvimを起動し、`lazy.nvim`をインストールしたら、`:checkhealth lazy`を実行して動作確認してください。

## 4. ハイライト機能などを提供する`nvim-treesitter`の導入

https://coralpink.github.io/commentary/neovim/plugin/nvim-treesitter.html

Windowsでは`nvim-treesitter`を導入するにあたって、C言語のコンパイラが必要になります。
詳しくは、[ドキュメント](https://github.com/nvim-treesitter/nvim-treesitter/wiki/Windows-support)に書いてある。筆者は、[Mingw toolchain](https://www.mingw-w64.org/)をchocolately経由でインストール後、`extensions/init.lua`に、

```lua
local M = {}

M.compilers = { vim.fn.getenv('CC'), "cc", "gcc", "clang", "cl", "zig" }
```

と付記して、`:TSInstall c`, `:TSInstall cpp`を実行したところ、問題なく使えた。

# 最後に

参考になれば幸いです。コメントなどあればお願いします。