feat: add nvimdots
This commit is contained in:
416
nvim/scripts/install.ps1
Normal file
416
nvim/scripts/install.ps1
Normal file
@@ -0,0 +1,416 @@
|
||||
#Requires -Version 7.1
|
||||
|
||||
# We don't need return codes for "$(command)", only stdout is needed.
|
||||
# Allow `func "$(command)"`, pipes, etc.
|
||||
|
||||
Set-StrictMode -Version 3.0
|
||||
|
||||
$ErrorActionPreference = "Stop" # Exit when command fails
|
||||
|
||||
# global-scope vars
|
||||
$USE_SSH = $True
|
||||
$REQUIRED_NVIM_VERSION = [version]'0.10.0'
|
||||
$REQUIRED_NVIM_VERSION_LEGACY = [version]'0.9.0'
|
||||
|
||||
# package mgr vars
|
||||
$choco_package_matrix = @{ "gcc" = "mingw"; "git" = "git"; "nvim" = "neovim"; "make" = "make"; "sudo" = "psutils"; "node" = "nodejs"; "pip" = "python3"; "fzf" = "fzf"; "rg" = "ripgrep"; "go" = "go"; "curl" = "curl"; "wget" = "wget"; "tree-sitter" = "tree-sitter"; "ruby" = "ruby"; "rustc" = "rust-ms" }
|
||||
$scoop_package_matrix = @{ "gcc" = "mingw"; "git" = "git"; "nvim" = "neovim"; "make" = "make"; "sudo" = "psutils"; "node" = "nodejs"; "pip" = "python"; "fzf" = "fzf"; "rg" = "ripgrep"; "go" = "go"; "curl" = "curl"; "wget" = "wget"; "tree-sitter" = "tree-sitter"; "ruby" = "ruby"; "rustc" = "rust" }
|
||||
$installer_pkg_matrix = @{ "NodeJS" = "npm"; "Python" = "pip"; "Ruby" = "gem" }
|
||||
|
||||
# env vars
|
||||
$env:XDG_CONFIG_HOME ??= $env:LOCALAPPDATA
|
||||
$env:CCPACK_MGR ??= 'unknown'
|
||||
$env:CCLONE_ATTR ??= 'undef'
|
||||
$env:CCLONE_BRANCH ??= 'main'
|
||||
$env:CCLONE_BRANCH_LEGACY ??= '0.9'
|
||||
$env:CCDEST_DIR ??= "$env:XDG_CONFIG_HOME\nvim"
|
||||
$env:CCBACKUP_DIR = "$env:CCDEST_DIR" + "_backup-" + (Get-Date).ToUniversalTime().ToString("yyyyMMddTHHmmss")
|
||||
|
||||
function _abort ([Parameter(Mandatory = $True)] [string]$Msg,[Parameter(Mandatory = $True)] [string]$Type,[Parameter(Mandatory = $False)] [string]$ExtMsg) {
|
||||
if ($ExtMsg -ne $null) {
|
||||
Write-Host $ExtMsg
|
||||
}
|
||||
Write-Error -Message "Error: $Msg" -Category $Type
|
||||
exit 1
|
||||
}
|
||||
|
||||
function _chomp ([Parameter(Mandatory = $True)] [string]$Str) {
|
||||
return [string]::Join("\n",([string]::Join("\r",($Str.Split("`r"))).Split("`n")))
|
||||
}
|
||||
|
||||
# Check if script is run with non-interactive mode, this is not allowed
|
||||
# Returns $True if validation failed (i.e., in non-interactive mode)
|
||||
function test_host {
|
||||
$NonInteractive = [System.Environment]::GetCommandLineArgs() | Where-Object { $_ -like '-NonI*' }
|
||||
if ([System.Environment]::UserInteractive -and -not $NonInteractive) {
|
||||
return $False
|
||||
} else {
|
||||
return $True
|
||||
}
|
||||
}
|
||||
|
||||
function info ([Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()] [string]$Msg) {
|
||||
Write-Host "==> " -ForegroundColor Blue -NoNewline; Write-Host $(_chomp -Str $Msg);
|
||||
}
|
||||
|
||||
function info_ext ([Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()] [string]$Msg) {
|
||||
Write-Host " $(_chomp -Str $Msg)"
|
||||
}
|
||||
|
||||
function warn ([Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()] [string]$Msg) {
|
||||
Write-Host "Warning:" -ForegroundColor Yellow -NoNewline; Write-Host " $(_chomp -Str $Msg)";
|
||||
}
|
||||
|
||||
function warn_ext ([Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()] [string]$Msg) {
|
||||
Write-Host " $(_chomp -Str $Msg)"
|
||||
}
|
||||
|
||||
function safe_execute ([Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()] [scriptblock]$WithCmd) {
|
||||
try {
|
||||
Invoke-Command -ErrorAction Stop -ScriptBlock $WithCmd
|
||||
if (-not $?) {
|
||||
throw # Also stop the script if cmd failed
|
||||
}
|
||||
}
|
||||
catch {
|
||||
_abort -Msg "Failed during: $WithCmd" -Type "InvalidResult"
|
||||
}
|
||||
}
|
||||
|
||||
function wait_for_user {
|
||||
Write-Host ""
|
||||
Write-Host "Press " -NoNewline; Write-Host "RETURN" -ForegroundColor White -BackgroundColor DarkGray -NoNewline; Write-Host "/" -NoNewline; Write-Host "ENTER" -ForegroundColor White -BackgroundColor DarkGray -NoNewline; Write-Host " to continue or any other key to abort...";
|
||||
$ks = [System.Console]::ReadKey()
|
||||
if ($ks.Key -ne 'Enter') {
|
||||
Write-Host ""
|
||||
_abort -Msg "Aborted." -Type "OperationStopped"
|
||||
}
|
||||
}
|
||||
|
||||
function check_ssh {
|
||||
info -Msg "Validating SSH connection..."
|
||||
Invoke-Command -ErrorAction SilentlyContinue -ScriptBlock { ssh -T git@github.com *> $null }
|
||||
if ($LastExitCode -ne 1) {
|
||||
info -Msg "We'll use HTTPS to fetch and update plugins."
|
||||
return $True
|
||||
} else {
|
||||
$_title = "Fetch Preferences"
|
||||
$_message = "Do you prefer to use SSH to fetch and update plugins? (otherwise HTTPS)"
|
||||
|
||||
$_opt_ssh = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes","Will use SSH to fetch and update plugins in the future"
|
||||
$_opt_https = New-Object System.Management.Automation.Host.ChoiceDescription "&No","Will use HTTPS to fetch and update plugins in the future"
|
||||
|
||||
$USR_CHOICE = $Host.ui.PromptForChoice($_title,$_message,[System.Management.Automation.Host.ChoiceDescription[]]($_opt_ssh,$_opt_https),0)
|
||||
if ($USR_CHOICE -eq 0) {
|
||||
return $False
|
||||
} else {
|
||||
return $True
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function check_clone_pref {
|
||||
info -Msg "Checking 'git clone' preferences..."
|
||||
|
||||
$_title = "'git clone' Preferences"
|
||||
$_message = "Would you like to perform a shallow clone ('--depth=1')?"
|
||||
|
||||
$_opt_yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes","Will append '--depth=1' to 'git clone' options"
|
||||
$_opt_no = New-Object System.Management.Automation.Host.ChoiceDescription "&No","Do nothing"
|
||||
|
||||
$USR_CHOICE = $Host.ui.PromptForChoice($_title,$_message,[System.Management.Automation.Host.ChoiceDescription[]]($_opt_yes,$_opt_no),0)
|
||||
if ($USR_CHOICE -eq 0) {
|
||||
$env:CCLONE_ATTR = '--depth=1'
|
||||
} else {
|
||||
$env:CCLONE_ATTR = '--progress'
|
||||
}
|
||||
}
|
||||
|
||||
function check_in_path ([Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()] [string]$WithName) {
|
||||
if ((Get-Command $WithName -ErrorAction SilentlyContinue)) {
|
||||
return $True
|
||||
} else {
|
||||
return $False
|
||||
}
|
||||
}
|
||||
|
||||
function query_pack {
|
||||
if ((check_in_path -WithName "scoop") -and (check_in_path -WithName "choco")) {
|
||||
info -Msg " [Detected] Multiple package managers detected."
|
||||
|
||||
$_title = "Package manager Preferences"
|
||||
$_message = "Pick your favorite package manager"
|
||||
|
||||
$_opt_scoop = New-Object System.Management.Automation.Host.ChoiceDescription "&Scoop","Will use 'scoop' to install dependencies"
|
||||
$_opt_choco = New-Object System.Management.Automation.Host.ChoiceDescription "&Chocolatey","Will use 'choco' to install dependencies"
|
||||
|
||||
$USR_CHOICE = $Host.ui.PromptForChoice($_title,$_message,[System.Management.Automation.Host.ChoiceDescription[]]($_opt_scoop,$_opt_choco),0)
|
||||
if ($USR_CHOICE -eq 0) {
|
||||
$env:CCPACK_MGR = 'scoop'
|
||||
} else {
|
||||
$env:CCPACK_MGR = 'choco'
|
||||
}
|
||||
} elseif ((check_in_path -WithName "scoop")) {
|
||||
info -Msg " [Detected] We'll use 'Scoop' as the default package mgr."
|
||||
$env:CCPACK_MGR = 'scoop'
|
||||
} elseif ((check_in_path -WithName "choco")) {
|
||||
info -Msg " [Detected] We'll use 'Chocolatey' as the default package mgr."
|
||||
$env:CCPACK_MGR = 'choco'
|
||||
} else {
|
||||
_abort -Msg "Required executable not found." -Type "NotInstalled" -ExtMsg @'
|
||||
You must install a modern package manager before installing this Nvim config.
|
||||
Available choices are:
|
||||
- Chocolatey
|
||||
https://chocolatey.org/install#individual
|
||||
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
- Scoop
|
||||
https://scoop.sh/
|
||||
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
[INFO] "scoop" and "choco" are both either not installed, missing from PATH, or not executable.
|
||||
|
||||
'@
|
||||
}
|
||||
}
|
||||
|
||||
function init_pack {
|
||||
info -Msg "Initializing package manager preferences..."
|
||||
if ($env:CCPACK_MGR -ne 'unknown') {
|
||||
info -Msg '$env:CCPACK_MGR already defined. Validating...'
|
||||
if (($env:CCPACK_MGR -eq 'choco') -and (check_in_path -WithName $env:CCPACK_MGR)) {
|
||||
info -Msg "We'll use 'Chocolatey' as the default package mgr."
|
||||
} elseif (($env:CCPACK_MGR -eq 'scoop') -and (check_in_path -WithName $env:CCPACK_MGR)) {
|
||||
info -Msg "We'll use 'Scoop' as the default package mgr."
|
||||
} else {
|
||||
info -Msg "Validation failed. Fallback to query."
|
||||
query_pack
|
||||
}
|
||||
} else {
|
||||
query_pack
|
||||
}
|
||||
}
|
||||
|
||||
function _install_exe ([Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()] [string]$WithName) {
|
||||
if ($env:CCPACK_MGR -eq 'choco') {
|
||||
Write-Host "Attempting to install dependency [" -NoNewline; Write-Host $WithName -ForegroundColor Green -NoNewline; Write-Host "] with Chocolatey"
|
||||
$_inst_name = $choco_package_matrix[$WithName]
|
||||
safe_execute -WithCmd { choco install "$_inst_name" -y }
|
||||
}
|
||||
elseif ($env:CCPACK_MGR -eq 'scoop') {
|
||||
Write-Host "Attempting to install dependency [" -NoNewline; Write-Host $WithName -ForegroundColor Green -NoNewline; Write-Host "] with Scoop"
|
||||
$_inst_name = $scoop_package_matrix[$WithName]
|
||||
safe_execute -WithCmd { scoop install "$_inst_name" }
|
||||
} else {
|
||||
_abort -Msg 'This function is invoked incorrectly - Invalid data: $env:CCPACK_MGR' -Type "InvalidOperation"
|
||||
}
|
||||
}
|
||||
|
||||
function _install_nodejs_deps {
|
||||
safe_execute -WithCmd { npm install --global neovim tree-sitter-cli }
|
||||
}
|
||||
|
||||
function _install_python_deps {
|
||||
safe_execute -WithCmd { python -m pip install --user wheel }
|
||||
safe_execute -WithCmd { python -m pip install --user pynvim }
|
||||
}
|
||||
|
||||
function _install_ruby_deps {
|
||||
safe_execute -WithCmd { gem install neovim }
|
||||
safe_execute -WithCmd { ridk install }
|
||||
}
|
||||
|
||||
function check_and_fetch_exec ([Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()] [string]$PkgName) {
|
||||
$_str = "Checking dependency: '$PkgName'" + " " * 15
|
||||
Write-Host $_str.substring(0,[System.Math]::Min(40,$_str.Length)) -NoNewline
|
||||
|
||||
if (-not (check_in_path -WithName $PkgName)) {
|
||||
Start-Sleep -Milliseconds 350
|
||||
Write-Host "Failed" -ForegroundColor Red
|
||||
_install_exe -WithName $PkgName
|
||||
} else {
|
||||
Start-Sleep -Milliseconds 350
|
||||
Write-Host "Success" -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
|
||||
function confirm_dep_inst ([Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()] [string]$PkgName) {
|
||||
$_inst_name = $installer_pkg_matrix[$PkgName]
|
||||
if (-not (check_in_path -WithName "$_inst_name")) {
|
||||
_abort -Msg "This function is invoked incorrectly - The '$_inst_name' executable not found" -Type "InvalidOperation"
|
||||
} else {
|
||||
$_title = "Dependencies Installation"
|
||||
$_message = "Would you like to check & install $PkgName dependencies?"
|
||||
|
||||
$_opt_yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes","Will install $PkgName dependencies"
|
||||
$_opt_no = New-Object System.Management.Automation.Host.ChoiceDescription "&No","Will SKIP installing $PkgName dependencies"
|
||||
|
||||
$USR_CHOICE = $Host.ui.PromptForChoice($_title,$_message,[System.Management.Automation.Host.ChoiceDescription[]]($_opt_yes,$_opt_no),1)
|
||||
if ($USR_CHOICE -eq 0) {
|
||||
return $True
|
||||
} else {
|
||||
return $False
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fetch_deps {
|
||||
check_and_fetch_exec -PkgName "gcc"
|
||||
check_and_fetch_exec -PkgName "git"
|
||||
check_and_fetch_exec -PkgName "nvim"
|
||||
check_and_fetch_exec -PkgName "make"
|
||||
check_and_fetch_exec -PkgName "sudo"
|
||||
check_and_fetch_exec -PkgName "node"
|
||||
check_and_fetch_exec -PkgName "pip"
|
||||
check_and_fetch_exec -PkgName "fzf"
|
||||
check_and_fetch_exec -PkgName "rg"
|
||||
check_and_fetch_exec -PkgName "ruby"
|
||||
check_and_fetch_exec -PkgName "go"
|
||||
check_and_fetch_exec -PkgName "curl"
|
||||
check_and_fetch_exec -PkgName "wget"
|
||||
check_and_fetch_exec -PkgName "rustc"
|
||||
check_and_fetch_exec -PkgName "tree-sitter"
|
||||
|
||||
# Reload PATH for future use
|
||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
||||
}
|
||||
|
||||
function check_nvim_version ([Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()] [version]$RequiredVersionMin) {
|
||||
$nvim_version = Invoke-Command -ErrorAction SilentlyContinue -ScriptBlock { nvim --version } # First get neovim version
|
||||
$nvim_version = $nvim_version.Split([System.Environment]::NewLine) | Select-Object -First 1 # Then do head -n1
|
||||
$nvim_version = $nvim_version.Split('-') | Select-Object -First 1 # Special for dev branches
|
||||
$nvim_version = $nvim_version -replace '[^(\d+(\.\d+)*)]','' # Then do regex replacement similar to sed
|
||||
|
||||
$nvim_version = [version]$nvim_version
|
||||
return ($nvim_version -ge $RequiredVersionMin)
|
||||
}
|
||||
|
||||
function clone_repo ([Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()] [string]$WithURL) {
|
||||
if ((check_nvim_version -RequiredVersionMin $REQUIRED_NVIM_VERSION)) {
|
||||
safe_execute -WithCmd { git clone --progress -b "$env:CCLONE_BRANCH" "$env:CCLONE_ATTR" $WithURL "$env:CCDEST_DIR" }
|
||||
} elseif ((check_nvim_version -RequiredVersionMin $REQUIRED_NVIM_VERSION_LEGACY)) {
|
||||
warn -Msg "You have outdated Nvim installed (< $REQUIRED_NVIM_VERSION)."
|
||||
info -Msg "Automatically redirecting you to the latest compatible version..."
|
||||
safe_execute -WithCmd { git clone --progress -b "$env:CCLONE_BRANCH_LEGACY" "$env:CCLONE_ATTR" $WithURL "$env:CCDEST_DIR" }
|
||||
} else {
|
||||
warn -Msg "You have outdated Nvim installed (< $REQUIRED_NVIM_VERSION_LEGACY)."
|
||||
_abort -Msg "This Neovim distribution is no longer supported." -Type "NotImplemented" -ExtMsg @"
|
||||
You have a legacy Neovim distribution installed.
|
||||
Please make sure you have nvim v$REQUIRED_NVIM_VERSION_LEGACY installed at the very least.
|
||||
|
||||
"@
|
||||
}
|
||||
}
|
||||
|
||||
function ring_bell {
|
||||
[System.Console]::beep()
|
||||
}
|
||||
|
||||
function _main {
|
||||
if (-not $IsWindows) {
|
||||
_abort -Msg "This install script can only execute on Windows." -Type "DeviceError"
|
||||
}
|
||||
|
||||
if ((test_host)) {
|
||||
_abort -Msg "This script cannot proceed in non-interactive mode." -Type "NotImplemented"
|
||||
}
|
||||
|
||||
info -Msg "Checking dependencies..."
|
||||
|
||||
init_pack
|
||||
fetch_deps
|
||||
|
||||
if ((confirm_dep_inst -PkgName "NodeJS")) {
|
||||
_install_nodejs_deps
|
||||
}
|
||||
if ((confirm_dep_inst -PkgName "Python")) {
|
||||
_install_python_deps
|
||||
}
|
||||
if ((confirm_dep_inst -PkgName "Ruby")) {
|
||||
_install_ruby_deps
|
||||
}
|
||||
|
||||
# Check dependencies
|
||||
if (-not (check_in_path -WithName "nvim")) {
|
||||
_abort -Msg "Required executable not found." -Type "NotInstalled" -ExtMsg @'
|
||||
You must install Neovim before installing this Nvim config. See:
|
||||
https://github.com/neovim/neovim/wiki/Installing-Neovim
|
||||
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
[INFO] "nvim" is either not installed, missing from PATH, or not executable.
|
||||
|
||||
'@
|
||||
}
|
||||
|
||||
if (-not (check_in_path -WithName "git")) {
|
||||
_abort -Msg "Required executable not found." -Type "NotInstalled" -ExtMsg @'
|
||||
You must install Git before installing this Nvim config. See:
|
||||
https://git-scm.com/
|
||||
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
[INFO] "git" is either not installed, missing from PATH, or not executable.
|
||||
|
||||
'@
|
||||
}
|
||||
|
||||
info -Msg "This script will install ayamir/nvimdots to:"
|
||||
Write-Host $env:CCDEST_DIR
|
||||
|
||||
if ((Test-Path $env:CCDEST_DIR)) {
|
||||
warn -Msg "The destination folder: `"$env:CCDEST_DIR`" already exists."
|
||||
warn_ext -Msg "We will make a backup for you at `"$env:CCBACKUP_DIR`"."
|
||||
}
|
||||
|
||||
ring_bell
|
||||
wait_for_user
|
||||
if ((check_ssh)) {
|
||||
$USE_SSH = $False
|
||||
}
|
||||
check_clone_pref
|
||||
|
||||
if ((Test-Path $env:CCDEST_DIR)) {
|
||||
safe_execute -WithCmd { Move-Item -Path "$env:CCDEST_DIR" -Destination "$env:CCBACKUP_DIR" -Force }
|
||||
}
|
||||
|
||||
info -Msg "Fetching in progress..."
|
||||
|
||||
if ($USE_SSH) {
|
||||
clone_repo -WithURL 'git@github.com:ayamir/nvimdots.git'
|
||||
} else {
|
||||
clone_repo -WithURL 'https://github.com/ayamir/nvimdots.git'
|
||||
}
|
||||
|
||||
safe_execute -WithCmd { Set-Location -Path "$env:CCDEST_DIR" }
|
||||
safe_execute -WithCmd { Copy-Item -Path "$env:CCDEST_DIR\lua\user_template\" -Destination "$env:CCDEST_DIR\lua\user" -Recurse -Force }
|
||||
|
||||
if (-not $USE_SSH) {
|
||||
info -Msg "Changing default fetching method to HTTPS..."
|
||||
safe_execute -WithCmd {
|
||||
(Get-Content "$env:CCDEST_DIR\lua\user\settings.lua") |
|
||||
ForEach-Object { $_ -replace '\["use_ssh"\] = true','["use_ssh"] = false' } |
|
||||
Set-Content "$env:CCDEST_DIR\lua\user\settings.lua"
|
||||
}
|
||||
}
|
||||
|
||||
info -Msg "Spawning Neovim and fetching plugins... (You'll be redirected shortly)"
|
||||
info -Msg 'Please make sure you have a Rust Toolchain installed via `rustup`! Otherwise, unexpected things may'
|
||||
info_ext -Msg 'happen. See: https://www.rust-lang.org/tools/install.¯¯¯¯¯¯¯¯¯¯¯¯'
|
||||
info_ext -Msg ' ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯'
|
||||
info -Msg 'If lazy.nvim failed to fetch any plugin(s), maunally execute `:Lazy sync` until everything is up-to-date.'
|
||||
Write-Host @'
|
||||
|
||||
Thank you for using this set of configuration!
|
||||
- Project Homepage:
|
||||
https://github.com/ayamir/nvimdots
|
||||
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
- Further documentation (including executables you |must| install for full functionality):
|
||||
https://github.com/ayamir/nvimdots/wiki/Prerequisites
|
||||
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
'@
|
||||
|
||||
ring_bell
|
||||
wait_for_user
|
||||
|
||||
safe_execute -WithCmd { nvim }
|
||||
|
||||
# Exit the script
|
||||
exit
|
||||
}
|
||||
|
||||
_main
|
||||
304
nvim/scripts/install.sh
Executable file
304
nvim/scripts/install.sh
Executable file
@@ -0,0 +1,304 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# We don't need return codes for "$(command)", only stdout is needed.
|
||||
# Allow `[[ -n "$(command)" ]]`, `func "$(command)"`, pipes, etc.
|
||||
# shellcheck disable=SC2312
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
# global-scope vars
|
||||
REQUIRED_NVIM_VERSION=0.10.0
|
||||
REQUIRED_NVIM_VERSION_LEGACY=0.9.0
|
||||
USE_SSH=1
|
||||
CLONE_ATTR=("--progress")
|
||||
DEST_DIR="${HOME}/.config/nvim"
|
||||
BACKUP_DIR="${DEST_DIR}_backup-$(date +%Y%m%dT%H%M%S)"
|
||||
|
||||
abort() {
|
||||
printf "%s\n" "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Fail fast with a concise message when not using bash
|
||||
# Single brackets are needed here for POSIX compatibility
|
||||
# shellcheck disable=SC2292
|
||||
if [ -z "${BASH_VERSION:-}" ]; then
|
||||
abort "Bash is required to interpret this script."
|
||||
fi
|
||||
|
||||
# Check if script is run with force-interactive mode in CI
|
||||
if [[ -n "${CI-}" && -n "${INTERACTIVE-}" ]]; then
|
||||
abort "Cannot run force-interactive mode in CI."
|
||||
fi
|
||||
|
||||
# String formatters
|
||||
if [[ -t 1 ]]; then
|
||||
tty_escape() { printf "\033[%sm" "$1"; }
|
||||
else
|
||||
tty_escape() { :; }
|
||||
fi
|
||||
|
||||
tty_mkbold() { tty_escape "1;$1"; }
|
||||
tty_underline="$(tty_escape "4;39")"
|
||||
tty_yellow="$(tty_escape "0;33")"
|
||||
tty_blue="$(tty_mkbold 34)"
|
||||
tty_red="$(tty_mkbold 31)"
|
||||
tty_bold="$(tty_mkbold 39)"
|
||||
tty_reset="$(tty_escape 0)"
|
||||
|
||||
shell_join() {
|
||||
local arg
|
||||
printf "%s" "$1"
|
||||
shift
|
||||
for arg in "$@"; do
|
||||
printf " "
|
||||
printf "%s" "${arg// /\ }"
|
||||
done
|
||||
}
|
||||
|
||||
execute() {
|
||||
if ! "$@"; then
|
||||
abort "$(printf "Failed during: %s" "$(shell_join "$@")")"
|
||||
fi
|
||||
}
|
||||
|
||||
major_minor() {
|
||||
echo "${1%%.*}.$(
|
||||
x="${1#*.}"
|
||||
echo "${x%%.*}"
|
||||
)"
|
||||
}
|
||||
|
||||
chomp() {
|
||||
printf "%s" "${1/"$'\n'"/}"
|
||||
}
|
||||
|
||||
info() {
|
||||
printf "${tty_blue}==>${tty_bold} %s${tty_reset}\n" "$(shell_join "$@")"
|
||||
}
|
||||
|
||||
info_ext() {
|
||||
printf "${tty_bold} %s${tty_reset}\n" "$(shell_join "$@")"
|
||||
}
|
||||
|
||||
warn() {
|
||||
printf "${tty_yellow}Warning:${tty_reset} %s\n" "$(chomp "$1")"
|
||||
}
|
||||
|
||||
warn_ext() {
|
||||
printf " %s\n" "$(chomp "$1")"
|
||||
}
|
||||
|
||||
getc() {
|
||||
local save_state
|
||||
save_state="$(/bin/stty -g)"
|
||||
/bin/stty raw -echo
|
||||
IFS='' read -r -n 1 -d '' "$@"
|
||||
/bin/stty "${save_state}"
|
||||
}
|
||||
|
||||
ring_bell() {
|
||||
# Use the shell's audible bell
|
||||
if [[ -t 1 ]]; then
|
||||
printf "\a"
|
||||
fi
|
||||
}
|
||||
|
||||
wait_for_user() {
|
||||
local c
|
||||
printf "\n"
|
||||
echo "Press ${tty_bold}RETURN${tty_reset}/${tty_bold}ENTER${tty_reset} to continue or any other key to abort..."
|
||||
getc c
|
||||
# we test for \r and \n because some stuff does \r instead
|
||||
if ! [[ "$c" == $'\r' || "$c" == $'\n' ]]; then
|
||||
abort "${tty_red}Aborted.${tty_reset}"
|
||||
fi
|
||||
}
|
||||
|
||||
version_ge() {
|
||||
[[ "${1%.*}" -gt "${2%.*}" ]] || [[ "${1%.*}" -eq "${2%.*}" && "${1#*.}" -ge "${2#*.}" ]]
|
||||
}
|
||||
|
||||
prompt_confirm() {
|
||||
local choice
|
||||
while true; do
|
||||
read -r -p "$1 [Y/n]: " choice
|
||||
case "$choice" in
|
||||
[yY][eE][sS] | [yY])
|
||||
return 1
|
||||
;;
|
||||
[nN][oO] | [nN])
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
if [[ -z "$choice" ]]; then
|
||||
return 1
|
||||
fi
|
||||
printf "${tty_red}%s\n\n${tty_reset}" "Input invalid! Please enter one of the following: '[y/yes]' or '[n/no]'."
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
check_ssh() {
|
||||
info "Validating SSH connection..."
|
||||
ssh -T git@github.com &>/dev/null
|
||||
if ! [ $? -eq 1 ]; then
|
||||
info "We'll use HTTPS to fetch and update plugins."
|
||||
return 0
|
||||
else
|
||||
prompt_confirm "Do you prefer to use SSH to fetch and update plugins? (otherwise HTTPS)"
|
||||
return $?
|
||||
fi
|
||||
}
|
||||
|
||||
clone_pref() {
|
||||
info "Checking 'git clone' preferences..."
|
||||
if ! prompt_confirm "Would you like to perform a shallow clone ('--depth=1')?"; then
|
||||
CLONE_ATTR+=("--depth=1")
|
||||
fi
|
||||
}
|
||||
|
||||
check_nvim_version() {
|
||||
local nvim_version
|
||||
nvim_version="$(nvim --version | head -n1 | sed -e 's|^[^0-9]*||' -e 's| .*||')"
|
||||
if version_ge "$(major_minor "${nvim_version##* }")" "$(major_minor "$1")"; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
clone_repo() {
|
||||
if check_nvim_version "${REQUIRED_NVIM_VERSION}"; then
|
||||
execute "git" "clone" "-b" "main" "${CLONE_ATTR[@]}" "$1" "${DEST_DIR}"
|
||||
elif check_nvim_version "${REQUIRED_NVIM_VERSION_LEGACY}"; then
|
||||
warn "You have outdated Nvim installed (< ${REQUIRED_NVIM_VERSION})."
|
||||
info "Automatically redirecting you to the latest compatible version..."
|
||||
execute "git" "clone" "-b" "0.9" "${CLONE_ATTR[@]}" "$1" "${DEST_DIR}"
|
||||
else
|
||||
warn "You have outdated Nvim installed (< ${REQUIRED_NVIM_VERSION_LEGACY})."
|
||||
abort "$(
|
||||
cat <<EOABORT
|
||||
You have a legacy Neovim distribution installed.
|
||||
Please make sure you have nvim v${REQUIRED_NVIM_VERSION_LEGACY} installed at the very least.
|
||||
EOABORT
|
||||
)"
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if both `INTERACTIVE` and `NONINTERACTIVE` are set
|
||||
# Always use single-quoted strings with `exp` expressions
|
||||
# shellcheck disable=SC2016
|
||||
if [[ -n "${INTERACTIVE-}" && -n "${NONINTERACTIVE-}" ]]; then
|
||||
abort 'Both `$INTERACTIVE` and `$NONINTERACTIVE` are set. Please unset at least one variable and try again.'
|
||||
fi
|
||||
|
||||
# Check if script is run non-interactively (e.g. CI)
|
||||
# If it is run non-interactively we should not prompt for confirmation.
|
||||
# Always use single-quoted strings with `exp` expressions
|
||||
# shellcheck disable=SC2016
|
||||
if [[ -z "${NONINTERACTIVE-}" ]]; then
|
||||
if [[ -n "${CI-}" ]]; then
|
||||
warn 'Running in non-interactive mode because `$CI` is set.'
|
||||
NONINTERACTIVE=1
|
||||
elif [[ ! -t 0 ]]; then
|
||||
if [[ -z "${INTERACTIVE-}" ]]; then
|
||||
warn 'Running in non-interactive mode because `stdin` is not a TTY.'
|
||||
NONINTERACTIVE=1
|
||||
else
|
||||
warn 'Running in interactive mode despite `stdin` not being a TTY because `$INTERACTIVE` is set.'
|
||||
fi
|
||||
fi
|
||||
else
|
||||
info 'Running in non-interactive mode because `$NONINTERACTIVE` is set.'
|
||||
fi
|
||||
|
||||
if ! command -v perl >/dev/null; then
|
||||
abort "$(
|
||||
cat <<EOABORT
|
||||
Perl is required to interpret this script. See:
|
||||
${tty_underline}https://www.perl.org/get.html${tty_reset}
|
||||
EOABORT
|
||||
)"
|
||||
fi
|
||||
|
||||
if ! command -v nvim >/dev/null; then
|
||||
abort "$(
|
||||
cat <<EOABORT
|
||||
You must install Neovim before installing this Nvim config. See:
|
||||
${tty_underline}https://github.com/neovim/neovim/wiki/Installing-Neovim${tty_reset}
|
||||
EOABORT
|
||||
)"
|
||||
fi
|
||||
|
||||
if ! command -v git >/dev/null; then
|
||||
abort "$(
|
||||
cat <<EOABORT
|
||||
You must install Git before installing this Nvim config. See:
|
||||
${tty_underline}https://git-scm.com/${tty_reset}
|
||||
EOABORT
|
||||
)"
|
||||
fi
|
||||
|
||||
# Always use HTTPS when this script is run non-interactively (e.g. CI)
|
||||
if [[ -n "${NONINTERACTIVE-}" ]]; then
|
||||
USE_SSH=0
|
||||
fi
|
||||
|
||||
info "This script will install ayamir/nvimdots to:"
|
||||
echo "${DEST_DIR}"
|
||||
|
||||
if [[ -d "${DEST_DIR}" ]]; then
|
||||
warn "The destination folder: \"${DEST_DIR}\" already exists."
|
||||
warn_ext "We will make a backup for you at \"${BACKUP_DIR}\"."
|
||||
fi
|
||||
|
||||
if [[ -z "${NONINTERACTIVE-}" ]]; then
|
||||
ring_bell
|
||||
wait_for_user
|
||||
|
||||
if check_ssh; then
|
||||
USE_SSH=0
|
||||
fi
|
||||
clone_pref
|
||||
fi
|
||||
|
||||
if [[ -d "${DEST_DIR}" ]]; then
|
||||
execute "mv" "-f" "${DEST_DIR}" "${BACKUP_DIR}"
|
||||
fi
|
||||
|
||||
info "Fetching in progress..."
|
||||
if [[ "${USE_SSH}" -eq "1" ]]; then
|
||||
clone_repo "git@github.com:ayamir/nvimdots.git"
|
||||
else
|
||||
clone_repo "https://github.com/ayamir/nvimdots.git"
|
||||
fi
|
||||
|
||||
cd "${DEST_DIR}" || return
|
||||
execute "cp" "-fRpP" "${DEST_DIR}/lua/user_template/" "${DEST_DIR}/lua/user"
|
||||
|
||||
if [[ "${USE_SSH}" -eq "0" ]]; then
|
||||
info "Changing default fetching method to HTTPS..."
|
||||
execute "perl" "-pi" "-e" "s/\[\"use_ssh\"\] \= true/\[\"use_ssh\"\] \= false/g" "${DEST_DIR}/lua/user/settings.lua"
|
||||
fi
|
||||
|
||||
info "Spawning Neovim and fetching plugins... (You'll be redirected shortly)"
|
||||
info "NOTE: Please make sure you have a Rust Toolchain installed ${tty_underline}via \`rustup\`${tty_reset}${tty_bold}! Otherwise, unexpected things may"
|
||||
info_ext " happen. See: ${tty_underline}https://www.rust-lang.org/tools/install${tty_reset}."
|
||||
info_ext ""
|
||||
info "If lazy.nvim failed to fetch any plugin(s), maunally execute \`:Lazy sync\` until everything is up-to-date."
|
||||
cat <<EOS
|
||||
|
||||
Thank you for using this set of configuration!
|
||||
- Project Homepage:
|
||||
${tty_underline}https://github.com/ayamir/nvimdots${tty_reset}
|
||||
- Further documentation (including executables you ${tty_bold}must${tty_reset} install for full functionality):
|
||||
${tty_underline}https://github.com/ayamir/nvimdots/wiki/Prerequisites${tty_reset}
|
||||
EOS
|
||||
|
||||
if [[ -z "${NONINTERACTIVE-}" ]]; then
|
||||
ring_bell
|
||||
wait_for_user
|
||||
nvim
|
||||
fi
|
||||
Reference in New Issue
Block a user