Skip to content

Instantly share code, notes, and snippets.

@elijahmanor
Created March 27, 2023 04:59
Show Gist options
  • Save elijahmanor/b279553c0132bfad7eae23e34ceb593b to your computer and use it in GitHub Desktop.
Save elijahmanor/b279553c0132bfad7eae23e34ceb593b to your computer and use it in GitHub Desktop.
Neovim Switcher
alias nvim-lazy="NVIM_APPNAME=LazyVim nvim"
alias nvim-kick="NVIM_APPNAME=kickstart nvim"
alias nvim-chad="NVIM_APPNAME=NvChad nvim"
alias nvim-astro="NVIM_APPNAME=AstroNvim nvim"
function nvims() {
items=("default" "kickstart" "LazyVim" "NvChad" "AstroNvim")
config=$(printf "%s\n" "${items[@]}" | fzf --prompt=" Neovim Config  " --height=~50% --layout=reverse --border --exit-0)
if [[ -z $config ]]; then
echo "Nothing selected"
return 0
elif [[ $config == "default" ]]; then
config=""
fi
NVIM_APPNAME=$config nvim $@
}
bindkey -s ^a "nvims\n"
@RayneScofield
Copy link

in terminal input nvims and enter
not a valid number: ~50
nothing selected
what's wrong?

@rdlu
Copy link

rdlu commented Apr 26, 2023

Just a correction for fish-shell binding:

bind \ca nvims

Fish already does the <Enter> for me, so the last line of @Yumshot line is not working for me.

(Fedora 38, Fish-shell 3.6.1 + tmux inside alacritty here)

@hopezh
Copy link

hopezh commented May 11, 2023

Here's a PowerShell suggestion. Unfortunately aliases are very limited so I opted for a function and it isn't possible to bind hotkeys AFAIK. Add this to $PROFILE

function nvim_lazy()
{
  $env:NVIM_APPNAME="nvim-lazy"
  nvim $args
}

function nvims()
{
  $items = "default", "nvim-lazy"
  $config = $items | fzf --prompt=" Neovim Config  " --height=~50% --layout=reverse --border --exit-0

  if ([string]::IsNullOrEmpty($config))
  {
    Write-Output "Nothing selected"
    break
  }
 
  if ($config -eq "default")
  {
    $config = ""
  }

  $env:NVIM_APPNAME=$config
  nvim $args
}

--edit: formatting, description and args

Thanks for sharing.

May I ask how to select from the menu as generated from your script in PowerShell?

@stekks
Copy link

stekks commented May 15, 2023

Rep

Just to be sure: you have to have 'fzf' installed (I use 'scoop' for installing stuff in Powershell). Then you can select items by just typing some characters of the selection you want (fuzzy finder) or select with cursor keys.

@georgejean
Copy link

georgejean commented May 17, 2023

For anyone who uses bash

# Neovim config switcher
alias nvim-chad="NVIM_APPNAME=nvim-chad nvim"

nvims() {
  items=("default" "NvChad")
  config=$(printf "%s\n" "${items[@]}" | fzf --prompt=" Neovim Config  " --height=~50% --layout=reverse --border --exit-0)
  if [[ -z $config ]]; then
    echo "Nothing selected"
    return 0
  elif [[ $config == "default" ]]; then
    config=""
  fi
  NVIM_APPNAME=$config nvim $@
}

bind -x '"\C-a": nvims'

⚠ NVIM_APPNAME(s) in alias and items (configs other than default) must match.

@weedatom
Copy link

weedatom commented Jun 3, 2023

Here's a PowerShell suggestion. Unfortunately aliases are very limited so I opted for a function and it isn't possible to bind hotkeys AFAIK. Add this to $PROFILE

function nvim_lazy()
{
  $env:NVIM_APPNAME="nvim-lazy"
  nvim $args
}

function nvims()
{
  $items = "default", "nvim-lazy"
  $config = $items | fzf --prompt=" Neovim Config  " --height=~50% --layout=reverse --border --exit-0

  if ([string]::IsNullOrEmpty($config))
  {
    Write-Output "Nothing selected"
    break
  }
 
  if ($config -eq "default")
  {
    $config = ""
  }

  $env:NVIM_APPNAME=$config
  nvim $args
}

--edit: formatting, description and args

How Does It Works?

@andyantrim
Copy link

So to make this a little easier (having to type nvims each time gets a bit old) I have the following:

alias vi="nvim"

alias nvim-lazy="NVIM_APPNAME=LazyVim nvim"
alias nvim-chad="NVIM_APPNAME=NvChad nvim"
alias nvim-astro="NVIM_APPNAME=AstroNvim nvim"

function nvims() {
  items=("default" "LazyVim" "NvChad" "AstroNvim")
  config=$(printf "%s\n" "${items[@]}" | fzf --prompt=" Neovim Config  " --height=~50% --layout=reverse --border --exit-0)
  if [[ -z $config ]]; then
    echo "Nothing selected"
    return 0
  elif [[ $config == "default" ]]; then
    config=""
  else
    alias vi="NVIM_APPNAME=${config} nvim"
  fi
  NVIM_APPNAME=$config nvim $@
}

This has the same behavior, but rewrites the vi alias to take you to the last selected nvim distro. The idea here is nvims can then become a context switcher, that sets the nvim distro/version which can be opened in the future with vi command.

@doctorfree
Copy link

@andyantrim that's a pretty cool trick. I am attempting to incorporate this in the Lazyman definition of nvims. The problem I am trying to solve is continuing to allow the user to override the NVIM_APPNAME environment variable value while also enabling this persistent alias. That is, once the alias has been set, subsequent invocations of vi always set NVIM_APPNAME to whatever was previously selected. The user can no longer override that value other than rerunning nvims and selecting another config.

I'm experimenting with something like the following:

alias vi="NVIM_APPNAME=${NVIM_APPNAME:-${config}} nvim"

With this slightly revised alias, if the user has NVIM_APPNAME set then that is used, if not then the selected config is used in the alias. That is, what persists as an alias for vi is an NVIM_APPNAME setting either 1) from the environment, or 2) from the selection.

Does this make sense?

@QMaxPowerQ
Copy link

in terminal input nvims and enter not a valid number: ~50 nothing selected what's wrong?

any news on this?
I do have the same error while just using nvims without any argument. Using WSL2 - bash

@saccarosium
Copy link

Here a POSIX shell script that can switch between configurations and remember the last selected one.

#!/bin/sh

config=""
history="${XDG_CACHE_HOME:-$HOME/.cache}/nvim-configuration"
items="default kickstart LazyVim NvChad AstroNvim"

trap 'echo "$config" >"$history"' EXIT

case $1 in
    -C | --config)
        if [ -z "$2" ]; then
            config=$(echo "$items" | tr ' ' '\n' | fzf --prompt=" Neovim Config  " --height=~50% --layout=reverse --border --exit-0) || exit 0
            shift
        else
            config="$2"
            shift
            shift
        fi
        ;;
    *)
        config=$(cat "$history")
        ;;
esac

[ "$config" = "default" ] && config=""

NVIM_APPNAME="${config:-""}" nvim "$@"

Usage

NOTE All input extra input is passed to nvim

  • -C without extra input: prompt with fzf to select a configuration
  • -C with extra input: selects passed configuration
  • without any flag: use the last selected one or default

@ajmasia
Copy link

ajmasia commented Sep 14, 2023

I have created this script so that I can use it in a more customised way 😄

#!/usr/bin/env bash

# ANSI color codes
RED='\033[0;31m'
YELLOW='\033[1;33m'
GREEN='\033[0;32m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
CLEAR='\033[0m'

DEFAULT_INSTANCE=nvim-default

show_help() {
	echo -e "Usage: ${YELLOW}nvim-starter ${PURPLE}[COMMAND]${CYAN} [NVIM_OPTIONS...]${CLEAR}"
	echo
	echo "Available commands: (no command start nvim natively)"
	echo -e "  ${PURPLE}sel, select${CLEAR}     Show a selector to choose the Neovim configuration"
	echo -e "  ${PURPLE}def, default${CLEAR}    Start the default instance of Neovim"
	echo -e "  ${PURPLE}help${CLEAR}            Display this help message"
}

select_config() {
	local items=("default" "nvim" "nvim-learning")
	local config=$(printf "%s\n" "${items[@]}" | fzf --prompt=" Neovim Config: " --height=~50% --layout=reverse --exit-0)

	if [[ -z $config ]]; then
		echo "${GREEN}Nothing selected${CLEAR}"
		exit 0
	elif [[ $config == "default" ]]; then
		config=$DEFAULT_INSTANCE
	fi

	NVIM_APPNAME=$config nvim "$@"
}

default_exec() {
	# Default behavior (no script commds)
	nvim "$@"
	exit 0
}

[[ $# -eq 0 ]] && default_exec

while [[ $# -gt 0 ]]; do
	key="$1"

	case $key in
	help)
		show_help
		exit 0
		;;
	sel | select)
		shift # remove the -s or --select
		select_config "$@"
		exit 0
		;;
	def | default)
		shift # remove the -d or --default
		NVIM_APPNAME=$DEFAULT_INSTANCE nvim "$@"
		exit 0
		;;
	*)
		default_exec
		;;
	esac
