lualine.nvimをカスタマイズして作業を便利にする

<style>
span.red {
  color: red;
}
</style>
:::note info
これは[Vim駅伝](https://vim-jp.org/ekiden/)の229本目の記事です。
:::
# 概要
みなさん、こんにちは。KITsのプログラマーの苔コッコーです。
初心者ですので、読みにくかったり、間違えていたりすると思います。あらかじめ謝っておきます。
つい最近、学校で友人に布教されてNeovimを使い始めたのですが、それまではVSCodeばっかり使っていたので、かっこいいUIが欲しかったわけです。そこで、NeovimのUIのプラグインを探して、たどり着いたのが[lualine.nvim](https://github.com/nvim-lualine/lualine.nvim)でした。
今回は、最大限にNeovimを活用するためのステータスラインカスタマイズを解説しようと思います。

# Lualine.nvimとは
ChatGPTその1
> Lualine.nvimは、Neovim用に開発されたステータスラインプラグインで、
その名前の通り、ステータスラインをより機能的かつ美しくすることを目的としています。
VimやNeovimのデフォルトのステータスラインに比べ、Lualineは高度にカスタマイズ可能で、
開発者に合わせた自由な設定が可能です。
## 特徴と利点
ChatGPTその2
>・軽量で高速
Lualine.nvimはLuaで書かれており、非常に軽量かつ高速です。
パフォーマンスを重視するNeovimユーザーにとって最適な選択肢です。
>
>・豊富なカスタマイズオプション
デフォルトのコンポーネントやセクション配置を柔軟に変更でき、
ユーザーのニーズに合わせてカスタマイズ可能です。
>
>・プラグインとの互換性
他の多くのNeovimプラグイン（例：Git情報表示、LSPインテグレーションなど）
と統合することができ、ステータスラインに必要な情報を追加できます。
>
>・豊富なテーマサポート
視覚的に魅力的な複数のテーマが用意されており、見た目を簡単に変更できます。
>
>・カスタムコンポーネントの追加
Lualine.nvimでは、独自のコンポーネントを追加して、より詳細な情報をステータスラインに
表示することができます。この機能により、開発環境をさらに個別化することが可能です。
## なぜカスタムコンポーネントが必要なのか？
ChatGPTその3
>Lualine.nvimの標準機能で提供されるコンポーネントだけでも十分に多機能ですが、
開発者それぞれのワークフローに合わせた情報を表示するにはカスタムコンポーネントが
非常に役立ちます。以下のような場合に、カスタムコンポーネントが有用です。
>
>特定のファイルタイプに特化した情報を表示
例えば、現在開いているファイルがPythonスクリプトの場合には、仮想環境の情報を表示する
コンポーネントを追加することができます。
>
>個々の開発スタイルに応じた設定
各プロジェクトごとに異なる情報をステータスラインに表示したい場合にも、
カスタムコンポーネントを利用することで柔軟な対応が可能です。
>
>独自の開発ツールとの統合
社内開発ツールや個人で開発したツールと連携し、ステータスラインに
その情報を表示することで、作業効率を向上させることができます。
>
>Lualine.nvimの柔軟性を活かし、自分だけのステータスラインを作成することで、
開発作業がより効率的で楽しいものになるでしょう。

ここまでChatGPT生成です。すみませんでした。

# カスタマイズ
さて、ではこれから実際のカスタマイズをお見せします。まずはステータスラインの画像から御覧ください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3723455/6f0efc3b-0d96-ebcf-b497-b2de218b7b38.png)
左から、<font color="red">モード</font>、応援メッセージ、<font color="red">ブランチ</font>、<font color="red">Gitのdiff</font>、<font color="red">ファイルに含まれる問題点</font>、インデントのサイズ、現在のToDo、<font color="red">文字コード</font>、<font color="red">ファイルの種類</font>、<font color="red">相対パス</font>、バッファの行数、ヤンクレジスタの要約、稼働中のLSP、現在時刻です。
赤文字のものはデフォルトでlualine.nvimに存在しているもので、それ以外はカスタムコンポーネントです。

以下は、カスタムコンポーネントの定義部分です。
```lua:カスタムコンポーネント
local function current_time()
  return os.date("%H:%M")  -- 時:分:秒の形式で現在時刻を取得
end

local function total_lines()
  return vim.fn.line('$')
end

local function encouragement()
  return [[頑張れ]]
end

local function lsp_clients()
  local clients = vim.lsp.get_active_clients({ bufnr = 0 })
  if next(clients) == nil then return "LSPなし" end
  local client_names = {}
  for _, client in pairs(clients) do
    table.insert(client_names, client.name)
  end
  return table.concat(client_names, ", ")
end

local function indent_style()
  if vim.bo.expandtab then
    return vim.bo.shiftwidth .. "スペース"
  else
    return vim.bo.tabstop .. "タブ"
  end
end

-- カスタムコンポーネントを作成
local function yank_register()
  -- ヤンクレジスタの内容を取得
  local yank_content = vim.fn.getreg('"')

  -- 改行をスペースに置き換え
  yank_content = yank_content:gsub("\n", " ")

  -- 内容を10文字に短縮し、長ければ"..."を追加
  if #yank_content > 10 then
    yank_content = string.sub(yank_content, 1, 7) .. "..."
  end

  -- 表示する内容を返す
  return yank_content ~= "" and yank_content or "EMPTY"
end
```
以下は、lualine.nvimの設定部分です。
```lua:lualine.nvimの設定部分
require("lualine").setup{
    options = {
      icons_enabled = true,
      theme = 'material',
      component_separators = { left = '', right = ''},
      section_separators = { left = '', right = ''},
      disabled_filetypes = {
        statusline = {},
        winbar = {},
      },
      ignore_focus = {},
      always_divide_middle = true,
      globalstatus = true,
      refresh = {
        statusline = 1000,
        tabline = 1000,
        winbar = 1000,
      }
    },
    sections = {
      lualine_a = {'mode'},
      lualine_b = {{encouragement, color={fg="#FF9999"}},'branch'},
      lualine_c = {
        {
          'diff',
          symbols = {added = ' ', modified = ' ', removed = ' '},
        },
        {
          'diagnostics',
          symbols = {error = ' ', warn = ' ', info = ' ', hint = ' '}
        },
        {
          indent_style
        },
      },
      lualine_x = {
        {todos.get_top_todo, color = {fg="#FFFF99"}},
        'encoding', 'filetype', {'filename', path=1}},
      lualine_y = {
        {total_lines, color={fg="#FF99FF"}},
        {yank_register, icon = '📋'},
      },
      lualine_z = {
        {lsp_clients, color={fg="#99FF99", bg="#3c3c6c"}},
        {current_time, color={fg="#99FFFF", bg="#3c3c6c"}},
      }
    },
    inactive_sections = {
      lualine_a = {},
      lualine_b = {},
      lualine_c = {},
      lualine_x = {},
      lualine_y = {},
      lualine_z = {}
    },
    tabline = {},
    winbar = {},
    inactive_winbar = {},
    extensions = {}
}
```
ブラウザがNerd Fontに対応していなければ、文字化けするかもしれません。

# そのコンポーネントを採用した理由
1. モード
   現在のモードが視覚的にわかるため、間違ったモードで操作をしてしまう（例:Insertモードでコマンドを入力してしまう）ことがなくなるため、効率的になる。
1. 応援メッセージ
   仕事で疲れてきたときに、応援メッセージが視界に入ることで、またやる気が出てくる。メンタル面でのサポート。
1. ブランチ・Gitのdiff・ファイルの問題点・文字コード・相対パス・ファイルの種類
もともと含まれていたので、あまり深く考えずに採用した。
1. インデントのサイズ
Visual Studio Codeにも同じ機能がある上、共同開発をしていると人によってインデントサイズが違うことがあるので必要だった。
1. 現在のToDo
Neovimは常に起動していることが多いので、プログラミングに関係なく、やらなきゃいけないことをそこに書いておくことでわかりやすくなると思った。
1. バッファの行数
デフォルトの現在位置やProgressよりも、行数がわかったほうが便利だから
1. ヤンクレジスタの要約
vimでは、ddやxで文字を削除したときもヤンクされるので、間違えてそれをペーストしてしまうことがよくあるため、現在は何がペーストされるのか一目で把握できてほしかった。
1. 稼働中のLSP
しっかりLSPが機能してくれているか確かめるため。
1. 現在時刻
Neovimでの作業中はタスクバーが隠れるので、現在時刻をいちいち確認するのが面倒くさかったから。
# まとめ
Neovimやlualineはもともと便利ですが、カスタマイズすると更に便利になります！みなさんもカスタマイズしてみてください！