The 300 line init.lua challenge

Hi all,

I recently saw a reddit post that claims neovim is hard to configure and unapproachable for beginners. I personally don’t feel that writing some lua and installing a few plugins should take anyone who is presumably using neovim to write software more than an hour or so. However, I thought it would be fun to turn this into a game to create the most featureful, yet approachable init.lua.

Post your init.lua inline using (ignore the dot, before the second set of backticks)

<details><summary>My (298 line) init.lua </summary>
```lua
your code here
.```
</details>

Rules:

  • Your config can be a maximum of 300 lines, with a maximum column length of 110 chars
  • It must be predominantly (>90 %) lua
  • It must bootstrap itself (as in, it includes detecting and installing its own plugin manager)
  • No cheating, that means no custom vim-sensible type bundling plugins
  • Your config must be heavily commented and contain enough blank space such that it is readable (I will be very subjective in disqualifications)
  • You will be judged on features, readability, and broad appeal (probably best not to include very esoteric key bindings)
  • You can edit your config after seeing other submissions, but try not to copy/paste
  • Post a couple lines explaining the key features/essential components of your config

There may or may not be a prize. Presumably we can make the winner stickied and visible for beginners. I’ll volunteer to go first.

My init.lua
-- Install packer
local install_path = vim.fn.stdpath 'data' .. '/site/pack/packer/start/packer.nvim'

if vim.fn.empty(vim.fn.glob(install_path)) > 0 then
  vim.fn.execute('!git clone https://github.com/wbthomason/packer.nvim ' .. install_path)
end

vim.cmd [[
  augroup Packer
    autocmd!
    autocmd BufWritePost init.lua PackerCompile
  augroup end
]]

local use = require('packer').use
require('packer').startup(function()
  use 'wbthomason/packer.nvim' -- Package manager
  use 'tpope/vim-fugitive' -- Git commands in nvim
  use 'tpope/vim-rhubarb' -- Fugitive-companion to interact with github
  use 'tpope/vim-commentary' -- "gc" to comment visual regions/lines
  use 'ludovicchabant/vim-gutentags' -- Automatic tags management
  -- UI to select things (files, grep results, open buffers...)
  use { 'nvim-telescope/telescope.nvim', requires = { 'nvim-lua/plenary.nvim' } }
  use 'joshdick/onedark.vim' -- Theme inspired by Atom
  use 'itchyny/lightline.vim' -- Fancier statusline
  -- Add indentation guides even on blank lines
  use 'lukas-reineke/indent-blankline.nvim'
  -- Add git related info in the signs columns and popups
  use { 'lewis6991/gitsigns.nvim', requires = { 'nvim-lua/plenary.nvim' } }
  -- Highlight, edit, and navigate code using a fast incremental parsing library
  use 'nvim-treesitter/nvim-treesitter'
  -- Additional textobjects for treesitter
  use 'nvim-treesitter/nvim-treesitter-textobjects'
  use 'neovim/nvim-lspconfig' -- Collection of configurations for built-in LSP client
  use 'hrsh7th/nvim-cmp' -- Autocompletion plugin
  use 'hrsh7th/cmp-nvim-lsp'
  use 'saadparwaiz1/cmp_luasnip'
  use 'L3MON4D3/LuaSnip' -- Snippets plugin
end)

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

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

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

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

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

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

--Decrease update time
vim.o.updatetime = 250
vim.wo.signcolumn = 'yes'

--Set colorscheme (order is important here)
vim.o.termguicolors = true
vim.g.onedark_terminal_italics = 2
vim.cmd [[colorscheme onedark]]

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

--Set statusbar
vim.g.lightline = {
  colorscheme = 'onedark',
  active = { left = { { 'mode', 'paste' }, { 'gitbranch', 'readonly', 'filename', 'modified' } } },
  component_function = { gitbranch = 'fugitive#head' },
}

--Remap space as leader key
vim.api.nvim_set_keymap('', '<Space>', '<Nop>', { noremap = true, silent = true })
vim.g.mapleader = ' '
vim.g.maplocalleader = ' '

--Remap for dealing with word wrap
vim.api.nvim_set_keymap('n', 'k', "v:count == 0 ? 'gk' : 'k'", { noremap = true, expr = true, silent = true })
vim.api.nvim_set_keymap('n', 'j', "v:count == 0 ? 'gj' : 'j'", { noremap = true, expr = true, silent = true })

-- Highlight on yank
vim.cmd [[
  augroup YankHighlight
    autocmd!
    autocmd TextYankPost * silent! lua vim.highlight.on_yank()
  augroup end
]]

--Map blankline
vim.g.indent_blankline_char = '┊'
vim.g.indent_blankline_filetype_exclude = { 'help', 'packer' }
vim.g.indent_blankline_buftype_exclude = { 'terminal', 'nofile' }
vim.g.indent_blankline_show_trailing_blankline_indent = false

-- Gitsigns
require('gitsigns').setup {
  signs = {
    add = { hl = 'GitGutterAdd', text = '+' },
    change = { hl = 'GitGutterChange', text = '~' },
    delete = { hl = 'GitGutterDelete', text = '_' },
    topdelete = { hl = 'GitGutterDelete', text = '‾' },
    changedelete = { hl = 'GitGutterChange', text = '~' },
  },
}

-- Telescope
require('telescope').setup {
  defaults = {
    mappings = {
      i = {
        ['<C-u>'] = false,
        ['<C-d>'] = false,
      },
    },
  },
}
--Add leader shortcuts
vim.api.nvim_set_keymap('n', '<leader><space>', [[<cmd>lua require('telescope.builtin').buffers()<CR>]], { noremap = true, silent = true })
vim.api.nvim_set_keymap('n', '<leader>sf', [[<cmd>lua require('telescope.builtin').find_files({previewer = false})<CR>]], { noremap = true, silent = true })
vim.api.nvim_set_keymap('n', '<leader>sb', [[<cmd>lua require('telescope.builtin').current_buffer_fuzzy_find()<CR>]], { noremap = true, silent = true })
vim.api.nvim_set_keymap('n', '<leader>sh', [[<cmd>lua require('telescope.builtin').help_tags()<CR>]], { noremap = true, silent = true })
vim.api.nvim_set_keymap('n', '<leader>st', [[<cmd>lua require('telescope.builtin').tags()<CR>]], { noremap = true, silent = true })
vim.api.nvim_set_keymap('n', '<leader>sd', [[<cmd>lua require('telescope.builtin').grep_string()<CR>]], { noremap = true, silent = true })
vim.api.nvim_set_keymap('n', '<leader>sp', [[<cmd>lua require('telescope.builtin').live_grep()<CR>]], { noremap = true, silent = true })
vim.api.nvim_set_keymap('n', '<leader>so', [[<cmd>lua require('telescope.builtin').tags{ only_current_buffer = true }<CR>]], { noremap = true, silent = true })
vim.api.nvim_set_keymap('n', '<leader>?', [[<cmd>lua require('telescope.builtin').oldfiles()<CR>]], { noremap = true, silent = true })

-- Treesitter configuration
-- Parsers must be installed manually via :TSInstall
require('nvim-treesitter.configs').setup {
  highlight = {
    enable = true, -- false will disable the whole extension
  },
  incremental_selection = {
    enable = true,
    keymaps = {
      init_selection = 'gnn',
      node_incremental = 'grn',
      scope_incremental = 'grc',
      node_decremental = 'grm',
    },
  },
  indent = {
    enable = true,
  },
  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
        ['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',
      },
    },
  },
}

