Skip to content

Commit 8aacc48

Browse files
Adding options for showing current file, using relative path...
Adding options for showing current file, using relative path for open files, opening in newtab if needed
1 parent 0c6c2b2 commit 8aacc48

2 files changed

Lines changed: 181 additions & 21 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ The only fix is to close and open the tree.
7171
| `filemanager2.foldersfirst` | Sorts folders above any files | `true` |
7272
| `filemanager2.openonstart` | Automatically open the file tree when starting Micro | `false` |
7373
| `filemanager2.nerdfonts` | Use nerd fonts icons | `false` |
74+
| `filemanager2.showcurrent` | Show and expand to current file in tree | `true` |
75+
| `filemanager2.relativepath` | Use relative paths when possible | `true` |
76+
| `filemanager2.newtab` | Open files in new tabs instead of splits | `true` |
7477

7578
### Commands and Keybindings
7679

filemanager2.lua

Lines changed: 178 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ end
3030

3131
-- Holds the micro.CurPane() we're manipulating
3232
local tree_view = nil
33+
-- The last bufpane we were using before we open the tree
34+
local last_buf_pane = nil
3335
-- Keeps track of the current working directory
3436
local current_dir = os.Getwd()
3537
-- Keep track of current highest visible indent to resize width appropriately
@@ -84,6 +86,17 @@ local function is_dir(path)
8486
end
8587
end
8688

89+
-- Turn to relative path if possible
90+
local function try_convert_rel(path)
91+
local wd, err = os.Getwd()
92+
if err == nil then
93+
local relPath, relErr = filepath.Rel(wd, path)
94+
return relPath
95+
end
96+
97+
return path
98+
end
99+
87100
-- Returns a list of files (in the target dir) that are ignored by the VCS system (if exists)
88101
-- aka this returns a list of gitignored files (but for whatever VCS is found)
89102
local function get_ignored_files(tar_dir)
@@ -539,6 +552,101 @@ local function go_back_dir()
539552
end
540553
end
541554