done

@soomtong
Copy link

soomtong commented Oct 14, 2023

thanks a lot!

my configuration of zshrc for nvims here. made in macOS.

function nvims() {
  local nv_items=("Vanilla" "LazyVim" "NvChad")
  local nv_app=$(printf "%s\n" "${nv_items[@]}" | fzf --prompt=" Neovim Config 󰶻  " --height=~50% --layout=reverse --border --exit-0)

  if [[ -z $nv_app ]]; then
    echo "Nothing selected"
    return 0
  elif [[ $nv_app == "Vanilla" ]]; then
    nv_app=""
  else
    echo "Set $nvims_config to $nv_app"
  fi

  echo "$nv_app" > "$nvims_config"
  alias vi="NVIM_APPNAME=${nv_app} nvim"

  NVIM_APPNAME=$nv_app nvim $@
}

# nvims
if [[ -x /usr/local/bin/nvim || -x /opt/homebrew/bin/nvim ]]; then
  nvims_config="${XDG_CACHE_HOME:-$HOME/.cache}/nvims"
  nvims_app=$(cat "$nvims_config")
  #echo "Bind Neovim to $nvims_app"
  alias vi="NVIM_APPNAME=${nvims_app} nvim"
  export EDITOR="vi"
  bindkey -s "^v" "nvims\n"
fi

@ZediWards
Copy link

in terminal input nvims and enter not a valid number: ~50 nothing selected what's wrong?

any news on this? I do have the same error while just using nvims without any argument. Using WSL2 - bash

I had the same error.
Fix was to make height=50% NOT height=~50%
image

@hasecilu
Copy link

Due to some changes on Nerd Font you may want to update the glyphs to: " Neovim Config 󰄾 "

@wochap
Copy link

wochap commented Dec 5, 2023

For zsh, I refactored the function so you don't need to hardcode the options; it finds any folder in ~/.config with an init.lua file in it and considers it a nvim config folder. Additionally, it adds a preview using lsd to display the folder contents.

function nvims() {
  items=$(find $HOME/.config -maxdepth 2 -name "init.lua" -type f -execdir sh -c 'pwd | xargs basename' \;)
  selected=$(printf "%s\n" "${items[@]}" | FZF_DEFAULT_OPTS="${FZF_DEFAULT_OPTS-} --preview-window 'right:border-left:50%:<40(right:border-left:50%:hidden)' --preview 'lsd -l -A --tree --depth=1 --color=always --blocks=size,name ~/.config/{} | head -200'" fzf )
  if [[ -z $selected ]]; then
    return 0
  elif [[ $selected == "nvim" ]]; then
    selected=""
  fi
  NVIM_APPNAME=$selected nvim "$@"
}
alias nvs=nvims
Preview:

@hasecilu
Copy link

hasecilu commented Dec 5, 2023

For zsh, I refactored the function so you don't need to hardcode the options;

Nice, works well with eza too.

@Armadillidiid
Copy link

Armadillidiid commented Dec 5, 2023

@wochap I tried your script on my setup and it doesn't seem to detect symlinks. I store all my configs under ~/.dotfiles and generate respective symlinks using Stow. To work around it, I simply added an extra folder to search.

	items=$(
		find $HOME/.config -maxdepth 2 -name "init.lua" -type f -execdir sh -c 'pwd | xargs basename' \;
		find $HOME/.dotfiles -maxdepth 5 -name "init.lua" -type f -execdir sh -c 'pwd | xargs basename' \;
	)

@doctorfree
Copy link

Rather than adding an extra folder to search, the find command can be altered either with:

find $HOME/.config -maxdepth 2 -name "init.lua" "(" -type f -o -type l ")" -execdir sh -c 'pwd | xargs basename' \;

or

find -L $HOME/.config -maxdepth 2 -name "init.lua" -type f -execdir sh -c 'pwd | xargs basename' \;

Either of those will pickup both plain files and symbolic links.

I also ran into a problem on an Ubuntu 20.04 system with the older version of fzf in their repo. It did not understand the preview options:

invalid preview window layout: right:border-left:50%:<40(right:border-left:50%:hidden)

I simplified the preview options to get it to work on that system:

selected=$(printf "%s\n" "${items[@]}" | FZF_DEFAULT_OPTS="${FZF_DEFAULT_OPTS-} --preview-window=right:50% --preview 'lsd -l -A --tree --depth=1 --color=always --blocks=size,name ~/.config/{} | head -200'" fzf )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment