自分のデストップに合うNeovimテーマがなかったので、作ってみた。
第1章:はじめに。
デスクトップテーマから始まった
落ち着いた緑を基調にした、自作のデスクトップテーマをこんな感じで整えていました。

ですが、同じ雰囲気のNeovimテーマがない。
既存テーマをカスタマイズしても微妙に理想に届かない。
そこで、自分の手で作るしかないと思い立ちました。
そして作ったのが yoda.nvim です。
この記事で学べること
この記事では、テーマ制作の流れを追いながら以下を学びます。
- Neovimテーマの基本構造
最初は「Hello, Theme!」から始めましょう。
第2章:最初のテーマを作る
colorschemeコマンドの裏側
Neovimのテーマ切り替えは次の1行でできます。
:colorscheme tokyonight <--- 自分の好きなテーマ
Neovimは内部で以下の処理を行います。
-
colors/mytheme.luaを探す - ファイルを実行して色設定を反映する
つまり、テーマとは「色を設定したLuaファイル」なのです。
“Hello, Theme!”
次の3行だけでテーマが動きます。
-- ~/.config/nvim/colors/mytheme.lua
vim.cmd('highlight clear')
vim.o.background = 'dark'
vim.cmd('highlight Normal guibg=#1a1a1a guifg=#e0e0e0')
:colorscheme mytheme を実行すれば背景と文字色が切り替わります。
highlightの基本
highlight は「どの部分を何色で表示するか」を指定します。
vim.cmd('highlight Comment guifg=#608b4e') -- コメント
vim.cmd('highlight String guifg=#ce9178') -- 文字列
vim.cmd('highlight Keyword guifg=#c586c0') -- キーワード
🧩 ハイライトグループとは「UI部品の名前」のこと。
Normal,Comment,Keyword,Stringなどが代表例です。
カーソル位置のグループは :Inspect で確認できます。
これを知っておくだけで、テーマ制作が一気にスムーズになります。
Luaらしい書き方にする
vim.api.nvim_set_hl() を使うと、より整理された記法になります。
local colors = {
bg = '#1a1a1a', fg = '#e0e0e0',
comment = '#608b4e', string = '#ce9178',
keyword = '#c586c0', func = '#dcdcaa',
}
local function hi(group, opts)
vim.api.nvim_set_hl(0, group, opts)
end
hi('Normal', { bg = colors.bg, fg = colors.fg })
hi('Comment', { fg = colors.comment, italic = true })
hi('String', { fg = colors.string })
hi('Keyword', { fg = colors.keyword, bold = true })
hi('Function', { fg = colors.func })
読みやすく、再利用もしやすくなりました。
構造を整える
最終的なディレクトリ構成はこうなります。
mytheme/
├── colors/
│ └── mytheme.lua # エントリーポイント
└── lua/
└── mytheme/
├── init.lua # メインロジック
└── palette.lua # 色定義
colors/mytheme.lua は require('mytheme').load() を呼び出すだけ。
本体の処理は lua/mytheme/init.lua にまとめましょう。
第3章:コアハイライト設計 - エディタに命を吹き込む
Normalを基準に考える
すべての配色は Normal から始まります。
この1行が全体の明暗バランスを決めます。
vim.api.nvim_set_hl(0, 'Normal', { bg = colors.bg, fg = colors.fg })
UI層の階層構造
NeovimのUIは階層的に整理できます。
hi('CursorLine', { bg = colors.bg_light }) -- レベル1
hi('Visual', { bg = colors.selection }) -- レベル2
hi('NormalFloat', { bg = colors.bg_lighter }) -- フロート
hi('CursorLineNr', { fg = colors.accent, bold = true }) -- 注目点
Normal → CursorLine → Visual → Float と段階をつけると、視線の流れが自然になります。
ステータスラインやサイドバー
hi('StatusLine', { bg = colors.bg_status, fg = colors.fg, bold = true })
hi('LineNr', { fg = colors.fg_dim })
hi('SignColumn', { bg = colors.bg })
最低限のUI整備で、もうプロフェッショナルな見た目に。
強調と診断表示
hi('ErrorMsg', { fg = colors.error, bold = true })
hi('WarningMsg', { fg = colors.warning })
hi('Search', { bg = colors.bg_search })
hi('IncSearch', { bg = colors.accent, fg = colors.bg })
⚡ 「常に目に入るが、邪魔しない」
これがテーマ設計の理想です。
第4章:TreeSitterでコードに命を吹き込む
Neovimでは今や TreeSitter が標準的な構文解析エンジン。
文脈を理解したハイライトが可能です。
local h = vim.api.nvim_set_hl
h(0, 'Comment', { fg = colors.comment, italic = true })
h(0, '@comment', { link = 'Comment' })
h(0, 'String', { fg = colors.string })
h(0, '@string', { link = 'String' })
h(0, 'Function', { fg = colors.func })
h(0, '@function', { link = 'Function' })
TreeSitterグループ(@stringなど)はより正確に構造を捉えます。
多色化しすぎず、関連要素を同系色でまとめるのがコツです。
第5章:Telescope対応 - プラグインとの調和
素晴らしいテーマでも、プラグインの色が合わないと台無しです。
代表例として、ファジーファインダー「Telescope」対応を見てみましょう。
-- lua/yoda/plugins/telescope.lua
local h = vim.api.nvim_set_hl
h(0, 'TelescopePromptNormal', { bg = colors.bg_search, fg = colors.fg })
h(0, 'TelescopePromptTitle', { bg = colors.accent, fg = colors.bg })
h(0, 'TelescopeSelection', { bg = colors.bg_highlight, bold = true })
h(0, 'TelescopeMatching', { fg = colors.match, bold = true })
この4つの調整だけで、Telescopeウィンドウがテーマ全体と溶け込みます。
他の主要プラグインも同様の仕組みで対応可能です。
| プラグイン | 機能 |
|---|---|
| Neo-tree | ファイルツリー |
| nvim-cmp | 補完メニュー |
| Gitsigns | Git差分表示 |
| Lualine | ステータスライン |
第6章:カスタマイズできるテーマ設計
ユーザーごとに「こうしたい」が違います。
背景の透明化、コメントの斜体、関数色の変更……
これらを可能にするのが setup() 関数です。
-- lua/yoda/init.lua
local M = {}
M.defaults = {
transparent_background = false,
italic_comments = true,
colors = {},
custom_highlights = {},
}
function M.setup(user_config)
M.config = vim.tbl_deep_extend('force', M.defaults, user_config or {})
end
return M
カスタマイズ例
背景を透明に
require('yoda').setup({
transparent_background = true,
})
独自ハイライトを追加
require('yoda').setup({
custom_highlights = {
Function = { fg = '#ff8800', bold = true },
['@string'] = { fg = '#99cc99' },
}
})
これだけで“自分好みのテーマ”に変えられます。
第7章:公開しよう
完成したらGitHubで公開しましょう。(READMEにはインストール例を載せておくと親切です。)
ほとんどの方がLazyvimを使っているので、公開自体はこれだけで、完了です。
ここまで読んでくださり、ありがとうございました。
あなたのNvimテーマをGithubで見れることを楽しみにしています!
kuri-sun
Discussion