555+
function open_pane_if_exist(path)
556+
local cleanFilepath = filepath.Clean(path)
557+
local wd, wdErr = os.Getwd()
558+
for i = 1, #micro.Tabs().List do
559+
for j = 1, #micro.Tabs().List[i].Panes do
560+
local currentPane = micro.Tabs().List[i].Panes[j]
561+
local currentBuf = currentPane.Buf
562+
563+
-- if currentBuf ~= nil then
564+
-- micro.Log("cleanFilepath:", cleanFilepath)
565+
-- micro.Log("currentBuf.AbsPath:", currentBuf.AbsPath)
566+
-- micro.Log("currentBuf.Path:", currentBuf.Path)
567+
-- end
568+
569+
if currentBuf ~= nil and currentBuf.AbsPath ~= "" and currentBuf.AbsPath ~= nil then
570+
local calculatedAbsPath = filepath.Abs(cleanFilepath)
571+
if not filepath.IsAbs(cleanFilepath) and wdErr == nil then
572+
local absPath, absErr = filepath.Abs(filepath.Join(wd, cleanFilepath))
573+
-- micro.Log("absPath:", absPath)
574+
if absErr == nil then
575+
calculatedAbsPath = absPath
576+
end
577+
end
578+
-- micro.Log("calculatedAbsPath:", calculatedAbsPath)
579+
580+
if filepath.Clean(currentBuf.AbsPath) == calculatedAbsPath or
581+
filepath.Clean(currentBuf.AbsPath) == cleanFilepath or
582+
filepath.Clean(currentBuf.Path) == cleanFilepath then
583+
584+
-- NOTE: SetActive functions has index starting at 0 instead lol
585+
micro.Tabs():SetActive(i - 1)
586+
micro.Tabs().List[i]:SetActive(j - 1)
587+
return true
588+
end
589+
end
590+
end
591+
end
592+
593+
return false
594+
end
595+
596+
-- Stat a path to check if it exists, returning true/false
597+
local function path_exists(path)
598+
local go_os = import('os')
599+
-- Stat the file/dir path we created
600+
-- file_stat should be non-nil, and stat_err should be nil on success
601+
local file_stat, stat_err = go_os.Stat(path)
602+
-- Check if what we tried to create exists
603+
if stat_err ~= nil then
604+
-- true/false if the file/dir exists
605+
return go_os.IsExist(stat_err)
606+
elseif file_stat ~= nil then
607+
-- Assume it exists if no errors
608+
return true
609+
end
610+
return false
611+
end
612+
613+
614+
local function is_path_dir(path)
615+
-- Stat the file/dir path we created
616+
-- file_stat should be non-nil, and stat_err should be nil on success
617+
local file_stat, stat_err = os.Stat(path)
618+
if stat_err ~= nil then
619+
return false
620+
elseif file_stat ~= nil then
621+
-- Assume it exists if no errors
622+
return file_stat:IsDir()
623+
end
624+
return false
625+
end
626+
627+
628+
function smart_new_tab(path)
629+
local cleanFilepath = filepath.Clean(path)
630+
631+
-- If current pane is empty, we can open in it
632+
if not path_exists(last_buf_pane.Buf.AbsPath) or is_path_dir(last_buf_pane.Buf.AbsPath) then
633+
if #last_buf_pane.Buf:Bytes() == 0 then
634+
last_buf_pane:OpenCmd({cleanFilepath})
635+
return
636+
end
637+
end
638+
639+
-- Otherwise find if there's any existing panes
640+
if open_pane_if_exist(cleanFilepath) then
641+
return
642+
end
643+
644+
-- If not just open it
645+
local currentActiveIndex = micro.Tabs():Active()
646+
last_buf_pane:NewTabCmd({cleanFilepath})
647+
last_buf_pane:TabMoveCmd({tostring(currentActiveIndex + 2)})
648+
end
649+
542650
-- Tries to open the current index
543651
-- If it's the top dir indicator, or separator, nothing happens
544652
-- If it's ".." then it tries to go back a dir
@@ -558,10 +666,21 @@ local function try_open_at_y(y)
558666
-- if passed path is a directory, update the current dir to be one deeper..
559667
update_current_dir(scanlist[y].abspath)
560668
else
669+
local open_path = scanlist[y].abspath
670+
671+
if config.GetGlobalOption('filemanager2.relativepath') then
672+
open_path = try_convert_rel(scanlist[y].abspath)
673+
end
674+
561675
-- If it's a file, then open it
562-
micro.InfoBar():Message('Filemanager2 opened ', scanlist[y].abspath)
563-
-- Opens the absolute path in new vertical view
564-
micro.CurPane():VSplitIndex(buffer.NewBufferFromFile(scanlist[y].abspath), true)
676+
micro.InfoBar():Message('Filemanager2 opened ', open_path)
677+
open_path = filepath.Clean(open_path)
678+
if config.GetGlobalOption('filemanager2.newtab') then
679+
smart_new_tab(open_path)
680+
else
681+
micro.CurPane():VSplitIndex(buffer.NewBufferFromFile(open_path), true)
682+
end
683+
565684
-- Resizes all views after opening a file
566685
-- tabs[curTab + 1]:Resize()
567686
end
@@ -631,23 +750,6 @@ local function uncompress_target(y)
631750
end
632751
end
633752

634-
-- Stat a path to check if it exists, returning true/false
635-
local function path_exists(path)
636-
local go_os = import('os')
637-
-- Stat the file/dir path we created
638-
-- file_stat should be non-nil, and stat_err should be nil on success
639-
local file_stat, stat_err = go_os.Stat(path)
640-
-- Check if what we tried to create exists
641-
if stat_err ~= nil then
642-
-- true/false if the file/dir exists
643-
return go_os.IsExist(stat_err)
644-
elseif file_stat ~= nil then
645-
-- Assume it exists if no errors
646-
return true
647-
end
648-
return false
649-
end
650-
651753
-- Prompts for a new name, then renames the file/dir at the cursor's position
652754
-- Not local so Micro can use it
653755
function rename_at_cursor(bp, args)
@@ -855,8 +957,44 @@ function new_dir(bp, args)
855957
create_filedir(dir_name, true)
856958
end
857959

