【Neovim】LuaSnipの導入&&設定方法

# LuaSnip？？？
LuaSnipはneovimでスニペットを使えるようにするプラグインです。

設定がとても細かくできる && 簡単にも使える
素晴らしいですね✨️✨️✨️✨️✨️

Githubはこちら ↓↓↓↓↓↓↓↓
https://github.com/L3MON4D3/LuaSnip

> GithubのREADMEのトップにデモ動画があります。こんなに使いこなせたらかっこいいですね………………………………

# インストール
以下のように記述しましょう。Lazy.nvim🎉を使ってます。
```lua:plugin spec
{
	"L3MON4D3/LuaSnip",
	version = "v2.*",
	build = "make install_jsregexp",
    config = function ()
    end,
}
```

# キーマップ
## _WITHOUT NVIM-CMP_
キーマップも設定しましょう！nvim-cmpを使っていない人はREADMEの通りに設定しましょう。
```lua
local ls = require("luasnip")

vim.keymap.set({"i"}, "<C-K>", function() ls.expand() end, {silent = true})
vim.keymap.set({"i", "s"}, "<C-L>", function() ls.jump( 1) end, {silent = true})
vim.keymap.set({"i", "s"}, "<C-J>", function() ls.jump(-1) end, {silent = true})

vim.keymap.set({"i", "s"}, "<C-E>", function()
	if ls.choice_active() then
		ls.change_choice(1)
	end
end, {silent = true})
```

## _WITH NVIM-CMP_
nvim-cmpを使ってる人は

***✞ Super-Tab like mapping ✞***

を使ってみましょう！😎😎😎😎😎

nvim-cmpのドキュメントにExampleが書いてあります。

https://github.com/hrsh7th/nvim-cmp/wiki/Example-mappings#super-tab-like-mapping

nvim.cmpのセットアップに以下を追加しましょう。

```lua
local luasnip = require("luasnip")
local cmp = require("cmp")

cmp.setup({

  -- ... Your other configuration ...

  mapping = {

    -- ... Your other mappings ...
   ['<CR>'] = cmp.mapping(function(fallback)
        if cmp.visible() then
            if luasnip.expandable() then
                luasnip.expand()
            else
                cmp.confirm({
                    select = true,
                })
            end
        else
            fallback()
        end
    end),

    ["<Tab>"] = cmp.mapping(function(fallback)
      if cmp.visible() then
        cmp.select_next_item()
      elseif luasnip.locally_jumpable(1) then
        luasnip.jump(1)
      else
        fallback()
      end
    end, { "i", "s" }),

    ["<S-Tab>"] = cmp.mapping(function(fallback)
      if cmp.visible() then
        cmp.select_prev_item()
      elseif luasnip.locally_jumpable(-1) then
        luasnip.jump(-1)
      else
        fallback()
      end
    end, { "i", "s" }),

    -- ... Your other mappings ...
  },

  -- ... Your other configuration ...
})
```

cmpと連携して、キーマップをいい感じに切り替えてますね。
VSCodeのようにTabを使ってスニペットの入力欄をジャンプできます！！✨✨✨

# スニペットを追加

ここで、公式のREADMEを見ると、

```lua:
-- これを使えばスニペットを追加できるよ！！
require("luasnip").add_snippets(filetype, snippets)
```
https://github.com/L3MON4D3/LuaSnip?tab=readme-ov-file#add-snippets

って書いてありますね。でもその下をよく見ると………………🔎
> This can also be done much cleaner, with all the benefits that come with using a loader, by using the loader for lua

> でも、loaderを使うことで…………更にcleanerな設定にできるよ！！！！！

これは使うしかないですね…………✨✨✨✨
勇敢な戦士であれってことです。

:::note info
`add_snipets()`でも全然スニペットを追加できます。お好みです。
:::

:::note info
この記事ではluaでスニペットを記述できる方法を紹介しますが、実は他にもVSCode-likeに記述できる方法とSnipMate-likeに記述できる方法というのがあります！これらの方がお手軽だったりするので、気になる方は公式DOCを参照してください。
:::

## plugin specを変更
先ほど書いたplugin specに1行追加しましょう。

```diff_lua
{
	"L3MON4D3/LuaSnip",
	version = "v2.*",
	build = "make install_jsregexp",
    config = function ()
+       require("luasnip.loaders.from_lua").load()
    end,
}
```

これでloaderを使うことができます！いよいよスニペットを書いてみましょう。

## スニペットを追加
loaderを使うと、スニペットをファイルに書いてディレクトリに入れておけば自動で読み込んでくれるようになります！✨✨✨✨

#### luasnippetsディレクトリを追加
init.luaと同じ階層に`luasnippets`という名前のディレクトリを追加しましょう。フォルダ階層はこんな感じになります。
```
nvim/
　├ init.lua
　├ luasnippets/
　│　├ 〇〇.lua
　│　└ ...
　└ ...
 ```

#### スニペットファイルを追加
`luasnippets`の中に`{スニペットを追加するFileType名}.lua`というなまえファイルを追加しましょう。
ここでは試しに`all.lua`を追加します。(すべてのFileTypeに対して追加します。例えばReactの.tsxに追加したいなら`typescriptreact.lua`とします。)

#### 作成したファイルに↓↓↓↓を書き込みます。
```lua:all.lua
-- ここではhelloと入力するとprintln("Hello World!")と補完できるスニペットを作成します
local s = ls.snippet
local t = ls.text_node
local i = ls.insert_node

return {
    s("hello", {
        t('println("Hello World!")')
    }),
}
```
`s()`とか`t()`とか妙な名前ですよね………………
でもスニペットを書くときに何回も使うので割と良かったりします。

スニペットの書き方は公式DOC参照↓↓↓↓↓↓↓↓↓

https://github.com/L3MON4D3/LuaSnip/blob/master/DOC.md#basics

(これもそのうち記事にするかもしれません……………気が向いたら🚲)

# 試してみる
これにて完了です！neovimを再起動して適当なファイルにhelloと打ってみましょう。スニペットが使えれば成功です！！🎉


# オマケ
## 自動リロード！？
スニペットファイルを編集すると、なんと自動でファイルをリロードしてすぐにスニペットを使えるようにしてくれます。素敵すぎる💫💫💫💫💫💫

## スニペット楽々編集メニュー😎
`require("luasnip.loaders").edit_snippet_files()`でスニペット楽々編集メニュー😎を出せます。試しにキーバインドして使ってみましょう！

plugin specに以下を追加します。
```diff_lua
{
	"L3MON4D3/LuaSnip",
	version = "v2.*",
	build = "make install_jsregexp",
    config = function ()
+       -- <leader>ss を押すとスニペット楽々編集メニュー😎が表示されます！
+       vim.keymap.set('n', '<leader>ss', require("luasnip.loaders").edit_snippet_files, { desc = "Edit snippets" })
        require("luasnip.loaders.from_lua").load()
    end,
}
```

`<leader>ss`を押すと下のようなメニューが表示されるはずです。

![image.png](https://user-images.githubusercontent.com/25300418/184359420-3bc22d67-1f90-49d9-ac4e-3ea2524bcf0d.gif)

これらを使いこなせば、コードを書いてる途中でもスニペットを追加したくなったらすぐに追加できますね！！✨✨✨✨

# 参考文献
手順はここに書いてあります。

https://github.com/L3MON4D3/LuaSnip/blob/master/DOC.md#lua

`:h luasnip-loaders`にloaderの設定なども書いてあります！