Setup dan Config Neovim Secara Modular di Nixos (LSP, Mason, Telescope, Tresitter, etc)

Cara setup dan config neovim di nixos, lengkap dengan LSP, Mason, Tresitter, Telescope, NeoTree, dll


JagoTekno.com - Jika menggunakan neovim, ada 2 cara untuk setup dan config neovim.

Cara pertama, yaitu install neovim, lalu isi config pada folder ~/.config/nvim/. Ini sama seperti config neovim distro linux pada umumnya.

Cara kedua, yaitu install dan config neovim langsung dari home-manager. Dengan cara ini neovim akan berjalan secara modular.

Tidak perlu lagi menggunakan plugin manager, karena plugin didefinisikan pada konfigurasi nvim di home-manager.

Apa saja yang aktif?

  • LSP
  • Completion
  • Mason
  • Tresitter
  • Telescope
  • Neotree
  • Toggleterm

dan banyak lagi…

Di sini saya akan menunjukkan config neovim yang saya definisikan pada nixos flakes saya, silahkan diedit sesuai kebutuhan.

Jadi langsung saja begini caranya:

Folder structure

.
└── home
    └── neovim
        └── default.nix
            ├── options.lua
            └── plugin
                ├── cmp.lua
                ├── lsp.lua
                ├── telescope.lua
                ├── toggleterm.lua
                └── treesitter.lua

Config default.nix

Pada file default.nix isi dengan :

{config, pkgs, input, ...}:

{
programs.neovim = 
  let
    toLua = str: "lua << EOF\n${str}\nEOF\n";
    toLuaFile = file: "lua << EOF\n${builtins.readFile file}\nEOF\n";
  in
  {
    enable = true;

    defaultEditor = true;
    withNodeJs = true;

    viAlias = true;
    vimAlias = true;

    extraPackages = with pkgs; [
	# install the languages
      rnix-lsp

	# clipboard tool
      xclip
      wl-clipboard

      cargo
    ];


    plugins = with pkgs.vimPlugins; [
	  vim-solarized8

      # status bar
      {
        plugin = lualine-nvim;
        config = toLua "require(\"lualine\").setup({icons_enabled = true, theme = \'solarized8\'})";
      }

#	  nvim-treesitter.withAllGrammars

	  neo-tree-nvim
	  plenary-nvim
	  nui-nvim
	  nvim-web-devicons

      {
        plugin = nvim-treesitter.withAllGrammars;
        config = toLuaFile ./plugin/treesitter.lua;
      }
    
      # completion
      {
        plugin = nvim-cmp;
        config = toLuaFile ./plugin/cmp.lua;
      }
      	## Snippet Engine & its associated nvim-cmp source
	    luasnip
      	cmp_luasnip

      	## Adds LSP completion capabilities
      	cmp-nvim-lsp
      	cmp-path

      	# Adds a number of user-friendly snippets
      	friendly-snippets


      # LSP
      {
        plugin = mason-nvim;
        config = toLuaFile ./plugin/lsp.lua;
      }
	  mason-lspconfig-nvim
      nvim-lspconfig
      neodev-nvim

	#comment
      {
        plugin = comment-nvim;
        config = toLua "require(\"Comment\").setup()";
      }

	# telescope
      {
        plugin = telescope-nvim;
        config = toLuaFile ./plugin/telescope.lua;
      }
	# include this with telescope
      telescope-fzf-native-nvim

	# toggleterm
      {
        plugin = toggleterm-nvim;
        config = toLuaFile ./plugin/toggleterm.lua;
      }

      vim-nix

];
    

    extraLuaConfig = ''
      ${builtins.readFile ./options.lua}
    '';
  };


}

Options.lua

Kemudian pada file options.lua set dengan config options lua anda:

-- this is kickstart.nvim from teej
-- Set <space> as the leader key
-- See `:help mapleader`
--  NOTE: Must happen before plugins are required (otherwise wrong leader will be used)
vim.g.mapleader = ' '
vim.g.maplocalleader = ' '

-- from my old option config
vim.keymap.set("v", "K", ":m '<-2<CR>gv=gv")
vim.keymap.set("v", "J", ":m '>+1<CR>gv=gv")

vim.keymap.set("n", "J", "mzJ`z")
vim.keymap.set("n", "<C-d>", "<C-d>zz")
vim.keymap.set("n", "<C-u>", "<C-u>zz")
vim.keymap.set("n", "n", "nzzzv")
vim.keymap.set("n", "N", "Nzzzv")