960+
local function try_uncompress_path(path)
961+
local target_path = try_convert_rel(path)
962+
target_path = filepath.Clean(target_path)
963+
local current = current_dir
964+
local components = {}
965+
966+
-- Split the path into components
967+
while target_path ~= current and target_path ~= "/" and target_path ~= "." do
968+
table.insert(components, 1, get_basename(target_path))
969+
target_path = filepath.Dir(target_path)
970+
end
971+
972+
-- For each component, find and uncompress the corresponding directory
973+
local y = 0
974+
for i = 1, #components do
975+
-- Search for the component in current level
976+
for j = 1, #scanlist do
977+
if get_basename(scanlist[j].abspath) == components[i] then
978+
y = j
979+
-- If it's a directory and not the last component, uncompress it
980+
if i < #components and scanlist[j].dirmsg == Icons()['dir'] then
981+
uncompress_target(y)
982+
end
983+
break
984+
end
985+
end
986+
end
987+
988+
-- Move cursor to the final target
989+
if y > 0 then
990+
tree_view.Cursor.Loc.Y = y + 2 -- +2 to account for header lines
991+
select_line()
992+
end
993+
end
994+
858995
-- open_tree setup's the view
859996
local function open_tree()
997+
last_buf_pane = micro.CurPane()
860998
-- Open a new Vsplit (on the very left)
861999
micro.CurPane():VSplitIndex(buffer.NewBuffer('', 'filemanager2'), false)
8621000
-- Save the new view so we can access it later
@@ -884,6 +1022,19 @@ local function open_tree()
8841022

8851023
-- Fill the scanlist, and then print its contents to tree_view
8861024
update_current_dir(os.Getwd())
1025+
1026+
config.RegisterCommonOption('filemanager2', 'showcurrent', true)
1027+
-- Use relative path is possible
1028+
config.RegisterCommonOption('filemanager2', 'relativepath', true)
1029+
-- Open on new tab?
1030+
config.RegisterCommonOption('filemanager2', 'newtab', true)
1031+
1032+
if config.GetGlobalOption('filemanager2.showcurrent') then
1033+
-- If there's a valid buffer path, uncompress the tree to reach it
1034+
if path_exists(last_buf_pane.Buf.AbsPath) then
1035+
try_uncompress_path(last_buf_pane.Buf.AbsPath)
1036+
end
1037+
end
8871038
end
8881039

8891040
function onBufPaneOpen(bp)
@@ -902,7 +1053,7 @@ end
9021053
-- close_tree will close the tree plugin view and release memory.
9031054
local function close_tree()
9041055
if tree_view ~= nil then
905-
tree_view:Quit()
1056+
tree_view:Unsplit()
9061057
tree_view = nil
9071058
clear_messenger()
9081059
end
@@ -1403,6 +1554,12 @@ function init()
14031554
config.RegisterCommonOption('filemanager2', 'openonstart', false)
14041555
-- Use nerd fonts icons
14051556
config.RegisterCommonOption('filemanager2', 'nerdfonts', false)
1557+
-- Shows the current file directory
1558+
config.RegisterCommonOption('filemanager2', 'showcurrent', true)
1559+
-- Use relative path is possible
1560+
config.RegisterCommonOption('filemanager2', 'relativepath', true)
1561+
-- Open on new tab?
1562+
config.RegisterCommonOption('filemanager2', 'newtab', true)
14061563

14071564
-- Use file icon in status bar
14081565
micro.SetStatusInfoFn('filemanager2.FileIcon')

0 commit comments

Comments
 (0)