@@ -508,6 +508,14 @@ M.is_floating = function(win_id)
508508 return false
509509end
510510
511+ M .is_winfixbuf = function (win_id )
512+ if vim .fn .exists (" &winfixbuf" ) == 1 then
513+ win_id = win_id or vim .api .nvim_get_current_win ()
514+ return vim .api .nvim_get_option_value (" winfixbuf" , { win = win_id })
515+ end
516+ return false
517+ end
518+
511519--- Evaluates the value of <afile>, which comes from an autocmd event, and determines if it
512520--- is a valid file or some sort of utility buffer like quickfix or neo-tree itself.
513521--- @param afile string The path or relative path to the file.
@@ -565,7 +573,7 @@ M.map = function(tbl, fn)
565573 return t
566574end
567575
568- M .get_appropriate_window = function (state )
576+ M .get_appropriate_window = function (state , ignore_winfixbuf )
569577 -- Avoid triggering autocommands when switching windows
570578 local eventignore = vim .o .eventignore
571579 vim .o .eventignore = " all"
@@ -579,7 +587,7 @@ M.get_appropriate_window = function(state)
579587 local ignore = M .list_to_dict (ignore_ft )
580588 ignore [" neo-tree" ] = true
581589 if nt .config .open_files_in_last_window then
582- local prior_window = nt .get_prior_window (ignore )
590+ local prior_window = nt .get_prior_window (ignore , ignore_winfixbuf )
583591 if prior_window > 0 then
584592 local success = pcall (vim .api .nvim_set_current_win , prior_window )
585593 if success then
@@ -601,6 +609,9 @@ M.get_appropriate_window = function(state)
601609 if ignore [vim .bo .filetype ] or ignore [bt ] or M .is_floating () then
602610 attempts = attempts + 1
603611 vim .cmd (" wincmd w" )
612+ elseif ignore_winfixbuf and M .is_winfixbuf () then
613+ attempts = attempts + 1
614+ vim .cmd (" wincmd w" )
604615 else
605616 suitable_window_found = true
606617 end
@@ -642,6 +653,28 @@ M.resolve_width = function(width)
642653 return math.floor (width )
643654end
644655
656+ M .force_new_split = function (current_position , escaped_path )
657+ local result , err
658+ local split_command = " vsplit"
659+ -- respect window position in user config when Neo-tree is the only window
660+ if current_position == " left" then
661+ split_command = " rightbelow vs"
662+ elseif current_position == " right" then
663+ split_command = " leftabove vs"
664+ end
665+ if escaped_path == M .escape_path_for_cmd (" [No Name]" ) then
666+ -- vim's default behavior is to overwrite [No Name] buffers.
667+ -- We need to split first and then open the path to workaround this behavior.
668+ result , err = pcall (vim .cmd , split_command )
669+ if result then
670+ vim .cmd .edit (escaped_path )
671+ end
672+ else
673+ result , err = pcall (vim .cmd , split_command .. " " .. escaped_path )
674+ end
675+ return result , err
676+ end
677+
645678--- Open file in the appropriate window.
646679--- @param state table The state of the source
647680--- @param path string The file to open
@@ -654,7 +687,8 @@ M.open_file = function(state, path, open_cmd, bufnr)
654687 if bufnr <= 0 then
655688 bufnr = nil
656689 else
657- local buf_cmd_lookup = { edit = " b" , e = " b" , split = " sb" , sp = " sb" , vsplit = " vert sb" , vs = " vert sb" }
690+ local buf_cmd_lookup =
691+ { edit = " b" , e = " b" , split = " sb" , sp = " sb" , vsplit = " vert sb" , vs = " vert sb" }
658692 local cmd_for_buf = buf_cmd_lookup [open_cmd ]
659693 if cmd_for_buf then
660694 open_cmd = cmd_for_buf
@@ -692,28 +726,24 @@ M.open_file = function(state, path, open_cmd, bufnr)
692726 width = M .get_value (state , " window.width" , 40 , false )
693727 width = M .resolve_width (width )
694728 end
695-
696- local split_command = " vsplit"
697- -- respect window position in user config when Neo-tree is the only window
698- if state .current_position == " left" then
699- split_command = " rightbelow vs"
700- elseif state .current_position == " right" then
701- split_command = " leftabove vs"
702- end
703- if path == " [No Name]" then
704- result , err = pcall (vim .cmd , split_command )
705- if result then
706- vim .cmd (" b" .. bufnr )
707- end
708- else
709- result , err = pcall (vim .cmd , split_command .. " " .. escaped_path )
710- end
711-
729+ result , err = M .force_new_split (state .current_position , escaped_path )
712730 vim .api .nvim_win_set_width (winid , width )
713731 else
714732 result , err = pcall (vim .cmd , open_cmd .. " " .. bufnr_or_path )
715733 end
716734 end
735+ if not result and string.find (err or " " , " winfixbuf" ) and M .is_winfixbuf () then
736+ local winid , is_neo_tree_window = M .get_appropriate_window (state , true )
737+ -- Rescan window list to find a window that is not winfixbuf.
738+ -- If found, retry executing command in that window,
739+ -- otherwise, all windows are either neo-tree or winfixbuf so we make a new split.
740+ if not is_neo_tree_window and not M .is_winfixbuf (winid ) then
741+ vim .api .nvim_set_current_win (winid )
742+ result , err = pcall (vim .cmd , open_cmd .. " " .. bufnr_or_path )
743+ else
744+ result , err = M .force_new_split (state .current_position , escaped_path )
745+ end
746+ end
717747 if result or err == " Vim(edit):E325: ATTENTION" then
718748 -- fixes #321
719749 vim .api .nvim_buf_set_option (0 , " buflisted" , true )
0 commit comments