-- LSP settings
local lspconfig = require 'lspconfig'
local on_attach = function(_, bufnr)
  local opts = { noremap = true, silent = true }
  vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gD', '<cmd>lua vim.lsp.buf.declaration()<CR>', opts)
  vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gd', '<cmd>lua vim.lsp.buf.definition()<CR>', opts)
  vim.api.nvim_buf_set_keymap(bufnr, 'n', 'K', '<cmd>lua vim.lsp.buf.hover()<CR>', opts)
  vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opts)
  vim.api.nvim_buf_set_keymap(bufnr, 'n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
  vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
  vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
  vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
  vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
  vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
  vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
  vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>ca', '<cmd>lua vim.lsp.buf.code_action()<CR>', opts)
  vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>e', '<cmd>lua vim.diagnostic.open_float()<CR>', opts)
  vim.api.nvim_buf_set_keymap(bufnr, 'n', '[d', '<cmd>lua vim.diagnostic.goto_prev()<CR>', opts)
  vim.api.nvim_buf_set_keymap(bufnr, 'n', ']d', '<cmd>lua vim.diagnostic.goto_next()<CR>', opts)
  vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>q', '<cmd>lua vim.diagnostic.setloclist()<CR>', opts)
  vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>so', [[<cmd>lua require('telescope.builtin').lsp_document_symbols()<CR>]], opts)
  vim.cmd [[ command! Format execute 'lua vim.lsp.buf.formatting()' ]]
end

-- nvim-cmp supports additional completion capabilities
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities = require('cmp_nvim_lsp').update_capabilities(capabilities)

-- Enable the following language servers
local servers = { 'clangd', 'rust_analyzer', 'pyright', 'tsserver' }
for _, lsp in ipairs(servers) do
  lspconfig[lsp].setup {
    on_attach = on_attach,
    capabilities = capabilities,
  }
end

-- Example custom server
-- Make runtime files discoverable to the server
local runtime_path = vim.split(package.path, ';')
table.insert(runtime_path, 'lua/?.lua')
table.insert(runtime_path, 'lua/?/init.lua')

lspconfig.sumneko_lua.setup {
  cmd = { vim.fn.getenv 'HOME' .. '/.local/bin/sumneko_lua/bin/Linux/lua-language-server' },
  on_attach = on_attach,
  capabilities = capabilities,
  settings = {
    Lua = {
      runtime = {
        -- Tell the language server which version of Lua you're using (most likely LuaJIT in the case of Neovim)
        version = 'LuaJIT',
        -- Setup your lua path
        path = runtime_path,
      },
      diagnostics = {
        -- Get the language server to recognize the `vim` global
        globals = { 'vim' },
      },
      workspace = {
        -- Make the server aware of Neovim runtime files
        library = vim.api.nvim_get_runtime_file('', true),
      },
      -- Do not send telemetry data containing a randomized but unique identifier
      telemetry = {
        enable = false,
      },
    },
  },
}

-- luasnip setup
local luasnip = require 'luasnip'

-- nvim-cmp setup
local cmp = require 'cmp'
cmp.setup {
  snippet = {
    expand = function(args)
      luasnip.lsp_expand(args.body)
    end,
  },
  mapping = {
    ['<C-p>'] = cmp.mapping.select_prev_item(),
    ['<C-n>'] = cmp.mapping.select_next_item(),
    ['<C-d>'] = cmp.mapping.scroll_docs(-4),
    ['<C-f>'] = cmp.mapping.scroll_docs(4),
    ['<C-Space>'] = cmp.mapping.complete(),
    ['<C-e>'] = cmp.mapping.close(),
    ['<CR>'] = cmp.mapping.confirm {
      behavior = cmp.ConfirmBehavior.Replace,
      select = true,
    },
  },
  sources = {
    { name = 'nvim_lsp' },
    { name = 'luasnip' },
  },
}
15 Likes

My Neovim config is way too “bloated” to be able to strip it down to something like this :slight_smile: But I love these kinds of threads because I get to learn about lots of interesting plugins that other people use, and arcane Vim options that even after years of use I still don’t know about (or forgot about).

4 Likes

This is a pretty standard neovim config, mainly for c++, lua and markdown projects.

Selfmade features are:

  • Session management
  • cd to root of project or current files directory
  • Lots of mappings (of which some may be useful for others)
My (293) lines init.lua copied (and compacted) from my lua directory
-- Install packer (did not have that, so I shamelessly copied it)
local execute = vim.api.nvim_command
local install_path = vim.fn.stdpath('data')..'/site/pack/packer/opt/packer.nvim'

if vim.fn.empty(vim.fn.glob(install_path)) > 0 then
  execute('!git clone https://github.com/wbthomason/packer.nvim '..install_path)
end

-- mapping and settings helpers
local utils = {}

function utils.map(type, key, value, opts) -- the other functions are just for more vim-feel usage
  local options = opts or {}
  vim.api.nvim_set_keymap(type, key, value, options)
end
function utils.noremap(type, key, value, opts)
  local options = {noremap = true}
  if opts then
    options = vim.tbl_extend('force', options, opts)
  end
  vim.api.nvim_set_keymap(type,key,value, options)
end
function utils.nnoremap(key, value, opts)
  utils.noremap('n', key, value, opts)
end
function utils.inoremap(key, value, opts)
  utils.noremap('i', key, value, opts)
end
function utils.vnoremap(key, value, opts)
  utils.noremap('v', key, value, opts)
end
function utils.xnoremap(key, value, opts)
  utils.noremap('x', key, value, opts)
end
function utils.tnoremap(key, value, opts)
  utils.noremap('t', key, value, opts)
end
function utils.cnoremap(key, value, opts)
  utils.noremap('c', key, value, opts)
end
function utils.nmap(key, value, opts)
  utils.map('n', key, value, opts)
end
function utils.imap(key, value, opts)
  utils.map('i', key, value, opts)
end
function utils.vmap(key, value, opts)
  utils.map('v', key, value, opts)
end
function utils.tmap(key, value, opts)
  utils.map('t', key, value, opts)
end

P = function(stuff) return print(vim.inspect(stuff)) end

-- SET OPTS --> EG --> opt('b', 'expandtab', true)
local scopes = {o = vim.o, b = vim.bo, w = vim.wo, g = vim.g}
function utils.opt(scope, key, value)
  scopes[scope][key] = value
  if scope ~= 'o' then scopes['o'][key] = value end
end

-- ===== real config starts here =====
local g = vim.g
local o = vim.o

g.mapleader = ','
g.tex_flavor = "latex"

utils.opt('w', 'number', true)
utils.opt('w', 'relativenumber', true)
-- faster macros
utils.opt('o', 'lazyredraw', true)
-- matching parenthesis
utils.opt('o', 'showmatch', true)
-- switch buffer without saving them
utils.opt('o', 'hidden', true)
-- better searching
utils.opt('o', 'ignorecase', true)
utils.opt('o', 'smartcase', true)
utils.opt('o', 'hlsearch', false)
-- show lines bellow cursor
utils.opt('o', 'scrolloff', 5)
utils.opt('o', 'sidescrolloff', 5)
-- tab config
utils.opt('b', 'expandtab', true)
utils.opt('b', 'shiftwidth', 2)
utils.opt('b', 'tabstop', 2)
utils.opt('b', 'softtabstop', 2)
-- split in reasonable positions
utils.opt('o', 'splitright', true)
utils.opt('o', 'splitbelow', true)
--folds
utils.opt('w', 'foldmethod', 'expr')
utils.opt('w', 'foldexpr', 'nvim_treesitter#foldexpr()')
utils.opt('o', 'foldlevelstart', 99)
o.formatoptions = o.formatoptions:gsub("r", ""):gsub("o", "")

-- ===== plugins =====
vim.cmd [[packadd packer.nvim]]
require('packer').startup(function(use)
  use {'wbthomason/packer.nvim', opt = true}
  use {'tpope/vim-fugitive'}
  use {'dylanaraps/wal.vim'}
  use {'morhetz/gruvbox'}
  use {'neovim/nvim-lspconfig'}
  use {'nvim-treesitter/nvim-treesitter'}
  use {'nvim-lua/completion-nvim'}
  use {'nvim-lua/popup.nvim'}
  use {'nvim-lua/plenary.nvim'}
  use {'nvim-telescope/telescope.nvim'}
  use {'SirVer/ultisnips'}
  use {'honza/vim-snippets'}
  use {'norcalli/nvim-colorizer.lua', config = [[require"colorizer".setup()]]}
  use {'~/repos/nvim-commenter'}
  use {'nvim-telescope/telescope-bibtex.nvim', config = [[require"telescope".load_extension("bibtex")]], ft = 'tex'}
end)
-- update plugins
vim.cmd([[autocmd BufWritePost plugins.lua PackerCompile]])

-- ===== colorsheme settings =====
vim.cmd('syntax on')
vim.o.termguicolors = true
vim.g.gruvbox_contrast_dark="hard"
vim.cmd("colorscheme gruvbox")

-- remove trailing whitespaces
vim.cmd([[autocmd BufWritePre * %s/\s\+$//e]])
-- remove trailing newline
vim.cmd([[autocmd BufWritePre * %s/\n\+\%$//e]])
-- Run xrdb whenever Xdefaults or Xresources are updated.
vim.cmd([[autocmd BufWritePost *xresources !xrdb %]])
-- Update binds when sxhkdrc is updated.
vim.cmd([[autocmd BufWritePost *sxhkdrc !pkill -USR1 sxhkd]])

-- ===== mappings =====
-- split resize
utils.nnoremap("<leader>-", "<cmd>vertical resize -10<CR>")
utils.nnoremap("<leader>+", "<cmd>vertical resize +10<CR>")
utils.nnoremap("<leader>_", "<cmd>resize -10<CR>")
utils.nnoremap("<leader>*", "<cmd>resize +10<CR>")
-- split navigation
utils.map("", "<C-h>", "<C-w>h")
utils.map("", "<C-j>", "<C-w>j")
utils.map("", "<C-k>", "<C-w>k")
utils.map("", "<C-l>", "<C-w>l")
-- run command in current line and paste stout into current buffer
utils.nnoremap("Q", "!!$SHELL<CR>")
-- move lines up and down in visual mode
utils.xnoremap("K", ":move '<-2<CR>gv-gv")
utils.xnoremap("J", ":move '>+1<CR>gv-gv")
-- useful bindings
utils.inoremap("kj", "<Esc>")
utils.noremap("", "<Space>", ":")
utils.nnoremap("<leader>ev", "<cmd>vs $MYVIMRC<CR>")
utils.nnoremap("<leader>sv", "<cmd>source $MYVIMRC<CR>")
-- quote quickly
utils.inoremap('<leader>"', '<Esc>viw<Esc>a"<Esc>bi"<Esc>leli')
utils.vnoremap('<leader>"', '<Esc>`<i"<Esc>`>ea"<Esc>')
-- substitute shortcut
utils.nnoremap("S", ":%s//g<Left><Left>")
utils.vnoremap("S", ":s//g<Left><Left>")
-- quickfix navigation
utils.nnoremap("<leader>q", "<cmd>cnext<cr>")
utils.nnoremap("<leader>Q", "<cmd>cprev<cr>")
-- spellcheck
utils.nnoremap("<leader>sp", ":setlocal spell spelllang=de")
-- more reachable line start/end
utils.nnoremap("H", "^")
utils.nnoremap("L", "$")
-- write to ----READONLY---- files
utils.cnoremap("w!!",  "execute 'silent! write !sudo tee % >/dev/null' <bar> edit!")
-- nvim-commenter
utils.vnoremap("<leader>x", "<cmd>MultiCommenterToggle<cr>")
utils.nnoremap("<leader>x", "<cmd>SingleCommenterToggle<cr>")
-- terminal mappings
utils.tnoremap("<Esc>", "<C-\\><C-n>")
utils.nnoremap("<leader>t", "<cmd>sp | term<cr>")
-- termdebugger
utils.nnoremap("<leader>dd", ":TermdebugCommand")

-- ===== find project root for quick cd =====
local api = vim.api
function find_project_root()
  local id = [[.git]]
  local file = api.nvim_buf_get_name(0)
  local root = vim.fn.finddir(id, file .. ';')
  if root ~= "" then
    root = root:gsub(id, '')
    print(root)
    vim.api.nvim_set_current_dir(root)
  else
    print("No repo found.")
  end
end
-- smart cwd
utils.nnoremap("cf", "<cmd>cd %:p:h | pwd<cr>")
utils.nnoremap("cr", "<cmd>lua find_project_root()<cr>")
-- tab for completion menu
utils.inoremap("<Tab>", 'pumvisible() ? "\\<C-n>" : "\\<Tab>"', {expr = true})
utils.inoremap("<S-Tab>", 'pumvisible() ? "\\<C-p>" : "\\<Tab>"', {expr = true})

-- ===== statusline =====
local stl = {' %M', ' %y', ' %r', ' %{pathshorten(expand("%:p"))}', ' %{FugitiveStatusline()}',
  '%=', ' %c:%l/%L'
}
vim.o.statusline = table.concat(stl)

-- ===== telescope setup =====
require('telescope').setup{
  --defaults excluded to reduce lines :P
}
utils.nnoremap('<leader>b', '<cmd>Telescope buffers<cr>')
utils.nnoremap('<leader>o', '<cmd>Telescope find_files<cr>')
utils.nnoremap('<leader>h', '<cmd>Telescope oldfiles<cr>')
utils.nnoremap('<leader>c', '<cmd>Telescope commands<cr>')
utils.nnoremap('<leader>ch', '<cmd>Telescope command_history<cr>')
utils.nnoremap('<leader>f', '<cmd>Telescope live_grep<cr>')
utils.nnoremap('<leader>z', '<cmd>Telescope spell_suggest<cr>')
utils.noremap('','<F1>', '<cmd>Telescope help_tags<cr>')

-- ===== simple session management =====
local session_dir = vim.fn.stdpath('data') .. '/sessions/'
utils.nnoremap('<leader>ss', ':mks! ' .. session_dir)
utils.nnoremap('<leader>sr', ':%bd | so ' .. session_dir)

-- ===== completion settings =====
vim.o.completeopt="menuone,noinsert,noselect"
vim.g.completion_matching_strategy_list = {'exact', 'substring', 'fuzzy'}
vim.g.completion_enable_snippet = 'UltiSnips'
vim.g.completion_matching_ignore_case = 1
vim.g.completion_trigger_keyword_length = 3

-- ===== snippets =====
vim.g.UltiSnipsExpandTrigger='<leader>s'
vim.g.UltiSnipsListSnippets='<c-l>'
vim.g.UltiSnipsJumpForwardTrigger='<c-b>'
vim.g.UltiSnipsJumpBackwardTrigger='<c-z>'
vim.g.UltiSnipsEditSplit='vertical'

-- ===== lsp setup =====
local custom_attach = function(client)
	print("LSP started.");
	require'completion'.on_attach(client)
  vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with(
    vim.lsp.diagnostic.on_publish_diagnostics, { virtual_text = false, update_in_insert = false }
  )
  -- automatic diagnostics popup
  vim.api.nvim_command('autocmd CursorHold <buffer> lua vim.lsp.diagnostic.show_line_diagnostics()')
  -- speedup diagnostics popup
  vim.o.updatetime=1000
  utils.nnoremap('gD','<cmd>lua vim.lsp.buf.declaration()<CR>')
  utils.nnoremap('<c-]>','<cmd>lua vim.lsp.buf.definition()<CR>')
  utils.nnoremap('K','<cmd>lua vim.lsp.buf.hover()<CR>')
  utils.nnoremap('gr','<cmd>lua vim.lsp.buf.references()<CR>')
  utils.nnoremap('gs','<cmd>lua vim.lsp.buf.signature_help()<CR>')
  utils.nnoremap('gi','<cmd>lua vim.lsp.buf.implementation()<CR>')
  utils.nnoremap('<F5>','<cmd>lua vim.lsp.buf.code_action()<CR>')
  utils.nnoremap('<leader>r','<cmd>lua vim.lsp.buf.rename()<CR>')
  utils.nnoremap('<leader>=', '<cmd>lua vim.lsp.buf.formatting()<CR>')
  utils.nnoremap('<leader>d', '<cmd>lua vim.lsp.diagnostic.goto_next()<CR>')
  utils.nnoremap('<leader>D', '<cmd>lua vim.lsp.diagnostic.goto_prev()<CR>')
end
-- setup all lsp servers here
local nvim_lsp = require'lspconfig'
nvim_lsp.clangd.setup{on_attach=custom_attach}
nvim_lsp.bashls.setup{on_attach=custom_attach}
nvim_lsp.texlab.setup{on_attach=custom_attach}
nvim_lsp.pyls.setup{on_attach=custom_attach}
nvim_lsp.tsserver.setup{on_attach=custom_attach}
nvim_lsp.sumneko_lua.setup{
  cmd = {'lua-language-server'},
  on_attach=custom_attach,
  settings = {
    Lua = {
      runtime = { version = "LuaJIT", path = { vim.split(package.path, ';') },
      },
      completion = { keywordSnippet = "Disable", },
      diagnostics = {enable = true, globals = {"vim","describe","it","before_each","after_each"}
      },
      workspace = {
        library = { [vim.fn.expand("$VIMRUNTIME/lua")] = true,
          [vim.fn.expand("$VIMRUNTIME/lua/vim/lsp")] = true},
        maxPreload = 1000,
        preloadFileSize = 1000,
      }
    }
  }
}
require'nvim-treesitter.configs'.setup {
  ensure_installed = {"cpp", "lua", "bash", "python", "typescript", "javascript"},
  highlight = { enable = true },
}
3 Likes

One question. will comments count towards our total or will it just be the code?

Refer to this handy lecture about the stringency of rules: Barbossa and the Pirate code - YouTube

This is just for fun, the point of 300 lines (including comments) is that it’s ~8 pages on a standard screen, so it’s very readable.

Ah ok thanks for the clarification! I will try to remember to keep it breezy

This is my hot off the press init.lua. There is nothing too impressive about this config. I am just here to prove (with a little time and a lot of :h) you can make a pretty usable config with little to no lua or neovim experience.
I recommend using this really handy website to learn the fundamentals of lua. it really helped me.
One final thing… If you are looking for my inspiration for the naming conventions and some of the humor doom emacs is the project that got me down this hell hole.

this was quite a bit of fun. Thanks @mjlbach!
My init.lua

my first neovim config and init.lua
-- the start of my nvim config I have not used lua or neovim before this day
-- packer initalisation -- stolen from mjlbach
local execute = vim.api.nvim_command
local install_path = vim.fn.stdpath('data')..'/site/pack/packer/opt/packer.nvim'

if vim.fn.empty(vim.fn.glob(install_path)) > 0 then
   execute('!git clone https://github.com/wbthomason/packer.nvim '..install_path)
end

vim.cmd [[packadd packer.nvim]]
vim.api.nvim_exec([[
  augroup Packer
    autocmd!
    autocmd BufWritePost plugins.lua PackerCompile
  augroup end
]], false)


local use = require('packer').use
local packer = require('packer')
packer.startup(function()
   -- package managment
   use {'wbthomason/packer.nvim', opt = true}  -- the package responsible for it all

   -- theme
   use 'ntk148v/vim-horizon' -- my theme of choice
   use 'itchyny/lightline.vim' -- that status bar at the bottom of the screen
   -- language support
   use 'sheerun/vim-polyglot' -- language support for the lazy
   use 'sherylynn/vim-elisp' -- what can I say except I enjoy living in sin
   -- lang server;s
   use 'neovim/nvim-lspconfig' -- all the completion
   use 'hrsh7th/nvim-compe'  -- for actual completion
   -- utilitys
   use 'mhinz/vim-startify' -- a nice start page
   use 'kana/vim-smartinput' -- auto close delimiters
   use 'ap/vim-css-color'  -- highlights colour values
   use 'Chiel92/vim-autoformat' -- thats enough <space> thank you very much
   use 'wellle/targets.vim' -- all the text objects
   use { 'nvim-telescope/telescope.nvim', -- search and select tool (very cool)
   requires = {{'nvim-lua/popup.nvim'}, {'nvim-lua/plenary.nvim'}}}

   -- snippets -- why should you type when you can get your minions to do it for you?
   use 'sirver/ultisnips' -- the engine 
   use 'honza/vim-snippets' -- the coal (the actuall snippets)

   -- tpope plugins -- he is an artist
   use 'tpope/vim-commentary' -- comment and uncomment things with ease
   use 'tpope/vim-endwise' -- adds end to languages that use end (like this one! (and ruby))
   use 'tpope/vim-eunuch' -- helpers for unix commands
   use 'tpope/vim-repeat' -- repeat plugin commands
   use 'tpope/vim-scriptease' -- when there;s somthing strange, in the code? who ya going to call? 'K'
   use 'tpope/vim-surround' -- surround texobj;s with all kinds of delimiters
   use 'tpope/vim-vinegar' -- netrw was is in dired need for an upgrade

   -- git
   use 'airblade/vim-gitgutter' -- get your mind out of the sidebar!
   use 'tpope/vim-fugitive' -- mostly for the nice branch in the modeline
   use 'TimUntersberger/neogit' -- emacs is dead, long live emacs!

   -- other stuff
   use 'aurieh/discord.nvim' -- whats the point in using vim if your not telling the world?
end)
-- settings -- this is all of the basic vim settings
local o = vim.o  -- global
local g = vim.g  -- global 2?
local wo = vim.wo -- window local
local bo = vim.bo -- buffer local

-- global options -- I could explain all of these but then again :h VAR exists...
vim.cmd('syntax enable')
o.inccommand = "nosplit"
o.swapfile = true
o.dir = '/tmp'
o.smartcase = true
o.laststatus = 2
o.hlsearch = true
o.incsearch = true
o.ignorecase = true
o.scrolloff = 12
o.showcmd = true
o.wildmenu = true
o.mouse = 'a'
o.showmatch = true
o.expandtab = true
o.ruler = true
o.clipboard = 'unnamedplus'
o.incsearch = true
o.hlsearch = true
o.showmode = false
o.tabstop = 4
o.encoding = 'UTF-8'
o.timeout = false
o.timeoutlen = 10
-- window-local option
wo.number = true
wo.relativenumber = true
wo.wrap = false
wo.cursorline = true
wo.foldenable = true
-- buffer-local options
bo.expandtab = true

-- keys -- my keybinding scheme is pretty much a rip off of dooms keybinds (because its great!)
-- leader

g.mapleader = ' '
local key = vim.api.nvim_set_keymap
local opts = {noremap = true, silent = true}

function cmdM(cmd)
   return '<cmd> ' .. cmd .. ' <cr>'
end

-- misc
key('n', '<leader><space>',
   cmdM("lua require('telescope.builtin').find_files()"),
   opts)

-- git
key('n', '<leader>gg', -- open neogit (the second most sane way to interact with git)
   cmdM('Neogit'),
   opts)

-- buffer
key('n', '<leader>b', -- open a list of all open buffers
   cmdM("lua require('telescope.builtin').buffers()"),
   { noremap = true, silent = true})

-- search
key('n', '<leader>sf', -- search the currently open file
   cmdM("lua require('telescope.builtin').current_buffer_fuzzy_find()"),
   opts)
-- window

key('n', '<leader>wv', -- vertical split
   cmdM("vsplit"),
   opts)

key('n', '<leader>ws', -- horizontal split
   cmdM("split"),
   opts)

key('n', '<leader>wc', -- close a window
   cmdM("quit"),
   opts)

-- session
key('n', '<leader>ql', -- load the last session
   cmdM("SLoad!"),
   opts)

key('n', '<leader>qs', -- save the current session
   cmdM("SSave!"),
   opts)

key('n', '<leader>qh', -- open startify (home)
   cmdM("Startify"),
   opts)

-- open
key('n', '<leader>o-',  -- open dired.. I mean Explore
   cmdM("Explore"),
   opts)

-- code
key('n', '<leader>cf', -- format the code
   cmdM('Autoformat'),
   opts)

-- snippets -----------------------------------------------------
g.UltiSnipsExpandTrigger="<tab>" -- expand snippet on tab
g.UltiSnipsJumpForwardTrigger="<c-b>"
g.UltiSnipsJumpBackwardTrigger="<c-z>"

--  If you want :UltiSnipsEdit to split your window.
g.UltiSnipsEditSplit="vertical"
-- lsp configs -- for dat solid completion TODO: finish lsp config

local lspconfig = require('lspconfig')

o.completeopt = "menuone,noselect"

require'compe'.setup {
   enabled = true;
   autocomplete = true;
   debug = false;
   min_length = 1;
   preselect = 'enable';
   throttle_time = 80;
   source_timeout = 200;
   incomplete_delay = 400;
   max_abbr_width = 100;
   max_kind_width = 100;
   max_menu_width = 100;
   documentation = true;

   source = {
      path = true;
      buffer = false;
      calc = true;
      vsnip = false;
      nvim_lsp = true;
      nvim_lua = true;
      spell = true;
      tags = false;
      snippets_nvim = true;
   };
}

local custom_attach = function(client)
   print("LSP started.");
   require'completion'.on_attach(client)
   vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with(
      vim.lsp.diagnostic.on_publish_diagnostics, { virtual_text = false, update_in_insert = false }
      )
   -- automatic diagnostics popup
   execute('autocmd CursorHold <buffer> lua vim.lsp.diagnostic.show_line_diagnostics()')
   -- speedup diagnostics popup
   o.updatetime=1000


   vim.cmd("inoremap <silent><expr> <C-Space> compe#complete()") -- meant to complete on point
   key('n', 'gD',cmdM('lua vim.lsp.buf.declaration()'), opts) -- jump to definition
end

-- lsp's I don't really do much
lspconfig.pyls.setup{} -- python
lspconfig.solargraph.setup{} -- ruby
lspconfig.texlab.setup{} -- latex

-- ui -- basic ui settings ------------------------------------------------------------
o.termguicolors = true
vim.cmd("colorscheme horizon")

-- custom lightline 
g.lightline = { colorscheme = 'horizon'; active = { left = { { 'mode', 'paste' },
   { 'gitbranch', 'readonly', 'filename', 'modified' }}};
component_function = { gitbranch = 'fugitive#head', };}

-- header of the start page
g.header = {
   '          ',
   '    _/_/_/',
   '   _/    _/    _/_/      _/_/    _/_/_/  _/_/',
   '  _/    _/  _/    _/  _/    _/  _/    _/    _/',
   ' _/    _/  _/    _/  _/    _/  _/    _/    _/',
   '_/_/_/      _/_/      _/_/    _/    _/    _/',
   '',
   '             _/  _/    _/',
   '            _/      _/_/_/_/    _/_/',
   '           _/  _/    _/      _/_/_/_/',
   '          _/  _/    _/      _/',
   '         _/  _/      _/_/    _/_/_/',
   '',
   '         wait, this is not emacs! ',
}

vim.cmd([[
let g:startify_custom_header = startify#center(g:header) 
]]) -- centers the startpage banner

-- misc stuff
g.discord_activate_on_enter = 1 

-- and thats it. thats my config. This should hopefully prove to people a noob (that can code)
-- can configure neovim to a very usable state. if you want to read more of this config (and check me out)
-- https://github.com/jeetelongname/dotfiles is the place to look
-- and we have reached 269 lines. Nice
2 Likes

Got some help getting mine working so thought I would share mine too! I have a separate utils file that I will include here that I like just to keep things clean in the actual init file, but combined it is under 300!

utils.lua
local utils = {}
local api = vim.api
local fn = vim.fn
local scopes = { o = vim.o, b = vim.bo, w = vim.wo }

_G.tab_complete = function()
  if fn.pumvisible() == 1 then
    return utils.t "<c-n>"
  elseif utils.check_back_space() then
    return utils.t "<tab>"
  else
    return fn['coc#refresh()']
  end
end

_G.s_tab_complete = function()
  if fn.pumvisible() == 1 then
    return utils.t "<c-p>"
  else
    return utils.t "<c-h>"
  end
end

function utils.opt(scope, key, value)
  scopes[scope][key] = value
  if scope ~= 'o' then scopes['o'][key] = value end
end

function utils.map(mode, lhs, rhs, opts)
  local options = { noremap = true }
  if opts then
    options = vim.tbl_extend('force', options, opts)
  end
  api.nvim_set_keymap(mode, lhs, rhs, options)
end

function utils.nvim_create_augroups(definitions)
  for group_name, definition in pairs(definitions) do
    api.nvim_command('augroup '..group_name)
    api.nvim_command('autocmd!')
    for _, def in ipairs(definition) do
      local command = table.concat(vim.tbl_flatten{'autocmd', def}, ' ')
      api.nvim_command(command)
    end
    api.nvim_command('augroup END')
  end
end

function utils.t(str)
  return api.nvim_replace_termcodes(str, true, true, true)
end

function utils.check_back_space()
  local col = fn.col('.') - 1
  if col == 0 or fn.getline('.'):sub(col, col):match('%s') then
    return true
  else
    return false
  end
end

return utils

And then the init.lua:

init.lua
local utils = require('utils')

local cmd = vim.cmd
local g = vim.g
local api = vim.api
local fn = vim.fn
local indent = 2

-- Map space to leader
g.mapleader = ' '

---- Plugins ----
cmd "call plug#begin('~/.vim/plugged')"

cmd "Plug 'airblade/vim-gitgutter'"
cmd "Plug 'Asheq/close-buffers.vim'"
cmd "Plug 'bling/vim-bufferline'"
cmd "Plug 'christoomey/vim-system-copy'"
cmd "Plug 'christoomey/vim-tmux-navigator'"
cmd "Plug 'editorconfig/editorconfig-vim'"
cmd "Plug 'edkolev/tmuxline.vim'"
cmd "Plug 'elzr/vim-json'"
cmd "Plug 'HerringtonDarkholme/yats.vim'"
cmd "Plug 'jiangmiao/auto-pairs'"
cmd "Plug 'jparise/vim-graphql'"
cmd "Plug 'junegunn/fzf', {'do': { -> fzf#install() }}"
cmd "Plug 'junegunn/fzf.vim'"
cmd "Plug 'mattn/emmet-vim'"
cmd "Plug 'neoclide/coc.nvim', {'branch': 'release'}"
cmd "Plug 'preservim/tagbar'"
cmd "Plug 'rafcamlet/coc-nvim-lua'"
cmd "Plug 'rust-lang/rust.vim'"
cmd "Plug 'scrooloose/nerdtree'"
cmd "Plug 'scrooloose/nerdtree-project-plugin'"
cmd "Plug 'tiagofumo/vim-nerdtree-syntax-highlight'"
cmd "Plug 'tomasr/molokai'"
cmd "Plug 'tpope/vim-surround'"
cmd "Plug 'tpope/vim-repeat'"
cmd "Plug 'tpope/vim-commentary'"
cmd "Plug 'tpope/vim-fugitive'"
cmd "Plug 'tpope/vim-obsession'"
cmd "Plug 'vim-airline/vim-airline'"
cmd "Plug 'vim-airline/vim-airline-themes'"

-- This needs to be loaded last
cmd "Plug 'ryanoasis/vim-devicons'"

cmd 'call plug#end()'

---- Settings ----

cmd 'syntax enable'
cmd 'filetype plugin indent on'
cmd 'colorscheme molokai'

-- Global Options
utils.opt('o', 'background', 'dark')
utils.opt('o', 'backup', false)
utils.opt('o', 'compatible', false)
utils.opt('o', 'guifont', 'FiraCode_NF')
utils.opt('o', 'hlsearch', true)
utils.opt('o', 'ignorecase', true)
utils.opt('o', 'incsearch', true)
utils.opt('o', 'lazyredraw', true)
utils.opt('o', 'mouse', 'v')
utils.opt('o', 'showcmd', true)
utils.opt('o', 'showmatch', true)
utils.opt('o', 'smartcase', true)
utils.opt('o', 'splitbelow', true)
utils.opt('o', 'splitright', true)
utils.opt('o', 'timeoutlen', 2500)
utils.opt('o', 'ttimeoutlen', 100)
utils.opt('o', 'termguicolors', true)
utils.opt('o', 'undodir', '~/.config/nvim/undodir')
utils.opt('o', 'updatetime', 100)
utils.opt('o', 'wildmode', 'longest,list')

-- Buffer Local Options
utils.opt('b', 'autoindent', true)
utils.opt('b', 'expandtab', true)
utils.opt('b', 'shiftwidth', indent)
utils.opt('b', 'smartindent', true)
utils.opt('b', 'swapfile', false)
utils.opt('b', 'tabstop', indent)
utils.opt('b', 'undofile', true)

-- Window Local Options
utils.opt('w', 'cursorline', true)
utils.opt('w', 'number', true)
utils.opt('w', 'wrap', false)


---- Plugin Settings ----

-- Airline --
g.airline_theme = 'molokai'
g.airline_powerline_fonts = 1
g['airline#extensions#obsession#enabled'] = 1
g['airline#extensions#obsession#indicator_text'] = '$'
g['airline#extensions#tagbar#enabled'] = 0
g['airline#extensions#bufferline#enabled'] = 1
g['airline#extensions#coc#enabled'] = 1
g['airline#extensions#fzf#enabled'] = 0
g['airline#extensions#tabline#enabled'] = 0

-- NERDTree --
g.NERDTreeIgnore = { 'node_modules', 'dist', 'build' }
g.NERDTreeDirArrowExpandable = ''
g.NERDTreeDirArrowCollapsible = ''
g.NERDTreeFileExtensionHighlightFullName = 1
g.NERDTreeExactMatchHighlightFullName = 1
g.NERDTreePatternMatchHighlightFullName = 1

-- Tagbar --
g.tagbar_ctags_bin = '/usr/local/bin/ctags'

---- Keymaps ----

-- Remap ';' to be used for commands to eliminate extra shift press
utils.map('n', ';', ':')
utils.map('n', ':', ';')
utils.map('v', ';', ':')
utils.map('v', ':', ';')

-- Pane navigation made easier
utils.map('n', '<leader>j', '<c-W><c-J>')
utils.map('n', '<leader>k', '<c-W><c-K>')
utils.map('n', '<leader>l', '<c-W><c-L>')
utils.map('n', '<leader>h', '<c-W><c-H>')

-- Faster buffer saving
utils.map('n', '<Leader>ss', ':w<cr>')

-- Shortcut for reloading init.lua
utils.map('n', '<Leader>sp', ':luafile ~/.config/nvim/init.lua<cr>', { silent = true })

-- Make enter work to select coc suggestion
utils.map('i', '<cr>', "pumvisible() ? '<c-y>' : '<c-g>u<cr>'", { expr = true })


-- Open the NERDTree file tree
utils.map('n', '<leader>b', ':NERDTreeToggle<cr>', { silent = true })

-- Open FZF in the current directory
utils.map('n', '<leader>ff', ':Files<cr>')
utils.map('n', '<leader>pw', ':Rg <c-r>=expand("<cword>")<cr><cr>')

-- Allow tab to trigger auto-complete, refresh on backspace
utils.map('i', '<tab>', 'v:lua.tab_complete()', { expr = true, silent = true })
utils.map('i', '<s-tab>', 'v:lua.s_tab_complete()', { expr = true, silent = true })

-- GoTo code navigation
utils.map('n', '<leader>gd', ":call CocActionAsync('jumpDefinition')<cr>", { silent = true })
utils.map('n', '<leader>gy', ":call CocActionAsync('jumpTypeDefinition')<cr>", { silent = true })
utils.map('n', '<leader>gi', ":call CocActionAsync('jumpImplementation')<cr>", { silent = true })
utils.map('n', '<leader>gr', ":call CocActionAsync('jumpReferences')<cr>", { silent = true })
utils.map('n', '<leader>gn', ":call CocActionAsync('diagnosticNext')<cr>", { silent = true })
utils.map('n', '<leader>gp', ":call CocActionAsync('diagnosticPrevious')<cr>", { silent = true })

-- Use K to show documentation in the preview window
utils.map('n', 'K', ':call ShowDocumentation()<cr>', { silent = true })
api.nvim_exec(
[[
function! ShowDocumentation()
  if (index(['vim','help'], &filetype) >=0)
    execute 'h '.expand('<cword>')
  else
    call CocActionAsync('doHover')
  endif
endfunction
]]
, false)

-- Symbol renaming
utils.map('n', '<leader>rn', '<Plug>(coc-rename)')

-- Quick Fix
utils.map('n', '<leader>qf', ':CocAction quickfix<cr>')

-- Add space above or below current line
utils.map('n', '<leader>lb', 'mpo<esc>`p')
utils.map('n', '<leader>la', 'mpO<esc>`p')

-- Buffer closing shortcuts using :Bdelete
utils.map('n', '<leader>bdo', ':Bdelete other<cr>')
utils.map('n', '<leader>bdh', ':Bdelete hidden<cr>')

-- TagBar
utils.map('n', '<leader>tt', ':TagbarToggle<cr>')

-- Clear highlighting
utils.map('n', '<leader>nh', ':let @/ = ""<cr>', { silent = true })

---- Autogroups ----
local definitions = {}
definitions['nerd_tree'] = {
  -- automatically open NERDTree when vim starts
  "VimEnter * if &filetype !=# 'gitcommit' | NERDTree | endif",
  -- Prevent other buffers from replacing NERDTree in its window
  [[BufEnter * if bufname('#') =~ 'NERD_tree\d\+' && bufname('%') !~ 'NERD_tree\d\+' && winnr('$') > 1 | let buf=bufnr() | buffer# | execute 'normal! \<c-w>w' | execute 'buffer'.buf | endif]],
  -- Exit Vim if NERDTree is the only window left
  [[BufEnter * if tabpagenr('$') == 1 && winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif]]
}
definitions['coc_highlight'] = {
  [[CursorHold * silent call CocActionAsync('highlight')]]
}
utils.nvim_create_augroups(definitions)

---- Fix for NERDTree icons after source ----
if fn.exists('g:loaded_webdevicons') then
  cmd 'call webdevicons#refresh()'
end

Combined it is less than 300 lines, I hope this still fits the bill even with the utils broken out a little for readability!

1 Like

If you win, I’ll merge it into one file anyways when its posted :sweat_smile:

1 Like

I think I might have snagged some of those utils from one of the Neovim project maintainer’s init.lua haha. I’ll have to see if I can remember who I snagged those from. The autogroups one I for sure did not come up with on my own but I love the simplicity of it!

Ok My config is definatly not under 300 line nor is 100% lua. So this is not an entry to the chalange . If @mjlbach don’t mind I’d still like to share my init.lua here :slight_smile: .

init.lua

Config_dir = vim.fn.glob('~/.config/nvim/configs/')
-- loads all vimscript and lua files in path
local function load_dir(path)
  if path[#path] ~= '/' then path = path..'/' end
  local dir = vim.loop.fs_scandir(path)
  if dir then
    local file = vim.loop.fs_scandir_next(dir)
    while file do
      local stat = vim.loop.fs_stat(path..file)
      if stat.type == 'file' then
        if vim.endswith(file, '.lua') then
          local ok, result = pcall(dofile, path..file)
          if not ok then print('Failed to load: '..path..file..' '..result) end
        elseif vim.endswith(file, '.vim') then
          local ok, result = pcall(vim.cmd,'source '..path..file)
          if not ok then print('Failed to load: '..path..file..' '..result) end
        end
      elseif file == 'lazy' and stat.type == 'directory' then
         -- load files in lazy folder after timer so they don't block startup
        vim.fn.timer_start(100, vim.schedule_wrap(function()load_dir(path..'lazy/')end))
      end
      file = vim.loop.fs_scandir_next(dir)
    end
  else
    vim.api.nvim_echo({{path..' not found!!', 'ErrorMsg'}}, true, {})
  end
end

-- Load config dir
load_dir(Config_dir)

So what this basically it loads all vim lua files in my config_dir . What I do is when I add new plugin. I just drop its config in a new file in that config directory . Also I have a mapping telescope mapping that search in that specific folder . So things are pretty easy to find and change . Why vim files you may ask, It’s mostly set commands . I’m waiting for vim.opt get merged :smiley:

1 Like

Alright, here’s my attempt:

init.lua
--- vim:sw=2 fdm=marker
--- Type za to toggle one fold or zi to toggle 'foldenable'. See :help fold-commands for more info.
local api, fn, cmd = vim.api, vim.fn, vim.cmd
--- {{{1 [[ OPTIONS ]]
vim.o.termguicolors = true
vim.wo.number = true
vim.wo.signcolumn = 'number' -- Display signs in the number column
vim.wo.list = true
vim.wo.linebreak = true
vim.wo.breakindent = true
vim.o.showmode = false
vim.o.pumblend = 10
vim.g.vimsyn_embed = 'l' -- Highlight Lua code inside .vim files

vim.o.expandtab = true; vim.bo.expandtab = true
vim.o.shiftwidth = 2; vim.bo.shiftwidth = 2
vim.o.tabstop = 2; vim.bo.tabstop = 2

vim.o.inccommand = 'split'

-- I'm used to text editors opening side panels to the right of/below the current one
vim.o.splitright = true
vim.o.splitbelow = true

-- This sets up prettier as the default formatter. It has good defaults for common filetypes.
-- Can be overridden with a buffer-local option
vim.o.formatprg = 'prettier --stdin-filepath=%'

vim.o.mouse = 'a'
-- CursorHold autocmds are dependent on updatetime. The default is 4000, which is too long for many things
vim.o.updatetime = 300
vim.o.hidden = true
vim.o.undofile = true; vim.bo.undofile = true -- Persistent undo is a neat feature
vim.o.shortmess = vim.o.shortmess .. 'cI' -- No startup screen, no ins-completion-menu messages
vim.o.completeopt = 'menuone,noselect' -- Required for nvim-compe
--- {{{1 [[ MAPPINGS ]]
-- I really only set custom mappings for stuff that I use often.
-- I prefer offloading the creation of mappings to vim-unimpaired.
-- For stuff that I don't use all that often, I prefer creating custom commands,
-- which I think are more versatile and easier to remember.
local map = api.nvim_set_keymap

-- <Space> seems to be a popular leader key (it's better than the default \ IMO).
vim.g.mapleader = ' '

map('', 'Y', 'y$', {}) -- I like consistency.
map('', 'Q', '', {}) -- Begone, foul beast. I can invoke your wrath with gQ anyway.

-- I do not enjoy accidentally nuking an entire line and not being able to undo the action :)
-- Incidentally, Vim has the <C-u> mapping in defaults.vim
map('i', '<C-u>', '<C-g>u<C-u>', {noremap = true})
map('i', '<C-w>', '<C-g>u<C-w>', {noremap = true})

-- Stolen from https://github.com/neovim/neovim/issues/6289
map('n', '<C-l>', '<Cmd>nohlsearch<CR><C-l>', {noremap = true})

-- Not being able to navigate lines visually annoyed me when I was a beginner
map('', 'j', "(v:count? 'j' : 'gj')", {noremap = true, expr = true})
map('', 'k', "(v:count? 'k' : 'gk')", {noremap = true, expr = true})

-- Custom text object: "around document". Useful to format/indent an entire file with gqad or =ad
map('o', 'ad', '<Cmd>normal! ggVG<CR>', {noremap = true})
map('x', 'ad', 'gg0oG$', {noremap = true})
--- {{{1 [[ PLUGINS ]]
-- Bootstrap packer.nvim
local install_path = fn.stdpath('data') .. '/site/pack/packer/start/packer.nvim'

if fn.isdirectory(install_path) == 0 then
  fn.system({'git', 'clone', 'https://github.com/wbthomason/packer.nvim', install_path})
  cmd 'packadd packer.nvim'
end

local packer = require('packer')
packer.startup(function(use)
  use 'wbthomason/packer.nvim'
  -- This one is cheating: it bundles vim-sensible + vim-sleuth + a truckload of syntax files.
  use 'sheerun/vim-polyglot'
  -- My colorscheme of choice is usually Dracula, but it's probably not everyone's cup of tea.
  -- I think this one has broader appeal and as a bonus, it has highlights for LSP, treesitter and telescope
  use {'sainnhe/sonokai', config = 'vim.cmd "colorscheme sonokai"'}
  use 'editorconfig/editorconfig-vim'
  use 'tpope/vim-eunuch'
  use 'tpope/vim-fugitive'
  use 'tpope/vim-commentary'
  use 'tpope/vim-surround'
  -- Lazy load vim-unimpaired because it slows down startuptime a bit
  use {'tpope/vim-unimpaired', keys = {'[', ']', '<', '>', '=', 'y'}}
  use 'tpope/vim-repeat'
  use 'Raimondi/delimitMate'
  use {'itchyny/lightline.vim',
    setup = function()
      vim.g.lightline = {
        colorscheme = 'sonokai',
        active = {
          left = {{'mode', 'paste'},
                  {'gitbranch', 'readonly', 'filename', 'modified'}},
        },
        component_function = {
          gitbranch = 'FugitiveHead',
        },
      }
    end,
  }
  use {'norcalli/nvim-colorizer.lua', config = [[require('colorizer').setup{'html', 'css', 'scss'}]]}
  use {'neovim/nvim-lspconfig', requires = {'kosayoda/nvim-lightbulb'}, config = '_G.lspconfig_init()'}
  use {'hrsh7th/nvim-compe', requires = {'hrsh7th/vim-vsnip'}, config = '_G.compe_init()'}
  use {
    'nvim-telescope/telescope.nvim',
    requires = {{'nvim-lua/popup.nvim'}, {'nvim-lua/plenary.nvim'}},
    config = function()
      local map = vim.api.nvim_set_keymap
      map('n', '<Leader>fb', '<Cmd>Telescope buffers<CR>', {noremap = true})
      map('n', '<Leader>ff', '<Cmd>Telescope find_files<CR>', {noremap = true})
    end,
  }
end)
--- {{{1 [[ LSPCONFIG ]]
local function custom_lsp_attach(client, bufnr)
  local cap = client.resolved_capabilities

  --- Mappings
  local function bmap(mode, lhs, rhs)
    api.nvim_buf_set_keymap(bufnr, mode, lhs, rhs, {noremap = true})
  end

  bmap('n', ']E', '<Cmd>lua vim.lsp.diagnostic.goto_next()<CR>')
  bmap('n', '[E', '<Cmd>lua vim.lsp.diagnostic.goto_prev()<CR>')
  bmap('n', 'gl', '<Cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR>')
  if cap.goto_definition then
    bmap('n', '<C-]>', '<Cmd>lua vim.lsp.buf.definition()<CR>')
  end
  if cap.hover then
    bmap('n', 'K', '<Cmd>lua vim.lsp.buf.hover()<CR>')
  end
  if cap.code_action then
    bmap('n', 'gA', '<Cmd>lua vim.lsp.buf.code_action()<CR>')
    bmap('x', 'gA', '<Cmd>lua vim.lsp.buf.range_code_action()<CR>')
  end

  --- Commands
  if cap.rename then
    cmd 'command! -buffer -nargs=? LspRename lua vim.lsp.buf.rename(<f-args>)'
  end
  if cap.find_references then
    cmd 'command! -buffer LspReferences lua vim.lsp.buf.references()'
  end
  if cap.workspace_symbol then
    cmd 'command! -buffer -nargs=? LspWorkspaceSymbol lua vim.lsp.buf.workspace_symbol(<f-args>)'
  end
  if cap.call_hierarchy then
    cmd 'command! -buffer LspIncomingCalls lua vim.lsp.buf.incoming_calls()'
    cmd 'command! -buffer LspOutgoingCalls lua vim.lsp.buf.outgoing_calls()'
  end
  if cap.workspace_folder_properties.supported then
    cmd 'command! -buffer LspListWorkspaceFolders lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))'
    cmd 'command! -buffer -nargs=? -complete=dir LspAddWorkspaceFolder lua vim.lsp.buf.add_workspace_folder(<f-args>)'
    cmd 'command! -buffer -nargs=? -complete=dir LspRemoveWorkspaceFolder lua vim.lsp.buf.remove_workspace_folder(<f-args>)'
  end
  if cap.document_symbol then
    cmd 'command! -buffer LspDocumentSymbol lua vim.lsp.buf.document_symbol()'
  end
  if cap.goto_definition then
    cmd 'command! -buffer LspDefinition lua vim.lsp.buf.definition()'
  end
  if cap.type_definition then
    cmd 'command! -buffer LspTypeDefinition lua vim.lsp.buf.type_definition()'
  end
  if cap.declaration then
    cmd 'command! -buffer LspDeclaration lua vim.lsp.buf.declaration()'
  end
  if cap.implementation then
    cmd 'command! -buffer LspImplementation lua vim.lsp.buf.implementation()'
  end
end

function _G.lspconfig_init()
  api.nvim_exec([[
  augroup lsp_lightbulb
    autocmd!
    autocmd CursorHold,CursorHoldI * lua require('nvim-lightbulb').update_lightbulb()
  augroup END
  ]], false)

  local lspconfig = require('lspconfig')
  lspconfig.sumneko_lua.setup {
    cmd = {'lua-language-server'},
    on_attach = custom_lsp_attach,
    settings = {
      Lua = {
        runtime = {
          version = 'LuaJIT',
          path = vim.split(package.path, ';'),
        },
        diagnostics = {
          globals = {'vim'},
        },
        workspace = {
          library = {
            [fn.expand('$VIMRUNTIME/lua')] = true,
          },
        },
      },
    },
  }
end
--- {{{1 [[ NVIM-COMPE ]]
function _G.compe_init()
  local compe = require('compe')
  compe.setup {
    enabled = true,
    preselect = 'enable',
    source = {
      path = true,
      buffer = true,
      nvim_lsp = true,
      nvim_lua = true,
      vsnip = true,
    }
  }

  local function t(str)
    return api.nvim_replace_termcodes(str, true, true, true)
  end

  local function check_back_space()
    local col = fn.col('.') - 1
    return not not (col == 0 or fn.getline('.'):sub(col, col):match('%s'))
  end

  -- Use (s-)tab to:
  --- move to prev/next item in completion menuone
  --- jump to prev/next snippet's placeholder
  function _G.tab_complete()
    if fn.pumvisible() == 1 then
      return t '<C-n>'
    elseif fn['vsnip#available'](1) == 1 then
      return t '<Plug>(vsnip-expand-or-jump)'
    elseif check_back_space() then
      return t '<Tab>'
    else
      return fn['compe#complete']()
    end
  end
  function _G.s_tab_complete()
    if fn.pumvisible() == 1 then
      return t '<C-p>'
    elseif fn['vsnip#jumpable'](-1) == 1 then
      return t '<Plug>(vsnip-jump-prev)'
    else
      return t '<S-Tab>'
    end
  end

  map('i', '<Tab>', 'v:lua.tab_complete()', {expr = true})
  map('s', '<Tab>', 'v:lua.tab_complete()', {expr = true})
  map('i', '<S-Tab>', 'v:lua.s_tab_complete()', {expr = true})
  map('s', '<S-Tab>', 'v:lua.s_tab_complete()', {expr = true})

  map('i', '<CR>', [[compe#confirm({ 'keys': "\<Plug>delimitMateCR" })]], {expr = true, silent = true})
end
--- {{{1 [[ COMMANDS ]]
-- LspLog: take a quick peek at the latest LSP log messages. Useful for debugging
-- LspStop: stop all active clients
-- Redirect: show the results of an ex command in a buffer rather than the built-in pager
api.nvim_exec([[
command! LspLog execute '<mods> pedit +$' v:lua.vim.lsp.get_log_path()
command! LspStop lua vim.lsp.stop_client(vim.lsp.get_active_clients())
command! -nargs=* -complete=command Redirect <mods> new | setl nonu nolist noswf bh=wipe bt=nofile | call append(0, split(execute(<q-args>), "\n"))
]], false)
--- {{{1 [[ AUTOCOMMANDS ]]
-- hl_yank: highlight the area that was just yanked
-- restore_curpos: restore the last position of the cursor in a file. Taken from Vim's defaults.vim
api.nvim_exec([[
augroup hl_yank
  autocmd!
  autocmd TextYankPost * lua require('vim.highlight').on_yank()
augroup END

augroup restore_curpos
  autocmd!
  autocmd BufReadPost * if line("'\"") >= 1 && line("'\"") <= line("$") && &ft !~# 'commit' | exe "normal! g`\"" | endif
augroup END
]], false)

And here’s the wrapper script that I use for sumneko_lua:

lua-language-server
#!/usr/bin/env sh

SUMNEKO_SRC_DIR="$HOME/.local/bin/lua-language-server-src"

exec "$SUMNEKO_SRC_DIR/bin/Linux/lua-language-server" -E "$SUMNEKO_SRC_DIR/main.lua" "$@"

Turns out you can do quite a lot with ~300 lines. Kind of makes me want to take a bunch of stuff out of my own config

EDIT: I just realized there’s a 110 chars per line limit… Unfortunately some of the Vimscript snippets don’t work if I put them on multiple lines. Oops.

3 Likes

We can let it slide :wink:

Woah. That was me who said Neovim is hard to configure. But I felt the community is awesome. Only a few bad actors who try to gatekeep. I finally took out the time to write my own config starting from Learn VimScript the Hard Way and Nvim lua guide. I made a rudimentary config of mine in neovim-dotfiles. It works just fine now.

BTW, I will soon be posting a blog series on VimScript and lua setup for a near-perfect IDE like setting. After of course the release of 0.5

1 Like

Ah so never! I kid of course. Can’t wait!