Last active
July 12, 2024 22:44
-
-
Save JayDoubleu/6a87607fa38e6f954f8426f743ae10bf to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -e | |
echo "Setting up Neovim with a modern configuration..." | |
# Detect the operating system | |
if [ -f /etc/os-release ]; then | |
. /etc/os-release | |
OS=$NAME | |
elif type lsb_release >/dev/null 2>&1; then | |
OS=$(lsb_release -si) | |
elif [ -f /etc/lsb-release ]; then | |
. /etc/lsb-release | |
OS=$DISTRIB_ID | |
else | |
OS=$(uname -s) | |
fi | |
# Function to install packages | |
install_packages() { | |
if [[ "$OS" == "Ubuntu" ]]; then | |
sudo apt update | |
sudo apt install -y "$@" | |
elif [[ "$OS" == "Fedora"* ]]; then | |
sudo dnf install -y "$@" | |
else | |
echo "Unsupported operating system: $OS" | |
exit 1 | |
fi | |
} | |
# Update system | |
echo "Updating system..." | |
if [[ "$OS" == "Ubuntu" ]]; then | |
sudo apt update && sudo apt upgrade -y | |
elif [[ "$OS" == "Fedora"* ]]; then | |
sudo dnf upgrade -y | |
fi | |
# Install dependencies | |
echo "Installing dependencies..." | |
if [[ "$OS" == "Ubuntu" ]]; then | |
install_packages git curl unzip nodejs npm ripgrep fd-find wget build-essential software-properties-common fontconfig | |
elif [[ "$OS" == "Fedora"* ]]; then | |
install_packages git curl unzip nodejs npm ripgrep fd-find wget gcc gcc-c++ make fontconfig | |
fi | |
# Install latest Neovim | |
echo "Installing latest Neovim..." | |
if [[ "$OS" == "Ubuntu" ]]; then | |
sudo add-apt-repository ppa:neovim-ppa/unstable -y | |
sudo apt update | |
sudo apt install neovim -y | |
elif [[ "$OS" == "Fedora"* ]]; then | |
sudo dnf install -y neovim python3-neovim | |
fi | |
# Check Neovim version | |
NVIM_VERSION=$(nvim --version | head -n 1 | cut -d ' ' -f 2) | |
echo "Installed Neovim version: $NVIM_VERSION" | |
if [ "$(printf '%s\n' "0.8.0" "$NVIM_VERSION" | sort -V | head -n1)" = "0.8.0" ]; then | |
echo "Neovim version is 0.8.0 or higher, proceeding with setup." | |
else | |
echo "Error: Neovim version is lower than 0.8.0. Please check your installation." | |
exit 1 | |
fi | |
# Create Neovim config directory | |
echo "Creating Neovim config directory..." | |
mkdir -p ~/.config/nvim | |
# Install Nerd Font (only if not already installed) | |
FONT_PATH="$HOME/.local/share/fonts/Droid Sans Mono Nerd Font Complete Mono.otf" | |
if [ ! -f "$FONT_PATH" ]; then | |
echo "Installing Nerd Font..." | |
mkdir -p ~/.local/share/fonts | |
cd ~/.local/share/fonts | |
wget https://github.com/ryanoasis/nerd-fonts/releases/download/v2.3.3/DroidSansMono.zip | |
unzip -o DroidSansMono.zip | |
rm DroidSansMono.zip | |
fc-cache -f | |
else | |
echo "Nerd Font already installed, skipping..." | |
fi | |
# Install or update Lazy.nvim | |
echo "Installing or updating Lazy.nvim..." | |
LAZY_PATH="$HOME/.local/share/nvim/lazy/lazy.nvim" | |
if [ -d "$LAZY_PATH" ]; then | |
echo "Lazy.nvim directory exists. Checking its state..." | |
if [ -d "$LAZY_PATH/.git" ]; then | |
echo "Updating Lazy.nvim..." | |
git -C "$LAZY_PATH" fetch --tags | |
git -C "$LAZY_PATH" checkout stable | |
else | |
echo "Lazy.nvim directory is not a git repository. Removing and reinstalling..." | |
rm -rf "$LAZY_PATH" | |
git clone --filter=blob:none https://github.com/folke/lazy.nvim.git --branch=stable "$LAZY_PATH" | |
fi | |
else | |
echo "Installing Lazy.nvim..." | |
git clone --filter=blob:none https://github.com/folke/lazy.nvim.git --branch=stable "$LAZY_PATH" | |
fi | |
# Create init.lua | |
echo "Creating init.lua..." | |
cat > ~/.config/nvim/init.lua << EOL | |
-- Bootstrap lazy.nvim | |
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" | |
if not vim.loop.fs_stat(lazypath) then | |
vim.fn.system({ | |
"git", | |
"clone", | |
"--filter=blob:none", | |
"https://github.com/folke/lazy.nvim.git", | |
"--branch=stable", | |
lazypath, | |
}) | |
end | |
vim.opt.rtp:prepend(lazypath) | |
-- Set leader key | |
vim.g.mapleader = " " | |
-- Plugin specification | |
require("lazy").setup({ | |
-- Colorscheme | |
{ "chriskempson/base16-vim" }, | |
-- LSP | |
{ | |
"neovim/nvim-lspconfig", | |
dependencies = { | |
"williamboman/mason.nvim", | |
"williamboman/mason-lspconfig.nvim", | |
}, | |
}, | |
-- Completion | |
{ | |
"hrsh7th/nvim-cmp", | |
dependencies = { | |
"hrsh7th/cmp-nvim-lsp", | |
"L3MON4D3/LuaSnip", | |
"saadparwaiz1/cmp_luasnip", | |
}, | |
}, | |
-- Treesitter | |
{ | |
"nvim-treesitter/nvim-treesitter", | |
build = ":TSUpdate", | |
config = function() | |
require("nvim-treesitter.configs").setup({ | |
ensure_installed = { "lua", "vim", "vimdoc", "python", "terraform", "hcl", "bash", "json", "yaml", "markdown", "git_rebase", "gitcommit" }, | |
auto_install = true, | |
highlight = { enable = true }, | |
}) | |
end, | |
}, | |
-- Telescope | |
{ | |
"nvim-telescope/telescope.nvim", | |
dependencies = { "nvim-lua/plenary.nvim" }, | |
}, | |
-- File Explorer | |
"nvim-tree/nvim-tree.lua", | |
-- Status Line | |
"nvim-lualine/lualine.nvim", | |
-- Terminal | |
"akinsho/toggleterm.nvim", | |
-- Git | |
"lewis6991/gitsigns.nvim", | |
-- Formatting | |
{ | |
"stevearc/conform.nvim", | |
opts = {}, | |
}, | |
-- Terraform | |
"hashivim/vim-terraform", | |
-- PowerShell | |
"pprovost/vim-ps1", | |
}) | |
EOL | |
cat >> ~/.config/nvim/init.lua << EOL | |
-- Basic settings | |
vim.opt.number = true | |
vim.opt.relativenumber = true | |
vim.opt.expandtab = true | |
vim.opt.shiftwidth = 2 | |
vim.opt.tabstop = 2 | |
vim.opt.smartindent = true | |
vim.opt.termguicolors = true | |
vim.opt.clipboard = "unnamedplus" -- Enable system clipboard | |
vim.opt.fileformats = "unix,dos" -- Automatically detect and use the correct line endings | |
-- Function to toggle paste mode | |
function toggle_paste_mode() | |
if vim.o.paste then | |
vim.o.paste = false | |
print("Paste mode: OFF") | |
else | |
vim.o.paste = true | |
print("Paste mode: ON") | |
end | |
end | |
-- Key mapping for F2 (Toggle paste mode) | |
vim.api.nvim_set_keymap('n', '<F2>', ':lua toggle_paste_mode()<CR>', {noremap = true, silent = true}) | |
-- Function to remove ^M characters | |
local function remove_ctrl_m() | |
local view = vim.fn.winsaveview() | |
vim.cmd([[%s/\r$//e]]) | |
vim.fn.winrestview(view) | |
end | |
-- Autocommand to remove ^M characters on file save | |
vim.api.nvim_create_autocmd("BufWritePre", { | |
pattern = "*", | |
callback = remove_ctrl_m | |
}) | |
-- Function to strip trailing whitespace | |
local function strip_trailing_whitespace() | |
local view = vim.fn.winsaveview() | |
vim.cmd([[%s/\s\+$//e]]) | |
vim.fn.winrestview(view) | |
end | |
-- Key mapping for F4 (Strip whitespace) | |
vim.api.nvim_set_keymap('n', '<F4>', ':lua strip_trailing_whitespace()<CR>', {noremap = true, silent = true}) | |
-- Color scheme (wrapped in pcall to avoid errors on first run) | |
pcall(function() | |
vim.cmd[[colorscheme base16-gruvbox-dark-hard]] | |
end) | |
-- Setup conform.nvim for formatting | |
require("conform").setup({ | |
formatters_by_ft = { | |
lua = { "stylua" }, | |
python = { "isort", "black" }, | |
terraform = { "terraform_fmt" }, | |
json = { "jq" }, | |
sh = { "shfmt" }, | |
bash = { "shfmt" }, | |
yaml = { "yamlfix" }, | |
markdown = { "prettier" }, | |
powershell = { "psscriptanalyzer" }, | |
}, | |
format_on_save = false, -- We'll use F5 instead of format on save | |
}) | |
-- Key mapping for F5 (Autoformat) | |
vim.api.nvim_set_keymap('n', '<F5>', ':lua require("conform").format()<CR>', {noremap = true, silent = true}) | |
EOL | |
cat >> ~/.config/nvim/init.lua << EOL | |
-- LSP and completion setup (wrapped in pcall to avoid errors if plugins are not yet installed) | |
pcall(function() | |
-- LSP setup | |
require("mason").setup() | |
require("mason-lspconfig").setup() | |
local lspconfig = require('lspconfig') | |
local capabilities = require('cmp_nvim_lsp').default_capabilities() | |
-- Setup language servers | |
local servers = { | |
'pyright', -- Python | |
'terraformls', -- Terraform | |
'powershell_es', -- PowerShell | |
'bashls', -- Bash (for Azure CLI scripts) | |
'jsonls', -- JSON (for JQ and Databricks notebooks) | |
'yamlls', -- YAML | |
} | |
for _, lsp in ipairs(servers) do | |
lspconfig[lsp].setup { | |
capabilities = capabilities, | |
} | |
end | |
-- Completion setup | |
local cmp = require('cmp') | |
cmp.setup({ | |
snippet = { | |
expand = function(args) | |
require('luasnip').lsp_expand(args.body) | |
end, | |
}, | |
mapping = cmp.mapping.preset.insert({ | |
['<C-b>'] = cmp.mapping.scroll_docs(-4), | |
['<C-f>'] = cmp.mapping.scroll_docs(4), | |
['<C-Space>'] = cmp.mapping.complete(), | |
['<C-e>'] = cmp.mapping.abort(), | |
['<CR>'] = cmp.mapping.confirm({ select = true }), | |
}), | |
sources = cmp.config.sources({ | |
{ name = 'nvim_lsp' }, | |
{ name = 'luasnip' }, | |
}, { | |
{ name = 'buffer' }, | |
}) | |
}) | |
-- Key mappings | |
local opts = { noremap=true, silent=true } | |
vim.keymap.set('n', '<space>e', vim.diagnostic.open_float, opts) | |
vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, opts) | |
vim.keymap.set('n', ']d', vim.diagnostic.goto_next, opts) | |
vim.keymap.set('n', '<space>q', vim.diagnostic.setloclist, opts) | |
-- Use LspAttach autocommand to only map the following keys | |
-- after the language server attaches to the current buffer | |
vim.api.nvim_create_autocmd('LspAttach', { | |
group = vim.api.nvim_create_augroup('UserLspConfig', {}), | |
callback = function(ev) | |
local bufopts = { noremap=true, silent=true, buffer=ev.buf } | |
vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, bufopts) | |
vim.keymap.set('n', 'gd', vim.lsp.buf.definition, bufopts) | |
vim.keymap.set('n', 'K', vim.lsp.buf.hover, bufopts) | |
vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, bufopts) | |
vim.keymap.set('n', '<C-k>', vim.lsp.buf.signature_help, bufopts) | |
vim.keymap.set('n', '<space>wa', vim.lsp.buf.add_workspace_folder, bufopts) | |
vim.keymap.set('n', '<space>wr', vim.lsp.buf.remove_workspace_folder, bufopts) | |
vim.keymap.set('n', '<space>wl', function() | |
print(vim.inspect(vim.lsp.buf.list_workspace_folders())) | |
end, bufopts) | |
vim.keymap.set('n', '<space>D', vim.lsp.buf.type_definition, bufopts) | |
vim.keymap.set('n', '<space>rn', vim.lsp.buf.rename, bufopts) | |
vim.keymap.set('n', '<space>ca', vim.lsp.buf.code_action, bufopts) | |
vim.keymap.set('n', 'gr', vim.lsp.buf.references, bufopts) | |
vim.keymap.set('n', '<space>f', function() vim.lsp.buf.format { async = true } end, bufopts) | |
end, | |
}) | |
end) | |
-- Filetype-specific settings | |
vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"}, { | |
pattern = "*.bicepparam", | |
command = "set filetype=bicep", | |
}) | |
vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"}, { | |
pattern = "*.tf,*.tfvars", | |
command = "set filetype=terraform", | |
}) | |
vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"}, { | |
pattern = "*.az", | |
command = "set filetype=sh", | |
}) | |
vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"}, { | |
pattern = "*.databricks", | |
command = "set filetype=json", | |
}) | |
print("Neovim configuration loaded successfully!") | |
EOL | |
# Install language servers and tools | |
echo "Installing language servers and tools..." | |
sudo npm install -g pyright typescript typescript-language-server | |
# Install Rust and rust-analyzer | |
if ! command -v rustc &> /dev/null; then | |
echo "Installing Rust..." | |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y | |
source $HOME/.cargo/env | |
rustup component add rust-analyzer | |
else | |
echo "Rust is already installed, skipping..." | |
fi | |
# Function to install Mason packages | |
install_mason_package() { | |
nvim --headless -c "MasonInstall $1" -c qall || echo "Failed to install $1" | |
} | |
# Install plugins and language servers | |
echo "Installing plugins and language servers..." | |
nvim --headless "+Lazy! sync" +qa | |
echo "Installing Mason packages..." | |
install_mason_package "pyright" | |
install_mason_package "terraform-ls" | |
install_mason_package "powershell-editor-services" | |
install_mason_package "bash-language-server" | |
install_mason_package "json-lsp" | |
install_mason_package "yaml-language-server" | |
# Final message | |
echo "Setup complete! You can now start Neovim by running 'nvim'." | |
echo "All plugins and language servers have been installed automatically." | |
echo "You may need to restart your terminal or log out and back in for font changes to take effect." | |
echo "Enjoy your new Neovim setup!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment