Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions filemanager-plugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a

## [Unreleased]

### Fixed

- Mouse clicks now let Micro position the cursor natively (via pre/post mouse-press handlers) instead of manually computing the click location, fixing incorrect click targeting with softwrap enabled
- Crashes from clicking on stale/out-of-range scanlist entries by adding nil checks around `scanlist[y]` and `tree_view`
- Tab navigation in the tree view being swallowed by the autocomplete popup; autocomplete is now disabled in the tree view
- Clicking the header or separator lines no longer errors or triggers unintended actions

### Changed

- Default tree pane width reduced from 30 to 25

## [3.4.0] - 2018-10-22

### Fixed
Expand Down
123 changes: 74 additions & 49 deletions filemanager-plugin/filemanager.lua
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,6 @@ local function select_line(last_y)
-- Makes sure the cursor is visible (if it isn't)
-- (false) means no callback
tree_view:Center()

-- Highlight the current line where the cursor is
tree_view.Cursor:SelectLine()
end

-- Simple true/false if scanlist is currently empty
Expand All @@ -259,10 +256,10 @@ end
local function refresh_view()
clear_messenger()

-- If it's less than 30, just use 30 for width. Don't want it too small
-- If it's less than 25, just use 25 for width. Don't want it too small

if tree_view:GetView().Width < 30 then
tree_view:ResizePane(30)
if tree_view:GetView().Width < 25 then
tree_view:ResizePane(25)
end

-- Delete everything in the view/buffer
Expand Down Expand Up @@ -427,9 +424,9 @@ local function compress_target(y, delete_y)
scanlist = second_table
end

if tree_view:GetView().Width > (30 + highest_visible_indent) then
if tree_view:GetView().Width > (25 + highest_visible_indent) then
-- Shave off some width
tree_view:ResizePane(30 + highest_visible_indent)
tree_view:ResizePane(25 + highest_visible_indent)
end

refresh_and_select()
Expand Down Expand Up @@ -471,8 +468,8 @@ end
local function update_current_dir(path)
-- Clear the highest since this is a full refresh
highest_visible_indent = 0
-- Set the width back to 30
tree_view:ResizePane(30)
-- Set the width back to 25
tree_view:ResizePane(25)
-- Update the current dir to the new path
current_dir = path

Expand Down Expand Up @@ -513,22 +510,28 @@ end
-- If it's actually a file, open it in a new vsplit
-- THIS EXPECTS ZERO-BASED Y
local function try_open_at_y(y)
-- 0 = header (current dir path), 1 = separator — silently ignore
if y == 0 or y == 1 then
return
-- 2 is the zero-based index of ".."
if y == 2 then
elseif y == 2 then
go_back_dir()
elseif y > 2 and not scanlist_is_empty() then
-- -2 to conform to our scanlist "missing" first 3 indicies
y = y - 2
if scanlist[y].dirmsg ~= "" then
-- if passed path is a directory, update the current dir to be one deeper..
update_current_dir(scanlist[y].abspath)
else
-- If it's a file, then open it
micro.InfoBar():Message("Filemanager opened ", scanlist[y].abspath)
-- Opens the absolute path in new vertical view
micro.CurPane():VSplitIndex(buffer.NewBufferFromFile(scanlist[y].abspath), true)
-- Resizes all views after opening a file
-- tabs[curTab + 1]:Resize()
-- Check if the entry exists before accessing it
if scanlist[y] ~= nil then
if scanlist[y].dirmsg ~= "" then
-- if passed path is a directory, update the current dir to be one deeper..
update_current_dir(scanlist[y].abspath)
else
-- If it's a file, then open it
micro.InfoBar():Message("Filemanager opened ", scanlist[y].abspath)
-- Opens the absolute path in new vertical view
micro.CurPane():VSplitIndex(buffer.NewBufferFromFile(scanlist[y].abspath), true)
-- Resizes all views after opening a file
-- tabs[curTab + 1]:Resize()
end
end
else
micro.InfoBar():Error("Can't open that")
Expand Down Expand Up @@ -823,31 +826,39 @@ end

-- open_tree setup's the view
local function open_tree()
-- Open a new Vsplit (on the very left)
-- Check if it already exists
if tree_view ~= nil then return end

-- Open a new Vsplit
micro.CurPane():VSplitIndex(buffer.NewBuffer("", "filemanager"), false)
-- Save the new view so we can access it later

-- Check if tree_view was properly initialized
tree_view = micro.CurPane()
if tree_view == nil then
micro.InfoBar():Error("Error: Could not initialize filemanager window.")
return
end

-- Set the width of tree_view to 30% & lock it
tree_view:ResizePane(30)
tree_view:ResizePane(25)
-- Set the type to unsavable
-- tree_view.Buf.Type = buffer.BTLog
tree_view.Buf.Type.Scratch = true
tree_view.Buf.Type.Readonly = true

-- tree_view.Buf.Type = buffer.BTLog
tree_view.Buf.Type.Scratch = true
tree_view.Buf.Type.Readonly = true
-- Set the various display settings, but only on our view (by using SetLocalOption instead of SetOption)
-- NOTE: Micro requires the true/false to be a string
-- Softwrap long strings (the file/dir paths)
tree_view.Buf:SetOptionNative("softwrap", true)
-- No line numbering
tree_view.Buf:SetOptionNative("ruler", false)
-- Is this needed with new non-savable settings from being "vtLog"?
tree_view.Buf:SetOptionNative("autosave", false)
-- Don't show the statusline to differentiate the view from normal views
tree_view.Buf:SetOptionNative("statusformatr", "")
tree_view.Buf:SetOptionNative("statusformatl", "filemanager")
tree_view.Buf:SetOptionNative("scrollbar", false)

tree_view.Buf:SetOptionNative("softwrap", true)
-- No line numbering
tree_view.Buf:SetOptionNative("ruler", false)
-- Disable autocomplete so Tab always goes through IndentSelection,
-- avoiding the autocomplete popup in the tree view.
tree_view.Buf:SetOptionNative("autocomplete", false)
-- Is this needed with new non-savable settings from being "vtLog"?
tree_view.Buf:SetOptionNative("autosave", false)
-- Don't show the statusline to differentiate the view from normal views
tree_view.Buf:SetOptionNative("statusformatr", "")
tree_view.Buf:SetOptionNative("statusformatl", "filemanager")
tree_view.Buf:SetOptionNative("scrollbar", false)
-- Fill the scanlist, and then print its contents to tree_view
update_current_dir(os.Getwd())
end
Expand Down Expand Up @@ -1084,17 +1095,23 @@ function onPreviousSplit(view)
selectline_if_tree(view)
end

-- On click, open at the click's y
-- On click, let micro move the cursor to the correct buffer position,
-- then open whatever is at that position.
-- We split across pre/post so micro handles all coordinate mapping for us,
-- correctly accounting for softwrap, tab bars, scroll, etc.
function preMousePress(view, event)
if view == tree_view then
local x, y = event:Position()
-- Fixes the y because softwrap messes with it
local new_x, new_y = tree_view:GetMouseClickLocation(x, y)
-- Try to open whatever is at the click's y index
-- Will go into/back dirs based on what's clicked, nothing gets expanded
try_open_at_y(new_y)
-- Don't actually allow the mousepress to trigger, so we avoid highlighting stuff
return false
-- Reset selection to prevent extending it on subsequent clicks
tree_view.Cursor:ResetSelection()
-- Return true to let micro handle the click naturally (moves cursor to correct position)
return true
end
end

function onMousePress(view, event)
if view == tree_view then
-- Cursor is now at the correct buffer position; open whatever is there
try_open_at_y(tree_view.Cursor.Loc.Y)
end
end

Expand Down Expand Up @@ -1133,7 +1150,7 @@ end
-- Ref https://github.com/zyedidia/micro/issues/992
local tab_pressed = false

-- Tab
-- Tab (when autocomplete is not active)
function preIndentSelection(view)
if view == tree_view then
tab_pressed = true
Expand All @@ -1145,6 +1162,14 @@ function preIndentSelection(view)
end
end

-- Tab (when autocomplete is active) — block the popup so Tab falls
-- through to IndentSelection which handles opening correctly.
function preAutocomplete(view)
if view == tree_view then
return false
end
end

-- Workaround for tab getting inserted into opened files
-- Ref https://github.com/zyedidia/micro/issues/992
function preInsertTab(view)
Expand Down