local ensure_packer = function()
    local fn = vim.fn
    local install_path = fn.stdpath('data') .. '/site/pack/packer/start/packer.nvim'
    if fn.empty(fn.glob(install_path)) > 0 then
        fn.system({ 'git', 'clone', '--depth', '1', 'https://github.com/wbthomason/packer.nvim', install_path })
        vim.cmd [[packadd packer.nvim]]
        return true
    end
    return false
end

local packer_bootstrap = ensure_packer()

-- Compile on plugin edits
vim.api.nvim_create_autocmd({ "BufWritePost" }, {
    pattern = "plugins.lua",
    command = "PackerCompile",
    desc = "Compile plugins after editing plugin list",
    group = vim.api.nvim_create_augroup('compilepackages', { clear = true })
})

local use = require("packer").use
require("packer").startup(function()
    -- packer manages itself
    use "wbthomason/packer.nvim"

    -- vim plugs
    -- essential
    use {
        'marty-oehme/Navigator.nvim',
        branch = 'feat/add-wezterm-navigation',
        config = function() require('Navigator').setup() end
    } -- allow seamless navigation between vim buffers and tmux splits
    use 'jeffkreeftmeijer/vim-numbertoggle' -- toggles numbers to absolute for all buffers but the current which is relative
    use 'RRethy/vim-illuminate' -- highlight other occurences of the word under cursor
    use 'ojroques/vim-oscyank' -- yank from *anywhere* (even ssh session) to clipboard, using :OSCYank
    use 'ggandor/lightspeed.nvim' -- jump between letters with improved fFtT quicksearch, mimics sneak
    -- files
    use 'vifm/vifm.vim' -- integrate file manager
    use {
        'lewis6991/gitsigns.nvim', -- show vcs changes on left-hand gutter
        requires = { 'nvim-lua/plenary.nvim' },
        tag = 'release',
        config = function() require('plug._gitsigns') end,
        event = "BufRead"
    }
    use {
        'norcalli/nvim-colorizer.lua', -- color hex, named colors in the correct preview scheme
        config = function() require('colorizer').setup() end,
        event = "BufRead"
    }
    use {
        'mhartington/formatter.nvim', -- auto formatting on save
        config = function() require('plug._format') end,
        event = "BufRead"
    }

    -- editing
    -- use {'machakann/vim-sandwich', event = "BufRead"} -- surround things with other things using sa/sd/sr
    use {
        'kylechui/nvim-surround',
        tag = '*',
        config = function() require('nvim-surround').setup() end
    } -- surround things with other things using ys/cs/ds
    use {
        'monaqa/dial.nvim', -- extend the ^a / ^x possibilities to dates, hex, alphabets, markdown headers
        event = "BufRead"
    }
    use {
        'tommcdo/vim-exchange', -- adds exchange operator with cx. common use: cxiw . on 2 words to switch
        event = "BufRead"
    }
    use {
        'windwp/nvim-autopairs',
        config = function() require('plug._autopair') end,
        event = "BufRead"
    } -- Auto close brackets and ''
    use {
        'junegunn/vim-easy-align', -- Align tables and other alignable things
        event = "BufRead"
    }
    use {
        'tversteeg/registers.nvim', -- Show the contents of regiseters on pasting from '', @, <C-R>
        event = "BufRead"
    }
    use { -- highlight where the cursor jumps to
        'edluffy/specs.nvim',
        config = function() require('specs').setup {} end,
        event = "BufRead"
    }

    -- colorschemes
    use 'norcalli/nvim-base16.lua'

    -- statusline
    use {
        'nvim-lualine/lualine.nvim',
        requires = { 'kyazdani42/nvim-web-devicons', opt = true },
        config = function() require('plug._lualine') end
    }

    -- writing
    use { 'vim-pandoc/vim-pandoc-syntax' }
    use { 'vim-pandoc/vim-pandoc' }
    use { 'vim-pandoc/vim-criticmarkup' }
    use {
        "quarto-dev/quarto-vim",
        requires = { { "vim-pandoc/vim-pandoc-syntax" } },
        ft = { "quarto" }
    }
    use 'micarmst/vim-spellsync' -- personal dict improvements for git sync
    use { 'folke/zen-mode.nvim', config = require('zen-mode').setup() } -- provide distraction free writing
    use 'folke/twilight.nvim' -- provide even distraction free-er writing (lowlight paragraphs)
    use 'alok/notational-fzf-vim' -- quickly search through the wiki

    -- languages
    use { 'euclidianAce/BetterLua.vim', ft = 'lua' } -- better syntax highlighting for lua
    use 'aliou/bats.vim' -- enable syntax for bats shell-code testing library

    -- REPL work
    use {
        'jpalardy/vim-slime', -- send arbitrary code chunks to REPLs
        config = function()
            vim.g.slime_target = 'tmux'
            vim.g.slime_paste_file = vim.fn.tempname()
            vim.g.slime_default_config = {
                socket_name = "default",
                target_pane = "{last}"
            }
            vim.g.slime_python_ipython = 1
            vim.g.slime_no_mappings = 1
        end
    }
    use {
        'hanschen/vim-ipython-cell', -- send code 'cells' to REPL
        ft = "python",
        config = function()
            vim.g.ipython_cell_highlight_cells_ft = { 'python' }
            vim.g.ipython_cell_insert_tag = "## Cell"
        end
    }

    --
    -- nvim plugs
    use {
        'echasnovski/mini.nvim',
        branch = 'stable',
        config = function() require('plug._mini') end
    }
    use 'Iron-E/nvim-cartographer' -- makes it easier to set mappings through lua
    use 'marty-oehme/zettelkasten.nvim' -- simple static markdown linking
    use {
        "akinsho/nvim-toggleterm.lua", -- simpler, programmable and multiple terminal toggling for nvim
        event = "BufWinEnter",
        config = function() require('plug._toggleterm') end
    }
    use {
        "folke/which-key.nvim",
        config = function() require("which-key").setup {} end
    }
    -- extensive organization plugin mimicking orgmode
    use {
        "nvim-neorg/neorg",
        config = function() require("plug._neorg") end,
        requires = "nvim-lua/plenary.nvim",
        tag = "*"
    }

    -- fuzzy matching
    use {
        "nvim-telescope/telescope.nvim",
        requires = {
            { "nvim-lua/popup.nvim" }, { "nvim-lua/plenary.nvim" },
            { "nvim-telescope/telescope-fzf-native.nvim", run = 'make' }
        },
        config = function() require('plug._telescope') end
    }
    use {
        'protex/better-digraphs.nvim',
        requires = { { "nvim-telescope/telescope.nvim" } }
    }

    -- snippeting
    use { "hrsh7th/vim-vsnip", event = "InsertEnter" } -- snippet engine
    use { "rafamadriz/friendly-snippets", event = "InsertEnter" } -- many snippets

    -- treesitter
    use {
        'nvim-treesitter/nvim-treesitter',
        run = ':TSUpdate',
        config = function() require('plug._treesitter') end
    }
    use 'nvim-treesitter/playground' -- interactively view and query the treesitter tree
    use 'romgrk/nvim-treesitter-context' -- show current cursor context at top of buffer
    use {
        'RRethy/nvim-treesitter-textsubjects', -- allows using . and ; to target treesitter branches
        config = function()
            require 'nvim-treesitter.configs'.setup {
                textsubjects = {
                    enable = true,
                    keymaps = {
                        ['.'] = 'textsubjects-smart',
                        [';'] = 'textsubjects-container-outer'
                    }
                }
            }
        end
    }
    use 'p00f/nvim-ts-rainbow' -- rainbow brackets using treesitter
    use 'JoosepAlviste/nvim-ts-context-commentstring' -- improves commenting plugin above by using ts
    use {
        'lewis6991/spellsitter.nvim', -- uses treesitter to highlight spelling errors
        config = function() require('spellsitter').setup() end
    }

    -- lsp
    use 'neovim/nvim-lspconfig' -- some commong language server configurations
    use {
        'simrat39/symbols-outline.nvim',
        config = function() require('symbols-outline').setup() end
    } -- vista-like outline view for code
    use 'ray-x/lsp_signature.nvim'
    use {
        'ray-x/navigator.lua',
        requires = { 'ray-x/guihua.lua', run = 'cd lua/fzy && make' },
        config = function() require('plug._lsp') end
    }
    -- and completion
    use {
        'hrsh7th/nvim-cmp', -- simple completion engine built specifically for nvim and lsp
        requires = {
            'onsails/lspkind-nvim', 'andersevenrud/cmp-tmux', -- completion source from adjacent tmux panes
            'hrsh7th/cmp-nvim-lsp', 'hrsh7th/cmp-buffer', 'hrsh7th/cmp-path',
            'hrsh7th/cmp-cmdline', 'hrsh7th/cmp-vsnip', 'hrsh7th/cmp-nvim-lua',
            'kdheepak/cmp-latex-symbols', 'ray-x/cmp-treesitter',
            'f3fora/cmp-spell', 'cbarrete/completion-vcard'

        }
    }
    require('plug._cmp')

    -- Automatically set up your configuration after cloning packer.nvim
    -- Put this at the end after all plugins
    if packer_bootstrap then
        require('packer').sync()
    end
end)
