{ config, lib, pkgs, ... }: with lib; let cfg = config.programs.neovim.extras; nvr = "${pkgs.neovim-remote}/bin/nvr"; shellConfig = with cfg.nvrAliases; '' # START programs.neovim.extras config ---------------------------------------------------------- '' + optionalString cfg.termBufferAutoChangeDir '' # If shell is running in a Neovim terminal buffer, set the PWD of the buffer to `$PWD`. if test -n "$NVIM_LISTEN_ADDRESS"; nvim-sync-term-buffer-pwd; end '' + optionalString cfg.nvrAliases.enable '' # Neovim Remote aliases if test -n "$NVIM_LISTEN_ADDRESS" alias ${edit} "${nvr}" alias ${split} "${nvr} -o" alias ${vsplit} "${nvr} -O" alias ${tabedit} "${nvr} --remote-tab" alias ${nvim} "command nvim" alias nvim "echo 'This shell is running in a Neovim termainal buffer. Use \'${nvim}\' to a nested instance of Neovim, otherwise use ${edit}, ${split}, ${vsplit}, or ${tabedit} to open files in the this Neovim instance.'" else alias ${edit} "nvim" end '' + '' # END programs.neovim.extras config ------------------------------------------------------------ ''; in { options.programs.neovim.extras = { termBufferAutoChangeDir = mkOption { type = types.bool; default = false; description = '' When enabled, the pwd of terminal buffers in Neovim are automatically updated to match $PWD of the shell running inside them. Note that you cannot use this option if you are using , use and instead. (Currently only works with Fish shell.) ''; }; nvrAliases = { enable = mkOption { type = types.bool; default = false; description = '' When enabled, shell aliases for helpful Neovim Remote commands are created if the shell is running inside a Neovim terminal buffer. Additionally, running nvim won't open a nested Neovim instance but instead print a message listing the available nvr aliases, as well as the command to run if you actually want to open a nested Neovim instance. Note that you cannot use this option if you are using , use and instead. (Currently only works with Fish shell.) ''; }; edit = mkOption { type = types.str; default = "n"; description = '' Equivalent to Neovim's :edit command, i.e., running n [file] will open the file in the current window. When not in Neovim this also acts as an alias for nvim. (Alias for nvr.) ''; }; split = mkOption { type = types.str; default = "ns"; description = '' Equivalent to Neovim's :split/command> command. (Alias for nvr -o.) ''; }; vsplit = mkOption { type = types.str; default = "nv"; description = '' Equivalent to Neovim's :vsplit/command> command. (Alias for nvr -O.) ''; }; tabedit = mkOption { type = types.str; default = "nt"; description = '' Equivalent to Neovim's :tabedit command. (Alias for nvr --remote-tab.) ''; }; nvim = mkOption { type = types.str; default = "neovim"; description = '' Opens a nested Neovim instance. ''; }; }; luaPackages = mkOption { type = with types; listOf package; default = [ ]; example = [ pkgs.luajitPackages.busted pkgs.luajitPackages.luafilesystem ]; description = '' Lua packages to make available in Neovim Lua environment. Note that you cannot use this option if you are using , use and instead. ''; }; }; config = mkIf config.programs.neovim.enable { programs.fish.functions.nvim-sync-term-buffer-pwd = mkIf cfg.termBufferAutoChangeDir { body = '' if test -n "$NVIM_LISTEN_ADDRESS" ${nvr} -c "let g:term_buffer_pwds.$fish_pid = '$PWD' | call Set_term_buffer_pwd() " end ''; onVariable = "PWD"; }; programs.neovim.extraConfig = mkIf cfg.termBufferAutoChangeDir '' " START programs.neovim.extras.termBufferAutoChangeDir config -------------------------------- " Dictionary used to track the PWD of terminal buffers. Keys should be PIDs and values are is " PWD of the shell with that PID. These values are updated from the shell using `nvr`. let g:term_buffer_pwds = {} " Function to call to update the PWD of the current terminal buffer. function Set_term_buffer_pwd() abort if &buftype == 'terminal' && exists('g:term_buffer_pwds[b:terminal_job_pid]') execute 'lchd ' . g:term_buffer_pwds[b:terminal_job_pid] endif endfunction " Sometimes the PWD the shell in a terminal buffer will change when in another buffer, so " when entering a terminal buffer we update try to update it's PWD. augroup NvimTermPwd au! au BufEnter * if &buftype == 'terminal' | call Set_term_buffer_pwd() | endif augroup END " END programs.neovim.extras.termBufferAutoChangeDir config ---------------------------------- ''; programs.fish.interactiveShellInit = mkIf (cfg.termBufferAutoChangeDir || cfg.nvrAliases.enable) shellConfig; programs.neovim.plugins = lib.singleton ( pkgs.vimUtils.buildVimPluginFrom2Nix { name = "lua-env"; src = pkgs.linkFarm "neovim-lua-env" ( lib.forEach cfg.luaPackages ( p: { name = "lua"; path = "${p}/lib/lua/${p.lua.luaversion}"; } ) ); } ); }; }