-- greatest remap ever
vim.keymap.set("x", "<leader>p", [["_dP]])

-- next greatest remap ever : asbjornHaland
vim.keymap.set({"n", "v"}, "<leader>y", [["+y]])
vim.keymap.set("n", "<leader>Y", [["+Y]])

vim.keymap.set({"n", "v"}, "<leader>d", [["_d]])

-- This is going to get me cancelled
vim.keymap.set("i", "<C-c>", "<Esc>")

vim.keymap.set("n", "Q", "<nop>")
vim.keymap.set("n", "<leader>f", vim.lsp.buf.format)

vim.keymap.set("n", "<C-k>", "<cmd>cnext<CR>zz")
vim.keymap.set("n", "<C-j>", "<cmd>cprev<CR>zz")
vim.keymap.set("n", "<leader>k", "<cmd>lnext<CR>zz")
vim.keymap.set("n", "<leader>j", "<cmd>lprev<CR>zz")

vim.keymap.set("n", "<leader>x", "<cmd>!chmod +x %<CR>", { silent = true })

-- Navigate vim panes better
vim.keymap.set('n', '<c-k>', ':wincmd k<CR>')
vim.keymap.set('n', '<c-j>', ':wincmd j<CR>')
vim.keymap.set('n', '<c-h>', ':wincmd h<CR>')
vim.keymap.set('n', '<c-l>', ':wincmd l<CR>')

-- call neotree
vim.keymap.set('n', '<F4>', ':Neotree right toggle<CR>')

vim.o.relativenumber = true -- set relative numbered lines

vim.g.maplocalleader = ' '

vim.o.backspace = '2'
vim.o.showcmd = true
vim.o.laststatus = 2
vim.o.autoread = true
vim.o.shiftround = true

vim.o.pumheight = 10                          -- pop up menu height
vim.o.showmode = false                        -- we don't need to see things like -- INSERT -- anymore

vim.o.splitbelow = true                       -- force all horizontal splits to go below current window
vim.o.splitright = true                       -- force all vertical splits to go to the right of current window
vim.o.swapfile = false                        -- creates a swapfile

vim.o.writebackup = false                     -- if a file is being edited by another program (or was written to file while editing with another program), it is not allowed to be edited
vim.o.expandtab = true                        -- convert tabs to spaces
vim.o.shiftwidth = 4                          -- the number of spaces inserted for each indentation
vim.o.tabstop = 4                             -- insert 2 spaces for a tab

vim.o.conceallevel = 0
vim.o.wrap = false                            -- display lines as one long line
vim.o.linebreak = true                        -- companion to wrap, don't split words
vim.o.scrolloff = 8                           -- minimal number of screen lines to keep above and below the cursor
vim.o.sidescrolloff = 8                       -- minimal number of screen columns either side of cursor if wrap is `false`
vim.o.guifont = "monospace:h17"               -- the font used in graphical neovim applications
vim.o.whichwrap = "bs<>[]hl"                  -- which "horizontal" keys are allowed to travel to prev/next line

-- end from my option config

-- Set highlight on search
vim.o.hlsearch = false

-- Make line numbers default
vim.wo.number = true

-- Enable mouse mode
vim.o.mouse = 'a'

-- Sync clipboard between OS and Neovim.
--  Remove this option if you want your OS clipboard to remain independent.
--  See `:help 'clipboard'`
vim.o.clipboard = 'unnamedplus'

-- Enable break indent
vim.o.breakindent = true

-- Save undo history
vim.o.undofile = true

-- Case-insensitive searching UNLESS \C or capital in search
vim.o.ignorecase = true
vim.o.smartcase = true

-- Keep signcolumn on by default
vim.wo.signcolumn = 'yes'

-- Decrease update time
vim.o.updatetime = 250
vim.o.timeoutlen = 300

-- Set completeopt to have a better completion experience
vim.o.completeopt = 'menuone,noselect'

-- NOTE: You should make sure your terminal supports this
vim.o.termguicolors = true

-- set solarize color scheme
-- vim.cmd("set background=dark")
vim.cmd.colorscheme 'solarized8'

-- teej kickstart feature
-- [[ Highlight on yank ]]
-- See `:help vim.highlight.on_yank()`
local highlight_group = vim.api.nvim_create_augroup('YankHighlight', { clear = true })
vim.api.nvim_create_autocmd('TextYankPost', {
  callback = function()
    vim.highlight.on_yank()
  end,
  group = highlight_group,
  pattern = '*',
})

-- Lualine
-- require("lualine").setup({
--     icons_enabled = true,
--     -- theme = 'onedark',
--     -- theme = 'solarized',
-- })

Completion

Kemudian pada file plugin/cmp.lua isi dengan ini:

-- teej kickstart neovim completion config
-- nvim-cmp supports additional completion capabilities, so broadcast that to servers
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities)

-- [[ Configure nvim-cmp ]]
-- See `:help cmp`
local cmp = require 'cmp'
local luasnip = require 'luasnip'
require('luasnip.loaders.from_vscode').lazy_load()
luasnip.config.setup {}

cmp.setup {
  snippet = {
    expand = function(args)
      luasnip.lsp_expand(args.body)
    end,
  },
  completion = {
    completeopt = 'menu,menuone,noinsert',
  },
  mapping = cmp.mapping.preset.insert {
    ['<C-n>'] = cmp.mapping.select_next_item(),
    ['<C-p>'] = cmp.mapping.select_prev_item(),
    ['<C-b>'] = cmp.mapping.scroll_docs(-4),
    ['<C-f>'] = cmp.mapping.scroll_docs(4),
    ['<C-Space>'] = cmp.mapping.complete {},
    ['<CR>'] = cmp.mapping.confirm {
      behavior = cmp.ConfirmBehavior.Replace,
      select = true,
    },
    ['<Tab>'] = cmp.mapping(function(fallback)
      if cmp.visible() then
        cmp.select_next_item()
      elseif luasnip.expand_or_locally_jumpable() then
        luasnip.expand_or_jump()
      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' }),
  },
  sources = {
    { name = 'nvim_lsp' },
    { name = 'luasnip' },
    { name = 'path' },
  },
}

LSP

Kemudian pada file plugin/lsp.lua isi dengan ini:


-- before setting up the servers.
require('mason').setup()
require('mason-lspconfig').setup()

local servers = {
  lua_ls = {
    Lua = {
      workspace = { checkThirdParty = false },
      telemetry = { enable = false },
    },
  },
}

-- Setup neovim lua configuration
require('neodev').setup()

-- nvim-cmp supports additional completion capabilities, so broadcast that to servers
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities)

-- Ensure the servers above are installed
local mason_lspconfig = require 'mason-lspconfig'

mason_lspconfig.setup {
  ensure_installed = vim.tbl_keys(servers),
}

mason_lspconfig.setup_handlers {
  function(server_name)
    require('lspconfig')[server_name].setup {
      capabilities = capabilities,
      on_attach = on_attach,
      settings = servers[server_name],
      filetypes = (servers[server_name] or {}).filetypes,
    }
  end,
}

Telescope

Pada file plugin/telescope.lua isi dengan config ini:


require('telescope').setup({
	extensions = {
		fzf = {
			fuzzy = true,                    -- false will only do exact matching
			override_generic_sorter = true,  -- override the generic sorter
			override_file_sorter = true,     -- override the file sorter
			case_mode = "smart_case",        -- or "ignore_case" or "respect_case"
			-- the default case_mode is "smart_case"
		}
	}
})

local builtin = require('telescope.builtin')

--vim.keymap.set('n', '<c-p>', builtin.find_files, {})
vim.keymap.set('n', '<Space>ff', builtin.find_files, {})
vim.keymap.set('n', '<Space><Space>', builtin.oldfiles, {})
vim.keymap.set('n', '<Space>fg', builtin.live_grep, {})
vim.keymap.set('n', '<Space>fh', builtin.help_tags, {})

require('telescope').load_extension('fzf')

Toggleterm

local status_ok, toggleterm = pcall(require, "toggleterm")
if not status_ok then
	return
end

toggleterm.setup({
	size = 10,
	open_mapping = [[<c-\>]], -- then to open new terminal type 2<c-\>, 3<c-\> and so on
	hide_numbers = true,
	shade_filetypes = {},
	shade_terminals = true,
	shading_factor = 2,
	start_in_insert = true,
	insert_mappings = true,
	persist_size = true,
	direction = "horizontal",
	close_on_exit = true,
	shell = vim.o.shell,
	float_opts = {
		border = "curved",
		winblend = 0,
		highlights = {
			border = "Normal",
			background = "Normal",
		},
	},
})

function _G.set_terminal_keymaps()
  local opts = {noremap = true}
  vim.api.nvim_buf_set_keymap(0, 't', '<esc>', [[<C-\><C-n>]], opts)
  vim.api.nvim_buf_set_keymap(0, 't', 'jk', [[<C-\><C-n>]], opts)
  vim.api.nvim_buf_set_keymap(0, 't', '<C-h>', [[<C-\><C-n><C-W>h]], opts)
  vim.api.nvim_buf_set_keymap(0, 't', '<C-j>', [[<C-\><C-n><C-W>j]], opts)
  vim.api.nvim_buf_set_keymap(0, 't', '<C-k>', [[<C-\><C-n><C-W>k]], opts)
  vim.api.nvim_buf_set_keymap(0, 't', '<C-l>', [[<C-\><C-n><C-W>l]], opts)
end

vim.cmd('autocmd! TermOpen term://* lua set_terminal_keymaps()')

local Terminal = require("toggleterm.terminal").Terminal

local lazygit = Terminal:new({ cmd = "lazygit", hidden = true })

function _LAZYGIT_TOGGLE()
	lazygit:toggle()
end

-- vim.api.nvim_set_keymap("n", "<leader>tg", "<cmd>lua _lazygit_toggle()<CR>", {noremap = true, silent = true})

local node = Terminal:new({ cmd = "node", hidden = true })

function _NODE_TOGGLE()
	node:toggle()
end

vim.api.nvim_set_keymap("n", "<leader>tn", "<cmd>lua _NODE_TOGGLE()<CR>", {noremap = true, silent = true})

local ncdu = Terminal:new({ cmd = "ncdu", hidden = true })

function _NCDU_TOGGLE()
	ncdu:toggle()
end

local htop = Terminal:new({ cmd = "htop", hidden = true })

function _HTOP_TOGGLE()
	htop:toggle()
end

local python = Terminal:new({ cmd = "python", hidden = true })

function _PYTHON_TOGGLE()
	python:toggle()
end

Treesitter


-- teej kickstart neovim config
vim.defer_fn(function()
  require('nvim-treesitter.configs').setup {
    -- Add languages to be installed here that you want installed for treesitter
    -- ensure_installed = { 'c', 'cpp', 'go', 'lua', 'python', 'rust', 'tsx', 'javascript', 'typescript', 'vimdoc', 'vim', 'bash' },
    ensure_installed = {},

    -- Autoinstall languages that are not installed. Defaults to false (but you can change for yourself!)
    auto_install = false,

    highlight = { enable = true },
    indent = { enable = true },
    incremental_selection = {
      enable = true,
      keymaps = {
        init_selection = '<c-space>',
        node_incremental = '<c-space>',
        scope_incremental = '<c-s>',
        node_decremental = '<M-space>',
      },
    },
    textobjects = {
      select = {
        enable = true,
        lookahead = true, -- Automatically jump forward to textobj, similar to targets.vim
        keymaps = {
          -- You can use the capture groups defined in textobjects.scm
          ['aa'] = '@parameter.outer',
          ['ia'] = '@parameter.inner',
          ['af'] = '@function.outer',
          ['if'] = '@function.inner',
          ['ac'] = '@class.outer',
          ['ic'] = '@class.inner',
        },
      },
      move = {
        enable = true,
        set_jumps = true, -- whether to set jumps in the jumplist
        goto_next_start = {
          [']m'] = '@function.outer',
          [']]'] = '@class.outer',
        },
        goto_next_end = {
          [']M'] = '@function.outer',
          [']['] = '@class.outer',
        },
        goto_previous_start = {
          ['[m'] = '@function.outer',
          ['[['] = '@class.outer',
        },
        goto_previous_end = {
          ['[M'] = '@function.outer',
          ['[]'] = '@class.outer',
        },
      },
      swap = {
        enable = true,
        swap_next = {
          ['<leader>a'] = '@parameter.inner',
        },
        swap_previous = {
          ['<leader>A'] = '@parameter.inner',
        },
      },
    },
  }
end, 0)

Demikian full setup config neovim secara modular pada nixos.

Inspirasi mendapatkan config ini adalah dari nvim.kickstart.

2 Contoh Cara Mengimplementasikan Dark Mode pada Halaman HTML: Panduan Praktis
Ditulis oleh Rafi pada Tuesday, 16 January 2024
mrfdn author

Rafi

  • 15 year+ of Linux user.
  • 5 years+ blogger and web developer.

Jika artikel yang dibuatnya ternyata bermanfaat, support dengan cara

    Share:

Baca juga


comments powered by Disqus