diff --git a/nvim/init.vim b/nvim/init.vim index 0b09add4..26c9981e 100644 --- a/nvim/init.vim +++ b/nvim/init.vim @@ -1,11 +1,8 @@ -" Specify a directory for plugins default is ~/.config/nvim/init.vim call plug#begin('~/.vim/plugged') Plug 'neoclide/coc.nvim', {'branch': 'release'} -Plug 'scrooloose/nerdtree' "Plug 'tsony-tsonev/nerdtree-git-plugin' -Plug 'Xuyuanp/nerdtree-git-plugin' -Plug 'tiagofumo/vim-nerdtree-syntax-highlight' -Plug 'ryanoasis/vim-devicons' +Plug 'kyazdani42/nvim-web-devicons' " for file icons +Plug 'kyazdani42/nvim-tree.lua' Plug 'mattn/emmet-vim' Plug 'ap/vim-css-color' Plug 'airblade/vim-gitgutter' @@ -27,24 +24,77 @@ Plug 'jremmen/vim-ripgrep' " Initialize plugin system call plug#end() -"Toggle NerdTree with Ctrl + l -nmap :NERDTreeToggle +"nvim tree default setup +lua require'nvim-tree'.setup {} +let g:nvim_tree_git_hl = 1 "0 by default, will enable file highlight for git attributes (can be used without the icons). +let g:nvim_tree_highlight_opened_files = 1 "0 by default, will enable folder and file icon highlight for opened files/directories. +let g:nvim_tree_root_folder_modifier = ':~' "This is the default. See :help filename-modifiers for more options +let g:nvim_tree_add_trailing = 1 "0 by default, append a trailing slash to folder names +let g:nvim_tree_group_empty = 1 " 0 by default, compact folders that only contain a single folder into one node in the file tree +let g:nvim_tree_icon_padding = ' ' "one space by default, used for rendering the space between the icon and the filename. Use with caution, it could break rendering if you set an empty string depending on your font. +let g:nvim_tree_symlink_arrow = ' >> ' " defaults to ' ➛ '. used as a separator between symlinks' source and target. +let g:nvim_tree_respect_buf_cwd = 1 "0 by default, will change cwd of nvim-tree to that of new buffer's when opening nvim-tree. +let g:nvim_tree_create_in_closed_folder = 1 "0 by default, When creating files, sets the path of a file when cursor is on a closed folder to the parent folder when 0, and inside the folder when 1. +let g:nvim_tree_special_files = { 'README.md': 1, 'Makefile': 1, 'MAKEFILE': 1 } " List of filenames that gets highlighted with NvimTreeSpecialFile +let g:nvim_tree_show_icons = { + \ 'git': 1, + \ 'folders': 0, + \ 'files': 0, + \ 'folder_arrows': 0, + \ } +"If 0, do not show the icons for one of 'git' 'folder' and 'files' +"1 by default, notice that if 'files' is 1, it will only display +"if nvim-web-devicons is installed and on your runtimepath. +"if folder is 1, you can also tell folder_arrows 1 to show small arrows next to the folder icons. +"but this will not work when you set renderer.indent_markers.enable (because of UI conflict) -" Start NERDTree. If a file is specified, move the cursor to its window. -autocmd StdinReadPre * let s:std_in=1 -autocmd VimEnter * NERDTree | if argc() > 0 || exists("s:std_in") | wincmd p | endif +" default will show icon by default if no icon is provided +" default shows no icon by default +let g:nvim_tree_icons = { + \ 'default': "", + \ 'symlink': "", + \ 'git': { + \ 'unstaged': "✗", + \ 'staged': "✓", + \ 'unmerged': "", + \ 'renamed': "➜", + \ 'untracked': "★", + \ 'deleted': "", + \ 'ignored': "◌" + \ }, + \ 'folder': { + \ 'arrow_open': "", + \ 'arrow_closed': "", + \ 'default': "", + \ 'open': "", + \ 'empty': "", + \ 'empty_open': "", + \ 'symlink': "", + \ 'symlink_open': "", + \ } + \ } -"NerdTree opens on right -let g:NERDTreeWinPos = "right" +nnoremap :NvimTreeToggle +nnoremap r :NvimTreeRefresh +nnoremap n :NvimTreeFindFile +" More available functions: +" NvimTreeOpen +" NvimTreeClose +" NvimTreeFocus +" NvimTreeFindFileToggle +nnoremap :NvimTreeResize +" NvimTreeCollapse +" NvimTreeCollapseKeepBuffers -"Adjust NerdTree size -let g:NERDTreeWinSize=28 +set termguicolors " this variable must be enabled for colors to be applied properly -"Show hidden files in NERDTree -let NERDTreeShowHidden=1 +set nosplitright +" +" Automatically closes Nvim tree if last window open +autocmd BufEnter * ++nested if winnr('$') == 1 && bufname() == 'NvimTree_' . tabpagenr() | quit | endif -" Exit Vim if NERDTree is the only window remaining in the only tab. -autocmd BufEnter * if tabpagenr('$') == 1 && winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif +" a list of groups can be found at `:help nvim_tree_highlight` +highlight NvimTreeFolderIcon guibg=blue "set colored brackets via rainbow" let g:rainbow_active = 1 "set to 0 if you want to enable it later via :RainbowToggle" @@ -61,24 +111,8 @@ let g:auto_save = 1 "silence AutoSave messages let g:auto_save_silent = 1 -let g:webdevicons_enable = 1 -let g:webdevicons_enable_nerdtree = 1 - -let g:NERDTreeGitStatusWithFlags = 1 -"let g:WebDevIconsUnicodeDecorateFolderNodes = 1 -"let g:NERDTreeGitStatusNodeColorization = 1 -"let g:NERDTreeColorMapCustom = { - "\ "Staged" : "#0ee375", - "\ "Modified" : "#d9bf91", - "\ "Renamed" : "#51C9FC", - "\ "Untracked" : "#FCE77C", - "\ "Unmerged" : "#FC51E6", - "\ "Dirty" : "#FFBD61", - "\ "Clean" : "#/87939A", - "\ "Ignored" : "#808080" - "\ } - -let g:NERDTreeIgnore = ['^node_modules$'] +" let g:webdevicons_enable = 1 +" let g:webdevicons_enable_nerdtree = 1 " do not close the markdown preview tab when switching to other buffers let g:mkdp_auto_close = 0 @@ -178,24 +212,6 @@ hi Normal guibg=NONE ctermbg=NONE "Enable Comments with Italics (below selected colorscheme) highlight Comment cterm=italic gui=italic -" sync open file with NERDTree -" " Check if NERDTree is open or active -function! IsNERDTreeOpen() - return exists("t:NERDTreeBufName") && (bufwinnr(t:NERDTreeBufName) != -1) -endfunction - -" Call NERDTreeFind iff NERDTree is active, current window contains a modifiable -" file, and we're not in vimdiff -function! SyncTree() - if &modifiable && IsNERDTreeOpen() && strlen(expand('%')) > 0 && !&diff - NERDTreeFind - wincmd p - endif -endfunction - -" Highlight currently open buffer in NERDTree -autocmd BufEnter * call SyncTree() - " coc config let g:coc_global_extensions = [ \ 'coc-snippets', diff --git a/nvim/nvim-tree.lua b/nvim/nvim-tree.lua new file mode 100644 index 00000000..a6bbdcb1 --- /dev/null +++ b/nvim/nvim-tree.lua @@ -0,0 +1,471 @@ +-- /home/brian/.vim/plugged/nvim-tree.lua/lua + +local luv = vim.loop +local api = vim.api + +local lib = require "nvim-tree.lib" +local log = require "nvim-tree.log" +local colors = require "nvim-tree.colors" +local renderer = require "nvim-tree.renderer" +local view = require "nvim-tree.view" +local utils = require "nvim-tree.utils" +local change_dir = require "nvim-tree.actions.change-dir" +local legacy = require "nvim-tree.legacy" +local core = require "nvim-tree.core" + +local _config = {} + +local M = {} + +function M.focus() + M.open() + view.focus() +end + +---@deprecated +M.on_keypress = require("nvim-tree.actions").on_keypress + +function M.toggle(find_file, no_focus) + if view.is_visible() then + view.close() + else + local previous_buf = api.nvim_get_current_buf() + M.open() + if _config.update_focused_file.enable or find_file then + M.find_file(false, previous_buf) + end + if no_focus then + vim.cmd "noautocmd wincmd p" + end + end +end + +function M.open(cwd) + cwd = cwd ~= "" and cwd or nil + if view.is_visible() then + lib.set_target_win() + view.focus() + else + lib.open(cwd) + end +end + +function M.open_replacing_current_buffer() + if view.is_visible() then + return + end + + local buf = api.nvim_get_current_buf() + local bufname = api.nvim_buf_get_name(buf) + if bufname == "" or vim.loop.fs_stat(bufname) == nil then + return + end + + local cwd = vim.fn.fnamemodify(bufname, ":p:h") + if not core.get_explorer() or cwd ~= core.get_cwd() then + core.init(cwd) + end + view.open_in_current_win { hijack_current_buf = false, resize = false } + require("nvim-tree.renderer").draw() + require("nvim-tree.actions.find-file").fn(bufname) +end + +function M.tab_change() + if view.is_visible { any_tabpage = true } then + local bufname = vim.api.nvim_buf_get_name(0) + if bufname:match "Neogit" ~= nil or bufname:match "--graph" ~= nil then + return + end + view.open { focus_tree = false } + require("nvim-tree.renderer").draw() + end +end + +local function find_existing_windows() + return vim.tbl_filter(function(win) + local buf = api.nvim_win_get_buf(win) + return api.nvim_buf_get_name(buf):match "NvimTree" ~= nil + end, api.nvim_list_wins()) +end + +local function is_file_readable(fname) + local stat = luv.fs_stat(fname) + return stat and stat.type == "file" and luv.fs_access(fname, "R") +end + +local function update_base_dir_with_filepath(filepath, bufnr) + local ft = api.nvim_buf_get_option(bufnr, "filetype") or "" + for _, value in pairs(_config.update_focused_file.ignore_list) do + if utils.str_find(filepath, value) or utils.str_find(ft, value) then + return + end + end + + if not vim.startswith(filepath, core.get_explorer().cwd) then + change_dir.fn(vim.fn.fnamemodify(filepath, ":p:h")) + end +end + +function M.find_file(with_open, bufnr) + if not with_open and not core.get_explorer() then + return + end + + bufnr = bufnr or api.nvim_get_current_buf() + local bufname = api.nvim_buf_get_name(bufnr) + local filepath = utils.canonical_path(vim.fn.fnamemodify(bufname, ":p")) + if not is_file_readable(filepath) then + return + end + + if with_open then + M.open() + end + + vim.schedule(function() + -- if we don't schedule, it will search for NvimTree + if _config.update_focused_file.update_cwd then + update_base_dir_with_filepath(filepath, bufnr) + end + require("nvim-tree.actions.find-file").fn(filepath) + end) +end + +M.resize = view.resize + +function M.open_on_directory() + local should_proceed = M.initialized and (_config.hijack_directories.auto_open or view.is_visible()) + if not should_proceed then + return + end + + local buf = api.nvim_get_current_buf() + local bufname = api.nvim_buf_get_name(buf) + if vim.fn.isdirectory(bufname) ~= 1 then + return + end + + change_dir.force_dirchange(bufname, true) +end + +function M.reset_highlight() + colors.setup() + renderer.render_hl(view.get_bufnr()) +end + +local prev_line +function M.place_cursor_on_node() + local l = vim.api.nvim_win_get_cursor(0)[1] + if l == prev_line then + return + end + prev_line = l + + local node = lib.get_node_at_cursor() + if not node or node.name == ".." then + return + end + + local line = api.nvim_get_current_line() + local cursor = api.nvim_win_get_cursor(0) + local idx = vim.fn.stridx(line, node.name) + + if idx >= 0 then + api.nvim_win_set_cursor(0, { cursor[1], idx }) + end +end + +function M.on_enter(netrw_disabled) + local bufnr = api.nvim_get_current_buf() + local bufname = api.nvim_buf_get_name(bufnr) + local buftype = api.nvim_buf_get_option(bufnr, "filetype") + local ft_ignore = _config.ignore_ft_on_setup + + local stats = luv.fs_stat(bufname) + local is_dir = stats and stats.type == "directory" + local is_file = stats and stats.type == "file" + local cwd + if is_dir then + cwd = vim.fn.expand(bufname) + -- INFO: could potentially conflict with rooter plugins + vim.cmd("noautocmd cd " .. cwd) + end + + local lines = not is_dir and api.nvim_buf_get_lines(bufnr, 0, -1, false) or {} + local buf_has_content = #lines > 1 or (#lines == 1 and lines[1] ~= "") + + local buf_is_dir = is_dir and netrw_disabled + local buf_is_empty = bufname == "" and not buf_has_content + local should_be_preserved = vim.tbl_contains(ft_ignore, buftype) + + local should_open = false + local should_focus_other_window = false + local should_find = false + if (_config.open_on_setup or _config.open_on_setup_file) and not should_be_preserved then + if buf_is_dir or buf_is_empty then + should_open = true + elseif is_file and _config.open_on_setup_file then + should_open = true + should_focus_other_window = true + should_find = _config.update_focused_file.enable + elseif _config.ignore_buffer_on_setup then + should_open = true + should_focus_other_window = true + end + end + + local should_hijack = _config.hijack_directories.enable + and _config.hijack_directories.auto_open + and is_dir + and not should_be_preserved + + -- Session that left a NvimTree Buffer opened, reopen with it + local existing_tree_wins = find_existing_windows() + if existing_tree_wins[1] then + api.nvim_set_current_win(existing_tree_wins[1]) + end + + if should_open or should_hijack or existing_tree_wins[1] ~= nil then + lib.open(cwd) + + if should_focus_other_window then + vim.cmd "noautocmd wincmd p" + if should_find then + M.find_file(false) + end + end + end + M.initialized = true +end + +local function manage_netrw(disable_netrw, hijack_netrw) + if hijack_netrw then + vim.cmd "silent! autocmd! FileExplorer *" + vim.cmd "autocmd VimEnter * ++once silent! autocmd! FileExplorer *" + end + if disable_netrw then + vim.g.loaded_netrw = 1 + vim.g.loaded_netrwPlugin = 1 + end +end + +local function setup_vim_commands() + vim.cmd [[ + command! -nargs=? -complete=dir NvimTreeOpen lua require'nvim-tree'.open("") + command! NvimTreeClose lua require'nvim-tree.view'.close() + command! NvimTreeToggle lua require'nvim-tree'.toggle(false) + command! NvimTreeFocus lua require'nvim-tree'.focus() + command! NvimTreeRefresh lua require'nvim-tree.actions.reloaders'.reload_explorer() + command! NvimTreeClipboard lua require'nvim-tree.actions.copy-paste'.print_clipboard() + command! NvimTreeFindFile lua require'nvim-tree'.find_file(true) + command! NvimTreeFindFileToggle lua require'nvim-tree'.toggle(true) + command! -nargs=1 NvimTreeResize lua require'nvim-tree'.resize("") + command! NvimTreeCollapse lua require'nvim-tree.actions.collapse-all'.fn() + command! NvimTreeCollapseKeepBuffers lua require'nvim-tree.actions.collapse-all'.fn(true) + ]] +end + +function M.change_dir(name) + change_dir.fn(name) + + if _config.update_focused_file.enable then + M.find_file(false) + end +end + +local function setup_autocommands(opts) + vim.cmd "augroup NvimTree" + vim.cmd "autocmd!" + + -- reset highlights when colorscheme is changed + vim.cmd "au ColorScheme * lua require'nvim-tree'.reset_highlight()" + if opts.auto_reload_on_write then + vim.cmd "au BufWritePost * lua require'nvim-tree.actions.reloaders'.reload_explorer()" + end + vim.cmd "au User FugitiveChanged,NeogitStatusRefreshed lua require'nvim-tree.actions.reloaders'.reload_git()" + + if opts.open_on_tab then + vim.cmd "au TabEnter * lua require'nvim-tree'.tab_change()" + end + if opts.hijack_cursor then + vim.cmd "au CursorMoved NvimTree_* lua require'nvim-tree'.place_cursor_on_node()" + end + if opts.update_cwd then + vim.cmd "au DirChanged * lua require'nvim-tree'.change_dir(vim.loop.cwd())" + end + if opts.update_focused_file.enable then + vim.cmd "au BufEnter * lua require'nvim-tree'.find_file(false)" + end + + if not opts.actions.open_file.quit_on_open then + vim.cmd "au BufWipeout NvimTree_* lua require'nvim-tree.view'._prevent_buffer_override()" + else + vim.cmd "au BufWipeout NvimTree_* lua require'nvim-tree.view'.abandon_current_window()" + end + + if opts.hijack_directories.enable then + vim.cmd "au BufEnter,BufNewFile * lua require'nvim-tree'.open_on_directory()" + end + + vim.cmd "augroup end" +end + +local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS + auto_reload_on_write = true, + disable_netrw = false, + hide_root_folder = false, + hijack_cursor = false, + hijack_netrw = true, + hijack_unnamed_buffer_when_opening = false, + ignore_buffer_on_setup = false, + open_on_setup = false, + open_on_setup_file = false, + open_on_tab = false, + sort_by = "name", + update_cwd = false, + view = { + width = 25, + height = 30, + side = "right", + preserve_window_proportions = true, + number = false, + relativenumber = false, + signcolumn = "yes", + mappings = { + custom_only = false, + list = { + -- user mappings go here + }, + }, + }, + renderer = { + indent_markers = { + enable = false, + icons = { + corner = "└ ", + edge = "│ ", + none = " ", + }, + }, + }, + hijack_directories = { + enable = true, + auto_open = true, + }, + update_focused_file = { + enable = false, + update_cwd = false, + ignore_list = {}, + }, + ignore_ft_on_setup = {}, + system_open = { + cmd = nil, + args = {}, + }, + diagnostics = { + enable = false, + show_on_dirs = false, + icons = { + hint = "", + info = "", + warning = "", + error = "", + }, + }, + filters = { + dotfiles = true, + custom = {}, + exclude = {}, + }, + git = { + enable = true, + ignore = true, + timeout = 400, + }, + actions = { + use_system_clipboard = true, + change_dir = { + enable = true, + global = false, + }, + open_file = { + quit_on_open = false, + resize_window = false, + window_picker = { + enable = true, + chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", + exclude = { + filetype = { "notify", "packer", "qf", "diff", "fugitive", "fugitiveblame" }, + buftype = { "nofile", "terminal", "help" }, + }, + }, + }, + }, + trash = { + cmd = "trash", + require_confirm = true, + }, + log = { + enable = false, + truncate = false, + types = { + all = false, + config = false, + copy_paste = false, + git = false, + profile = false, + }, + }, +} -- END_DEFAULT_OPTS + +local function merge_options(conf) + if conf and conf.update_to_buf_dir then + conf.hijack_directories = conf.update_to_buf_dir + conf.update_to_buf_dir = nil + end + return vim.tbl_deep_extend("force", DEFAULT_OPTS, conf or {}) +end + +function M.setup(conf) + legacy.migrate_legacy_options(conf or {}) + + local opts = merge_options(conf) + local netrw_disabled = opts.disable_netrw or opts.hijack_netrw + + if opts.auto_close then + utils.warn "auto close feature has been removed, see note in the README (tips & reminder section)" + end + + _config.update_focused_file = opts.update_focused_file + _config.open_on_setup = opts.open_on_setup + _config.open_on_setup_file = opts.open_on_setup_file + _config.ignore_buffer_on_setup = opts.ignore_buffer_on_setup + _config.ignore_ft_on_setup = opts.ignore_ft_on_setup + _config.hijack_directories = opts.hijack_directories + _config.hijack_directories.enable = _config.hijack_directories.enable and netrw_disabled + + manage_netrw(opts.disable_netrw, opts.hijack_netrw) + + require("nvim-tree.log").setup(opts) + + log.line("config", "default config + user") + log.raw("config", "%s\n", vim.inspect(opts)) + + require("nvim-tree.actions").setup(opts) + require("nvim-tree.colors").setup() + require("nvim-tree.diagnostics").setup(opts) + require("nvim-tree.explorer").setup(opts) + require("nvim-tree.git").setup(opts) + require("nvim-tree.view").setup(opts) + require("nvim-tree.lib").setup(opts) + require("nvim-tree.renderer").setup(opts) + + setup_vim_commands() + setup_autocommands(opts) + + vim.schedule(function() + M.on_enter(netrw_disabled) + end) +end + +return M