diff --git a/micro/backups/%home%amir%ssh.log b/micro/backups/%home%amir%ssh.log
new file mode 100644
index 0000000..da079f0
--- /dev/null
+++ b/micro/backups/%home%amir%ssh.log
@@ -0,0 +1,71 @@
+Last login: Mon Nov  4 11:39:32 2024
+[1m[7m%[27m[1m[0m                                                                                                                                                 
 

[0m[27m[24m[JDYNA-NB-ABAM% [K[?2004hpping 8.8.8     ls    p  lls[?2004l
+InsCMDs  homenet-ping-report.log  paclog.txt  ping-google.log  ssh.log	text.txt
+[1m[7m%[27m[1m[0m                                                                                                                                                 
 

[0m[27m[24m[JDYNA-NB-ABAM% [K[?2004hcc cd ..[?2004l
+[1m[7m%[27m[1m[0m                                                                                                                                                 
 

[0m[27m[24m[JDYNA-NB-ABAM% [K[?2004hcc ..[?2004l
+zsh: command not found: c
+[1m[7m%[27m[1m[0m                                                                                                                                                 
 

[0m[27m[24m[JDYNA-NB-ABAM% [K[?2004hlls[?2004l
+amir
+[1m[7m%[27m[1m[0m                                                                                                                                                 
 

[0m[27m[24m[JDYNA-NB-ABAM% [K[?2004hccd ..[?2004l
+[1m[7m%[27m[1m[0m                                                                                                                                                 
 

[0m[27m[24m[JDYNA-NB-ABAM% [K[?2004hlls[?2004l
+bashlog.txt  boot  etc	 init  lib64	   maintainance.log  opt	 proc  run   srv  tmp  var
+bin	     dev   home  lib   lost+found  mnt		     paclog.txt  root  sbin  sys  usr  wlog.txt
+[1m[7m%[27m[1m[0m                                                                                                                                                 
 

[0m[27m[24m[JDYNA-NB-ABAM% [K[?2004hc ccat m wlog.txt[1m [0m[0m [?2004l
+balbjasdkljalöbjöa
+----------------------
+Mon Nov  4 14:51:07 CET 2024
+USERCALL: installing: ssh
+----------------------
+Mon Nov  4 14:51:42 CET 2024
+USERCALL: installing: openssh
+resolving dependencies...
+looking for conflicting packages...
+
+Package (1)   New Version  Net Change  Download Size
+
+core/openssh  9.9p1-2        5.70 MiB       1.16 MiB
+
+Total Download Size:   1.16 MiB
+Total Installed Size:  5.70 MiB
+
+:: Retrieving packages...
+ openssh-9.9p1-2-x86_64 downloading...
+checking keyring...
+checking package integrity...
+loading package files...
+checking for file conflicts...
+:: Processing package changes...
+installing openssh...
+Optional dependencies for openssh
+    libfido2: FIDO/U2F support
+    sh: for ssh-copy-id and findssl.sh [installed]
+    x11-ssh-askpass: input passphrase in X
+    xorg-xauth: X11 forwarding
+:: Running post-transaction hooks...
+(1/4) Reloading system manager configuration...
+(2/4) Reloading user manager configuration...
+(3/4) Creating temporary files...
+(4/4) Arming ConditionNeedsUpdate...
+[1m[7m%[27m[1m[0m                                                                                                                                                 
 

[0m[27m[24m[JDYNA-NB-ABAM% [K[?2004hl[?2004l
+zsh: command not found: l
+[1m[7m%[27m[1m[0m                                                                                                                                                 
 

[0m[27m[24m[JDYNA-NB-ABAM% [K[?2004hlll[?2004l
+zsh: command not found: ll
+[1m[7m%[27m[1m[0m                                                                                                                                                 
 

[0m[27m[24m[JDYNA-NB-ABAM% [K[?2004hlls[?2004l
+bashlog.txt  boot  etc	 init  lib64	   maintainance.log  opt	 proc  run   srv  tmp  var
+bin	     dev   home  lib   lost+found  mnt		     paclog.txt  root  sbin  sys  usr  wlog.txt
+[1m[7m%[27m[1m[0m                                                                                                                                                 
 

[0m[27m[24m[JDYNA-NB-ABAM% [K[?2004hlls[?2004l
+bashlog.txt  boot  etc	 init  lib64	   maintainance.log  opt	 proc  run   srv  tmp  var
+bin	     dev   home  lib   lost+found  mnt		     paclog.txt  root  sbin  sys  usr  wlog.txt
+[1m[7m%[27m[1m[0m                                                                                                                                                 
 

[0m[27m[24m[JDYNA-NB-ABAM% [K[?2004hlls -a[?2004l
+.   .dockerenv	 bin   dev  home  lib	 lost+found	   mnt	paclog.txt  root  sbin	sys  usr  wlog.txt
+..  bashlog.txt  boot  etc  init  lib64  maintainance.log  opt	proc	    run   srv	tmp  var
+[1m[7m%[27m[1m[0m                                                                                                                                                 
 

[0m[27m[24m[JDYNA-NB-ABAM% [K[?2004heexit[?2004l
+Last login: Mon Nov  4 14:52:23 2024 from 127.0.0.1
+[1m[7m%[27m[1m[0m                                                                                                                                                 
 

[0m[27m[24m[JDYNA-NB-ABAM% [K[?2004hllsblk[1m [0m[0m [?2004l
+NAME MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
+sda    8:0    0 388.4M  1 disk 
+sdb    8:16   0     2G  0 disk [SWAP]
+sdc    8:32   0     1T  0 disk 
+sdd    8:48   0     1T  0 disk /mnt/wslg/distro
+                               /
+[1m[7m%[27m[1m[0m                                                                                                                                                 
 

[0m[27m[24m[JDYNA-NB-ABAM% [K[?2004hccat  c  eexit[?2004l
diff --git a/micro/bindings.json b/micro/bindings.json
new file mode 100644
index 0000000..0fd0c08
--- /dev/null
+++ b/micro/bindings.json
@@ -0,0 +1,5 @@
+{
+    "Alt-/": "lua:comment.comment",
+    "CtrlUnderscore": "lua:comment.comment",
+    "Ctrl-Space": "command:tree"
+}
diff --git a/micro/buffers/history b/micro/buffers/history
new file mode 100644
index 0000000..2d679c1
Binary files /dev/null and b/micro/buffers/history differ
diff --git a/micro/plug/filemanager/.editorconfig b/micro/plug/filemanager/.editorconfig
new file mode 100644
index 0000000..a34d753
--- /dev/null
+++ b/micro/plug/filemanager/.editorconfig
@@ -0,0 +1,17 @@
+# EditorConfig is awesome: http://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+charset = utf-8
+end_of_line = lf
+indent_style = tab
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+# Ignore .md files, because 2 spaces at end-of-line has meaning
+[*.md]
+trim_trailing_whitespace = false
diff --git a/micro/plug/filemanager/CHANGELOG.md b/micro/plug/filemanager/CHANGELOG.md
new file mode 100644
index 0000000..46d51c4
--- /dev/null
+++ b/micro/plug/filemanager/CHANGELOG.md
@@ -0,0 +1,109 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
+
+## [Unreleased]
+
+## [3.4.0] - 2018-10-22
+
+### Fixed
+
+- Issues with Lua's `io.popen` on some systems by using Micro's built-in `RunShellCommand` instead, [thanks to @scottbilas](https://github.com/NicolaiSoeborg/filemanager-plugin/pull/38)
+
+### Added
+
+- Adds the option `filemanager-openonstart` to allow auto-opening the file tree when Micro is started (default OFF)
+
+### Changed
+
+- Update README's option's documentation
+
+## [3.3.1] - 2018-10-03
+
+### Changed
+
+- Performance improvement by removing unnecessary refresh of the opened file, [thanks to @jackwilsdon](https://github.com/NicolaiSoeborg/filemanager-plugin/pull/37)
+
+## [3.3.0] - 2018-09-13
+
+### Added
+
+- The ability to sort folders above files, [thanks to @cbrown1](https://github.com/NicolaiSoeborg/filemanager-plugin/pull/33)
+
+### Fixed
+
+- The displayed filenames are now correctly only showing their "basename" on Windows
+
+## [3.2.0] - 2018-02-15
+
+### Added
+
+- The ability to go to parent directory with left arrow (when not minimizing). Thanks @avently
+- The ability to jump to the `..` as a "parent directory". Thanks @avently
+
+## [3.1.2] - 2018-02-07
+
+### Fixed
+
+- The minimum Micro version, which was incorrectly set to v1.4.0. Ref [issue #28](https://github.com/NicolaiSoeborg/filemanager-plugin/issues/28)
+
+## [3.1.1] - 2018-02-04
+
+### Fixed
+
+Ref https://github.com/zyedidia/micro/issues/992 for both of these fixes.
+
+- The syntax parser not loading correctly (mostly block comments) on opened files. **Requires Micro >= v1.4.0**
+- An errant tab being inserted into the newly opened file.
+
+## [3.1.0] - 2018-01-30
+
+### Added
+
+- The ability to hide dotfiles using the `filemanager-showdotfiles` option.
+- The ability to hide files ignored in your VCS (aka `.gitignore`'d) using the `filemanager-showignored` option. Only works with Git at the moment.
+- This `CHANGELOG.md`
+
+### Fixed
+
+- A bug with the `rm` command that caused weird, undefined behaviour to contents within the same dir as the file/dir deleted.
+- Issue [#24](https://github.com/NicolaiSoeborg/filemanager-plugin/issues/24)
+
+## [3.0.0] - 2018-01-10
+
+### Fixed
+
+- Issues [#13](https://github.com/NicolaiSoeborg/filemanager-plugin/issues/13), [#14](https://github.com/NicolaiSoeborg/filemanager-plugin/issues/14), [#15](https://github.com/NicolaiSoeborg/filemanager-plugin/issues/15), [#19](https://github.com/NicolaiSoeborg/filemanager-plugin/issues/19), [#20](https://github.com/NicolaiSoeborg/filemanager-plugin/issues/20)
+- The broken syntax highlighting
+
+### Added
+
+- Directory expansion/compression below itself for viewing more akin to a file tree.
+- The `rm` command, which deletes the file/directory under the cursor.
+- The `touch` command, which creates a file with the passed filename.
+- The `mkdir` command, which creates a directory with the passed filename.
+- An API, of sorts, for the user to rebind their keys to if they dislike the defaults.
+- An [editorconfig](http://editorconfig.org/) file.
+
+### Changed
+
+- The view that it spawns in to read-only, which requires Micro version >= 1.3.5
+- The functionality of some keybindings (when in the view) so they work safetly, or at all, with the plugin.
+- From the `enter` key to `tab` for opening/going into files/dirs (a side-effect of using the read-only setting)
+
+### Removed
+
+- The ability to use a lot of keybindings that would otherwise mess with the view, and have no benifit.
+- The pointless `.gitignore` file.
+
+[unreleased]: https://github.com/NicolaiSoeborg/filemanager-plugin/compare/v3.4.0...HEAD
+[3.4.0]: https://github.com/NicolaiSoeborg/filemanager-plugin/compare/v3.3.1...v3.4.0
+[3.3.1]: https://github.com/NicolaiSoeborg/filemanager-plugin/compare/v3.3.0...v3.3.1
+[3.3.0]: https://github.com/NicolaiSoeborg/filemanager-plugin/compare/v3.2.0...v3.3.0
+[3.2.0]: https://github.com/NicolaiSoeborg/filemanager-plugin/compare/v3.1.2...v3.2.0
+[3.1.2]: https://github.com/NicolaiSoeborg/filemanager-plugin/compare/v3.1.1...v3.1.2
+[3.1.1]: https://github.com/NicolaiSoeborg/filemanager-plugin/compare/v3.1.0...v3.1.1
+[3.1.0]: https://github.com/NicolaiSoeborg/filemanager-plugin/compare/v3.0.0...v3.1.0
+[3.0.0]: https://github.com/NicolaiSoeborg/filemanager-plugin/compare/v2.1.1...v3.0.0
diff --git a/micro/plug/filemanager/LICENSE b/micro/plug/filemanager/LICENSE
new file mode 100644
index 0000000..ae6fb2f
--- /dev/null
+++ b/micro/plug/filemanager/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 Nicolai Søborg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/micro/plug/filemanager/README.md b/micro/plug/filemanager/README.md
new file mode 100644
index 0000000..79d983d
--- /dev/null
+++ b/micro/plug/filemanager/README.md
@@ -0,0 +1,56 @@
+# Filemanager Plugin
+
+A simple plugin that allows for easy navigation of a file tree.
+
+![Example picture](./example.jpg?raw=true "Example")
+
+**Installation:** run `plugin install filemanager` and restart Micro.
+
+## Basics
+
+The top line always has the current directory's path to show you where you are.\
+The `..` near the top is used to move back a directory, from your current position.
+
+All directories have a `/` added to the end of it, and are syntax-highlighted as a `special` character.\
+If the directory is expanded, there will be a `+` to the left of it. If it is collapsed there will be a `-` instead.
+
+**NOTE:** If you change files without using the plugin, it can't know what you did. The only fix is to close and open the tree.
+
+### Options
+
+| Option                       | Purpose                                                      | Default |
+| :--------------------------- | :----------------------------------------------------------- | :------ |
+| `filemanager-showdotfiles`   | Show dotfiles (hidden if false)                              | `true`  |
+| `filemanager-showignored`    | Show gitignore'd files (hidden if false)                     | `true`  |
+| `filemanager-compressparent` | Collapse the parent dir when left is pressed on a child file | `true`  |
+| `filemanager-foldersfirst`   | Sorts folders above any files                                | `true`  |
+| `filemanager-openonstart`    | Automatically open the file tree when starting Micro         | `false` |
+
+### Commands and Keybindings
+
+The keybindings below are the equivalent to Micro's defaults, and not actually set by the plugin. If you've changed any of those keybindings, then that key is used instead.
+
+If you want to [keybind](https://github.com/zyedidia/micro/blob/master/runtime/help/keybindings.md#rebinding-keys) any of the operations/commands, bind to the labeled API in the table below.
+
+| Command  | Keybinding(s)              | What it does                                                                                | API for `bindings.json`               |
+| :------- | :------------------------- | :------------------------------------------------------------------------------------------ | :------------------------------------ |
+| `tree`   | -                          | Open/close the tree                                                                         | `filemanager.toggle_tree`             |
+| -        | <kbd>Tab</kbd> & MouseLeft | Open a file, or go into the directory. Goes back a dir if on `..`                           | `filemanager.try_open_at_cursor`      |
+| -        | <kbd>→</kbd>               | Expand directory in tree listing                                                            | `filemanager.uncompress_at_cursor`    |
+| -        | <kbd>←</kbd>               | Collapse directory listing                                                                  | `filemanager.compress_at_cursor`      |
+| -        | <kbd>Shift ⬆</kbd>         | Go to the target's parent directory                                                         | `filemanager.goto_parent_dir`         |
+| -        | <kbd>Alt Shift {</kbd>     | Jump to the previous directory in the view                                                  | `filemanager.goto_next_dir`           |
+| -        | <kbd>Alt Shift }</kbd>     | Jump to the next directory in the view                                                      | `filemanager.goto_prev_dir`           |
+| `rm`     | -                          | Prompt to delete the target file/directory your cursor is on                                | `filemanager.prompt_delete_at_cursor` |
+| `rename` | -                          | Rename the file/directory your cursor is on, using the passed name                          | `filemanager.rename_at_cursor`        |
+| `touch`  | -                          | Make a new file under/into the file/directory your cursor is on, using the passed name      | `filemanager.new_file`                |
+| `mkdir`  | -                          | Make a new directory under/into the file/directory your cursor is on, using the passed name | `filemanager.new_dir`                 |
+
+#### Notes
+
+- `rename`, `touch`, and `mkdir` require a name to be passed when calling.\
+  Example: `rename newnamehere`, `touch filenamehere`, `mkdir dirnamehere`.\
+  If the passed name already exists in the current dir, it will cancel instead of overwriting (for safety).
+
+- The <kbd>Ctrl w</kbd> keybinding is to switch which buffer your cursor is on.\
+  This isn't specific to the plugin, it's just part of Micro, but many people seem to not know this.
diff --git a/micro/plug/filemanager/example.jpg b/micro/plug/filemanager/example.jpg
new file mode 100644
index 0000000..ab5bf1c
Binary files /dev/null and b/micro/plug/filemanager/example.jpg differ
diff --git a/micro/plug/filemanager/filemanager.lua b/micro/plug/filemanager/filemanager.lua
new file mode 100644
index 0000000..fef17d4
--- /dev/null
+++ b/micro/plug/filemanager/filemanager.lua
@@ -0,0 +1,1387 @@
+VERSION = "3.5.1"
+
+local micro = import("micro")
+local config = import("micro/config")
+local shell = import("micro/shell")
+local buffer = import("micro/buffer")
+local os = import("os")
+local filepath = import("path/filepath")
+
+-- Clear out all stuff in Micro's messenger
+local function clear_messenger()
+	-- messenger:Reset()
+	-- messenger:Clear()
+end
+
+-- Holds the micro.CurPane() we're manipulating
+local tree_view = nil
+-- Keeps track of the current working directory
+local current_dir = os.Getwd()
+-- Keep track of current highest visible indent to resize width appropriately
+local highest_visible_indent = 0
+-- Holds a table of paths -- objects from new_listobj() calls
+local scanlist = {}
+
+-- Get a new object used when adding to scanlist
+local function new_listobj(p, d, o, i)
+	return {
+		["abspath"] = p,
+		["dirmsg"] = d,
+		["owner"] = o,
+		["indent"] = i,
+		-- Since decreasing/increasing is common, we include these with the object
+		["decrease_owner"] = function(self, minus_num)
+			self.owner = self.owner - minus_num
+		end,
+		["increase_owner"] = function(self, plus_num)
+			self.owner = self.owner + plus_num
+		end
+	}
+end
+
+-- Repeats a string x times, then returns it concatenated into one string
+local function repeat_str(str, len)
+	-- Do NOT try to concat in a loop, it freezes micro...
+	-- instead, use a temporary table to hold values
+	local string_table = {}
+	for i = 1, len do
+		string_table[i] = str
+	end
+	-- Return the single string of repeated characters
+	return table.concat(string_table)
+end
+
+-- A check for if a path is a dir
+local function is_dir(path)
+	-- Used for checking if dir
+	local golib_os = import("os")
+	-- Returns a FileInfo on the current file/path
+	local file_info, stat_error = golib_os.Stat(path)
+	-- Wrap in nil check for file/dirs without read permissions
+	if file_info ~= nil then
+		-- Returns true/false if it's a dir
+		return file_info:IsDir()
+	else
+		-- Couldn't stat the file/dir, usually because no read permissions
+		micro.InfoBar():Error("Error checking if is dir: ", stat_error)
+		-- Nil since we can't read the path
+		return nil
+	end
+end
+
+-- Returns a list of files (in the target dir) that are ignored by the VCS system (if exists)
+-- aka this returns a list of gitignored files (but for whatever VCS is found)
+local function get_ignored_files(tar_dir)
+	-- True/false if the target dir returns a non-fatal error when checked with 'git status'
+	local function has_git()
+		local git_rp_results = shell.ExecCommand('git  -C "' .. tar_dir .. '" rev-parse --is-inside-work-tree')
+		return git_rp_results:match("^true%s*$")
+	end
+	local readout_results = {}
+	-- TODO: Support more than just Git, such as Mercurial or SVN
+	if has_git() then
+		-- If the dir is a git dir, get all ignored in the dir
+		local git_ls_results =
+			shell.ExecCommand('git -C "' .. tar_dir .. '" ls-files . --ignored --exclude-standard --others --directory')
+		-- Cut off the newline that is at the end of each result
+		for split_results in string.gmatch(git_ls_results, "([^\r\n]+)") do
+			-- git ls-files adds a trailing slash if it's a dir, so we remove it (if it is one)
+			readout_results[#readout_results + 1] =
+				(string.sub(split_results, -1) == "/" and string.sub(split_results, 1, -2) or split_results)
+		end
+	end
+
+	-- Make sure we return a table
+	return readout_results
+end
+
+-- Returns the basename of a path (aka a name without leading path)
+local function get_basename(path)
+	if path == nil then
+		micro.Log("Bad path passed to get_basename")
+		return nil
+	else
+		-- Get Go's path lib for a basename callback
+		local golib_path = import("filepath")
+		return golib_path.Base(path)
+	end
+end
+
+-- Returns true/false if the file is a dotfile
+local function is_dotfile(file_name)
+	-- Check if the filename starts with a dot
+	if string.sub(file_name, 1, 1) == "." then
+		return true
+	else
+		return false
+	end
+end
+
+-- Structures the output of the scanned directory content to be used in the scanlist table
+-- This is useful for both initial creation of the tree, and when nesting with uncompress_target()
+local function get_scanlist(dir, ownership, indent_n)
+	local golib_ioutil = import("ioutil")
+	-- Gets a list of all the files in the current dir
+	local dir_scan, scan_error = golib_ioutil.ReadDir(dir)
+
+	-- dir_scan will be nil if the directory is read-protected (no permissions)
+	if dir_scan == nil then
+		micro.InfoBar():Error("Error scanning dir: ", scan_error)
+		return nil
+	end
+
+	-- The list of files to be returned (and eventually put in the view)
+	local results = {}
+	local files = {}
+
+	local function get_results_object(file_name)
+		local abs_path = filepath.Join(dir, file_name)
+		-- Use "+" for dir's, "" for files
+		local dirmsg = (is_dir(abs_path) and "+" or "")
+		return new_listobj(abs_path, dirmsg, ownership, indent_n)
+	end
+
+	-- Save so we don't have to rerun GetOption a bunch
+	local show_dotfiles = config.GetGlobalOption("filemanager.showdotfiles")
+	local show_ignored = config.GetGlobalOption("filemanager.showignored")
+	local folders_first = config.GetGlobalOption("filemanager.foldersfirst")
+
+	-- The list of VCS-ignored files (if any)
+	-- Only bother getting ignored files if we're not showing ignored
+	local ignored_files = (not show_ignored and get_ignored_files(dir) or {})
+	-- True/false if the file is an ignored file
+	local function is_ignored_file(filename)
+		for i = 1, #ignored_files do
+			if ignored_files[i] == filename then
+				return true
+			end
+		end
+		return false
+	end
+
+	-- Hold the current scan's filename in most of the loops below
+	local filename
+
+	for i = 1, #dir_scan do
+		local showfile = true
+		filename = dir_scan[i]:Name()
+		-- If we should not show dotfiles, and this is a dotfile, don't show
+		if not show_dotfiles and is_dotfile(filename) then
+			showfile = false
+		end
+		-- If we should not show ignored files, and this is an ignored file, don't show
+		if not show_ignored and is_ignored_file(filename) then
+			showfile = false
+		end
+		if showfile then
+			-- This file is good to show, proceed
+			if folders_first and not is_dir(filepath.Join(dir, filename)) then
+				-- If folders_first and this is a file, add it to (temporary) files
+				files[#files + 1] = get_results_object(filename)
+			else
+				-- Otherwise, add to results
+				results[#results + 1] = get_results_object(filename)
+			end
+		end
+	end
+	if #files > 0 then
+		-- Append any files to results, now that all folders have been added
+		-- files will be > 0 only if folders_first and there are files
+		for i = 1, #files do
+			results[#results + 1] = files[i]
+		end
+	end
+
+	-- Return the list of scanned files
+	return results
+end
+
+-- A short "get y" for when acting on the scanlist
+-- Needed since we don't store the first 3 visible indicies in scanlist
+local function get_safe_y(optional_y)
+	-- Default to 0 so we can check against and see if it's bad
+	local y = 0
+	-- Make the passed y optional
+	if optional_y == nil then
+		-- Default to cursor's Y loc if nothing was passed, instead of declaring another y
+		optional_y = tree_view.Cursor.Loc.Y
+	end
+	-- 0/1/2 would be the top "dir, separator, .." so check if it's past
+	if optional_y > 2 then
+		-- -2 to conform to our scanlist, since zero-based Go index & Lua's one-based
+		y = tree_view.Cursor.Loc.Y - 2
+	end
+	return y
+end
+
+-- Joins the target dir's leading path to the passed name
+local function dirname_and_join(path, join_name)
+	-- The leading path to the dir we're in
+	local leading_path = filepath.Dir(path)
+	-- Joins with OS-specific slashes
+	return filepath.Join(leading_path, join_name)
+end
+
+-- Hightlights the line when you move the cursor up/down
+local function select_line(last_y)
+	-- Make last_y optional
+	if last_y ~= nil then
+		-- Don't let them move past ".." by checking the result first
+		if last_y > 1 then
+			-- If the last position was valid, move back to it
+			tree_view.Cursor.Loc.Y = last_y
+		end
+	elseif tree_view.Cursor.Loc.Y < 2 then
+		-- Put the cursor on the ".." if it's above it
+		tree_view.Cursor.Loc.Y = 2
+	end
+
+	-- Puts the cursor back in bounds (if it isn't) for safety
+	tree_view.Cursor:Relocate()
+
+	-- 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
+local function scanlist_is_empty()
+	if next(scanlist) == nil then
+		return true
+	else
+		return false
+	end
+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 tree_view:GetView().Width < 30 then
+		tree_view:ResizePane(30)
+	end
+
+	-- Delete everything in the view/buffer
+	tree_view.Buf.EventHandler:Remove(tree_view.Buf:Start(), tree_view.Buf:End())
+
+	-- Insert the top 3 things that are always there
+	-- Current dir
+	tree_view.Buf.EventHandler:Insert(buffer.Loc(0, 0), current_dir .. "\n")
+	-- An ASCII separator
+	tree_view.Buf.EventHandler:Insert(buffer.Loc(0, 1), repeat_str("─", tree_view:GetView().Width) .. "\n")
+	-- The ".." and use a newline if there are things in the current dir
+	tree_view.Buf.EventHandler:Insert(buffer.Loc(0, 2), (#scanlist > 0 and "..\n" or ".."))
+
+	-- Holds the current basename of the path (purely for display)
+	local display_content
+
+	-- NOTE: might want to not do all these concats in the loop, it can get slow
+	for i = 1, #scanlist do
+		-- The first 3 indicies are the dir/separator/"..", so skip them
+		if scanlist[i].dirmsg ~= "" then
+			-- Add the + or - to the left to signify if it's compressed or not
+			-- Add a forward slash to the right to signify it's a dir
+			display_content = scanlist[i].dirmsg .. " " .. get_basename(scanlist[i].abspath) .. "/"
+		else
+			-- Use the basename from the full path for display
+			-- Two spaces to align with any directories, instead of being "off"
+			display_content = "  " .. get_basename(scanlist[i].abspath)
+		end
+
+		if scanlist[i].owner > 0 then
+			-- Add a space and repeat it * the indent number
+			display_content = repeat_str(" ", 2 * scanlist[i].indent) .. display_content
+		end
+
+		-- Newlines are needed for all inserts except the last
+		-- If you insert a newline on the last, it leaves a blank spot at the bottom
+		if i < #scanlist then
+			display_content = display_content .. "\n"
+		end
+
+		-- Insert line-by-line to avoid out-of-bounds on big folders
+		-- +2 so we skip the 0/1/2 positions that hold the top dir/separator/..
+		tree_view.Buf.EventHandler:Insert(buffer.Loc(0, i + 2), display_content)
+	end
+
+	-- Resizes all views after messing with ours
+    tree_view:Tab():Resize()
+end
+
+-- Moves the cursor to the ".." in tree_view
+local function move_cursor_top()
+	-- 2 is the position of the ".."
+	tree_view.Cursor.Loc.Y = 2
+
+	-- select the line after moving
+	select_line()
+end
+
+local function refresh_and_select()
+	-- Save the cursor position before messing with the view..
+	-- because changing contents in the view causes the Y loc to move
+	local last_y = tree_view.Cursor.Loc.Y
+	-- Actually refresh
+	refresh_view()
+	-- Moves the cursor back to it's original position
+	select_line(last_y)
+end
+
+-- Find everything nested under the target, and remove it from the scanlist
+local function compress_target(y, delete_y)
+	-- Can't compress the top stuff, or if there's nothing there, so exit early
+	if y == 0 or scanlist_is_empty() then
+		return
+	end
+	-- Check if the target is a dir, since files don't have anything to compress
+	-- Also make sure it's actually an uncompressed dir by checking the gutter message
+	if scanlist[y].dirmsg == "-" then
+		local target_index, delete_index
+		-- Add the original target y to stuff to delete
+		local delete_under = {[1] = y}
+		local new_table = {}
+		local del_count = 0
+		-- Loop through the whole table, looking for nested content, or stuff with ownership == y...
+		-- and delete matches. y+1 because we want to start under y, without actually touching y itself.
+		for i = 1, #scanlist do
+			delete_index = false
+			-- Don't run on y, since we don't always delete y
+			if i ~= y then
+				-- On each loop, check if the ownership matches
+				for x = 1, #delete_under do
+					-- Check for something belonging to a thing to delete
+					if scanlist[i].owner == delete_under[x] then
+						-- Delete the target if it has an ownership to our delete target
+						delete_index = true
+						-- Keep count of total deleted (can't use #delete_under because it's for deleted dir count)
+						del_count = del_count + 1
+						-- Check if an uncompressed dir
+						if scanlist[i].dirmsg == "-" then
+							-- Add the index to stuff to delete, since it holds nested content
+							delete_under[#delete_under + 1] = i
+						end
+						-- See if we're on the "deepest" nested content
+						if scanlist[i].indent == highest_visible_indent and scanlist[i].indent > 0 then
+							-- Save the lower indent, since we're minimizing/deleting nested dirs
+							highest_visible_indent = highest_visible_indent - 1
+						end
+						-- Nothing else to do, so break this inner loop
+						break
+					end
+				end
+			end
+			if not delete_index then
+				-- Save the index in our new table
+				new_table[#new_table + 1] = scanlist[i]
+			end
+		end
+
+		scanlist = new_table
+
+		if del_count > 0 then
+			-- Ownership adjusting since we're deleting an index
+			for i = y + 1, #scanlist do
+				-- Don't touch root file/dirs
+				if scanlist[i].owner > y then
+					-- Minus ownership, on everything below i, the number deleted
+					scanlist[i]:decrease_owner(del_count)
+				end
+			end
+		end
+
+		-- If not deleting, then update the gutter message to be + to signify compressed
+		if not delete_y then
+			-- Update the dir message
+			scanlist[y].dirmsg = "+"
+		end
+	elseif config.GetGlobalOption("filemanager.compressparent") and not delete_y then
+		goto_parent_dir()
+		-- Prevent a pointless refresh of the view
+		return
+	end
+
+	-- Put outside check above because we call this to delete targets as well
+	if delete_y then
+		local second_table = {}
+		-- Quickly remove y
+		for i = 1, #scanlist do
+			if i == y then
+				-- Reduce everything's ownership by 1 after y
+				for x = i + 1, #scanlist do
+					-- Don't touch root file/dirs
+					if scanlist[x].owner > y then
+						-- Minus 1 since we're just deleting y
+						scanlist[x]:decrease_owner(1)
+					end
+				end
+			else
+				-- Put everything but y into the temporary table
+				second_table[#second_table + 1] = scanlist[i]
+			end
+		end
+		-- Put everything (but y) back into scanlist, with adjusted ownership values
+		scanlist = second_table
+	end
+
+	if tree_view:GetView().Width > (30 + highest_visible_indent) then
+		-- Shave off some width
+        tree_view:ResizePane(30 + highest_visible_indent)
+	end
+
+	refresh_and_select()
+end
+
+-- Prompts the user for deletion of a file/dir when triggered
+-- Not local so Micro can access it
+function prompt_delete_at_cursor()
+	local y = get_safe_y()
+	-- Don't let them delete the top 3 index dir/separator/..
+	if y == 0 or scanlist_is_empty() then
+		micro.InfoBar():Error("You can't delete that")
+		-- Exit early if there's nothing to delete
+		return
+	end
+
+    micro.InfoBar():YNPrompt("Do you want to delete the " .. (scanlist[y].dirmsg ~= "" and "dir" or "file") .. ' "' .. scanlist[y].abspath .. '"? ', function(yes, canceled)
+        if yes and not canceled then
+            -- Use Go's os.Remove to delete the file
+            local go_os = import("os")
+            -- Delete the target (if its a dir then the children too)
+            local remove_log = go_os.RemoveAll(scanlist[y].abspath)
+            if remove_log == nil then
+                micro.InfoBar():Message("Filemanager deleted: ", scanlist[y].abspath)
+                -- Remove the target (and all nested) from scanlist[y + 1]
+                -- true to delete y
+                compress_target(get_safe_y(), true)
+            else
+                micro.InfoBar():Error("Failed deleting file/dir: ", remove_log)
+            end
+        else
+            micro.InfoBar():Message("Nothing was deleted")
+        end
+    end)
+end
+
+-- Changes the current dir in the top of the tree..
+-- then scans that dir, and prints it to the view
+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)
+	-- Update the current dir to the new path
+	current_dir = path
+
+	-- Get the current working dir's files into our list of files
+	-- 0 ownership because this is a scan of the base dir
+	-- 0 indent because this is the base dir
+	local scan_results = get_scanlist(path, 0, 0)
+	-- Safety check with not-nil
+	if scan_results ~= nil then
+		-- Put in the new scan stuff
+		scanlist = scan_results
+	else
+		-- If nil, just empty it
+		scanlist = {}
+	end
+
+	refresh_view()
+	-- Since we're going into a new dir, move cursor to the ".." by default
+	move_cursor_top()
+end
+
+-- (Tries to) go back one "step" from the current directory
+local function go_back_dir()
+	-- Use Micro's dirname to get everything but the current dir's path
+	local one_back_dir = filepath.Dir(current_dir)
+	-- Try opening, assuming they aren't at "root", by checking if it matches last dir
+	if one_back_dir ~= current_dir then
+		-- If filepath.Dir returns different, then they can move back..
+		-- so we update the current dir and refresh
+		update_current_dir(one_back_dir)
+	end
+end
+
+-- Tries to open the current index
+-- If it's the top dir indicator, or separator, nothing happens
+-- If it's ".." then it tries to go back a dir
+-- If it's a dir then it moves into the dir and refreshes
+-- If it's actually a file, open it in a new vsplit
+-- THIS EXPECTS ZERO-BASED Y
+local function try_open_at_y(y)
+	-- 2 is the zero-based index of ".."
+	if 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()
+		end
+	else
+		micro.InfoBar():Error("Can't open that")
+	end
+end
+
+-- Opens the dir's contents nested under itself
+local function uncompress_target(y)
+	-- Exit early if on the top 3 non-list items
+	if y == 0 or scanlist_is_empty() then
+		return
+	end
+	-- Only uncompress if it's a dir and it's not already uncompressed
+	if scanlist[y].dirmsg == "+" then
+		-- Get a new scanlist with results from the scan in the target dir
+		local scan_results = get_scanlist(scanlist[y].abspath, y, scanlist[y].indent + 1)
+		-- Don't run any of this if there's nothing in the dir we scanned, pointless
+		if scan_results ~= nil then
+			-- Will hold all the old values + new scan results
+			local new_table = {}
+			-- By not inserting in-place, some unexpected results can be avoided
+			-- Also, table.insert actually moves values up (???) instead of down
+			for i = 1, #scanlist do
+				-- Put the current val into our new table
+				new_table[#new_table + 1] = scanlist[i]
+				if i == y then
+					-- Fill in the scan results under y
+					for x = 1, #scan_results do
+						new_table[#new_table + 1] = scan_results[x]
+					end
+					-- Basically "moving down" everything below y, so ownership needs to increase on everything
+					for inner_i = y + 1, #scanlist do
+						-- When root not pushed by inserting, don't change its ownership
+						-- This also has a dual-purpose to make it not effect root file/dirs
+						-- since y is always >= 3
+						if scanlist[inner_i].owner > y then
+							-- Increase each indicies ownership by the number of scan results inserted
+							scanlist[inner_i]:increase_owner(#scan_results)
+						end
+					end
+				end
+			end
+
+			-- Update our scanlist with the new values
+			scanlist = new_table
+		end
+
+		-- Change to minus to signify it's uncompressed
+		scanlist[y].dirmsg = "-"
+
+		-- Check if we actually need to resize, or if we're nesting at the same indent
+		-- Also check if there's anything in the dir, as we don't need to expand on an empty dir
+		if scan_results ~= nil then
+			if scanlist[y].indent > highest_visible_indent and #scan_results >= 1 then
+				-- Save the new highest indent
+				highest_visible_indent = scanlist[y].indent
+				-- Increase the width to fit the new nested content
+				tree_view:ResizePane(tree_view:GetView().Width + scanlist[y].indent)
+			end
+		end
+
+		refresh_and_select()
+	end
+end
+
+-- Stat a path to check if it exists, returning true/false
+local function path_exists(path)
+	local go_os = import("os")
+	-- Stat the file/dir path we created
+	-- file_stat should be non-nil, and stat_err should be nil on success
+	local file_stat, stat_err = go_os.Stat(path)
+	-- Check if what we tried to create exists
+	if stat_err ~= nil then
+		-- true/false if the file/dir exists
+		return go_os.IsExist(stat_err)
+	elseif file_stat ~= nil then
+		-- Assume it exists if no errors
+		return true
+	end
+	return false
+end
+
+-- Prompts for a new name, then renames the file/dir at the cursor's position
+-- Not local so Micro can use it
+function rename_at_cursor(bp, args)
+
+	if micro.CurPane() ~= tree_view then
+		micro.InfoBar():Message("Rename only works with the cursor in the tree!")
+		return
+	end
+
+	-- Safety check they actually passed a name
+	if #args < 1 then
+		micro.InfoBar():Error('When using "rename" you need to input a new name')
+		return
+	end
+
+	local new_name = args[1]
+
+	-- +1 since Go uses zero-based indices
+	local y = get_safe_y()
+	-- Check if they're trying to rename the top stuff
+	if y == 0 then
+		-- Error since they tried to rename the top stuff
+		micro.InfoBar():Message("You can't rename that!")
+		return
+	end
+
+	-- The old file/dir's path
+	local old_path = scanlist[y].abspath
+	-- Join the path into their supplied rename, so that we have an absolute path
+	local new_path = dirname_and_join(old_path, new_name)
+	-- Use Go's os package for renaming the file/dir
+	local golib_os = import("os")
+	-- Actually rename the file
+	local log_out = golib_os.Rename(old_path, new_path)
+	-- Output the log, if any, of the rename
+	if log_out ~= nil then
+		micro.Log("Rename log: ", log_out)
+	end
+
+	-- Check if the rename worked
+	if not path_exists(new_path) then
+		micro.InfoBar():Error("Path doesn't exist after rename!")
+		return
+	end
+
+	-- NOTE: doesn't alphabetically sort after refresh, but it probably should
+	-- Replace the old path with the new path
+	scanlist[y].abspath = new_path
+	-- Refresh the tree with our new name
+	refresh_and_select()
+end
+
+-- Prompts the user for the file/dir name, then creates the file/dir using Go's os package
+local function create_filedir(filedir_name, make_dir)
+	if micro.CurPane() ~= tree_view then
+		micro.InfoBar():Message("You can't create a file/dir if your cursor isn't in the tree!")
+		return
+	end
+
+	-- Safety check they passed a name
+	if filedir_name == nil then
+		micro.InfoBar():Error('You need to input a name when using "touch" or "mkdir"!')
+		return
+	end
+
+	-- The target they're trying to create on top of/in/at/whatever
+	local y = get_safe_y()
+	-- Holds the path passed to Go for the eventual new file/dir
+	local filedir_path
+	-- A true/false if scanlist is empty
+	local scanlist_empty = scanlist_is_empty()
+
+	-- Check there's actually anything in the list, and that they're not on the ".."
+	if not scanlist_empty and y ~= 0 then
+		-- If they're inserting on a folder, don't strip its path
+		if scanlist[y].dirmsg ~= "" then
+			-- Join our new file/dir onto the dir
+			filedir_path = filepath.Join(scanlist[y].abspath, filedir_name)
+		else
+			-- The current index is a file, so strip its name and join ours onto it
+			filedir_path = dirname_and_join(scanlist[y].abspath, filedir_name)
+		end
+	else
+		-- if nothing in the list, or cursor is on top of "..", use the current dir
+		filedir_path = filepath.Join(current_dir, filedir_name)
+	end
+
+	-- Check if the name is already taken by a file/dir
+	if path_exists(filedir_path) then
+		micro.InfoBar():Error("You can't create a file/dir with a pre-existing name")
+		return
+	end
+
+	-- Use Go's os package for creating the files
+	local golib_os = import("os")
+	-- Create the dir or file
+	if make_dir then
+		-- Creates the dir
+		golib_os.Mkdir(filedir_path, golib_os.ModePerm)
+		micro.Log("Filemanager created directory: " .. filedir_path)
+	else
+		-- Creates the file
+		golib_os.Create(filedir_path)
+		micro.Log("Filemanager created file: " .. filedir_path)
+	end
+
+	-- If the file we tried to make doesn't exist, fail
+	if not path_exists(filedir_path) then
+		micro.InfoBar():Error("The file/dir creation failed")
+
+		return
+	end
+
+	-- Creates a sort of default object, to be modified below
+	-- If creating a dir, use a "+"
+	local new_filedir = new_listobj(filedir_path, (make_dir and "+" or ""), 0, 0)
+
+	-- Refresh with our new value(s)
+	local last_y
+
+	-- Only insert to scanlist if not created into a compressed dir, since it'd be hidden if it was
+	-- Wrap the below checks so a y=0 doesn't break something
+	if not scanlist_empty and y ~= 0 then
+		-- +1 so it's highlighting the new file/dir
+		last_y = tree_view.Cursor.Loc.Y + 1
+
+		-- Only actually add the object to the list if it's not created on an uncompressed folder
+		if scanlist[y].dirmsg == "+" then
+			-- Exit early, since it was created into an uncompressed folder
+
+			return
+		elseif scanlist[y].dirmsg == "-" then
+			-- Check if created on top of an uncompressed folder
+			-- Change ownership to the folder it was created on top of..
+			-- otherwise, the ownership would be incorrect
+			new_filedir.owner = y
+			-- We insert under the folder, so increment the indent
+			new_filedir.indent = scanlist[y].indent + 1
+		else
+			-- This triggers if the cursor is on top of a file...
+			-- so we copy the properties of it
+			new_filedir.owner = scanlist[y].owner
+			new_filedir.indent = scanlist[y].indent
+		end
+
+		-- A temporary table for adding our new object, and manipulation
+		local new_table = {}
+		-- Insert the new file/dir, and update ownership of everything below it
+		for i = 1, #scanlist do
+			-- Don't use i as index, as it will be off by one on the next pass after below "i == y"
+			new_table[#new_table + 1] = scanlist[i]
+			if i == y then
+				-- Insert our new file/dir (below the last item)
+				new_table[#new_table + 1] = new_filedir
+				-- Increase ownership of everything below it, since we're inserting
+				-- Basically "moving down" everything below y, so ownership needs to increase on everything
+				for inner_i = y + 1, #scanlist do
+					-- When root not pushed by inserting, don't change its ownership
+					-- This also has a dual-purpose to make it not effect root file/dirs
+					-- since y is always >= 3
+					if scanlist[inner_i].owner > y then
+						-- Increase each indicies ownership by 1 since we're only inserting 1 file/dir
+						scanlist[inner_i]:increase_owner(1)
+					end
+				end
+			end
+		end
+		-- Update the scanlist with the new object & updated ownerships
+		scanlist = new_table
+	else
+		-- The scanlist is empty (or cursor is on ".."), so we add on our new file/dir at the bottom
+		scanlist[#scanlist + 1] = new_filedir
+		-- Add current position so it takes into account where we are
+		last_y = #scanlist + tree_view.Cursor.Loc.Y
+	end
+
+	refresh_view()
+	select_line(last_y)
+end
+
+-- Triggered with "touch filename"
+function new_file(bp, args)
+
+	-- Safety check they actually passed a name
+	if #args < 1 then
+		micro.InfoBar():Error('When using "touch" you need to input a file name')
+		return
+	end
+
+	local file_name = args[1]
+
+	-- False because not a dir
+	create_filedir(file_name, false)
+end
+
+-- Triggered with "mkdir dirname"
+function new_dir(bp, args)
+
+	-- Safety check they actually passed a name
+	if #args < 1 then
+		micro.InfoBar():Error('When using "mkdir" you need to input a dir name')
+		return
+	end
+
+	local dir_name = args[1]
+
+	-- True because dir
+	create_filedir(dir_name, true)
+end
+
+-- open_tree setup's the view
+local function open_tree()
+	-- Open a new Vsplit (on the very left)
+	micro.CurPane():VSplitIndex(buffer.NewBuffer("", "filemanager"), false)
+	-- Save the new view so we can access it later
+	tree_view = micro.CurPane()
+
+	-- Set the width of tree_view to 30% & lock it
+    tree_view:ResizePane(30)
+	-- Set the type to unsavable
+    -- 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)
+
+	-- Fill the scanlist, and then print its contents to tree_view
+	update_current_dir(os.Getwd())
+end
+
+-- close_tree will close the tree plugin view and release memory.
+local function close_tree()
+	if tree_view ~= nil then
+		tree_view:Quit()
+		tree_view = nil
+		clear_messenger()
+	end
+end
+
+-- toggle_tree will toggle the tree view visible (create) and hide (delete).
+function toggle_tree()
+	if tree_view == nil then
+		open_tree()
+	else
+		close_tree()
+	end
+end
+
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-- Functions exposed specifically for the user to bind
+-- Some are used in callbacks as well
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+function uncompress_at_cursor()
+	if micro.CurPane() == tree_view then
+		uncompress_target(get_safe_y())
+	end
+end
+
+function compress_at_cursor()
+	if micro.CurPane() == tree_view then
+		-- False to not delete y
+		compress_target(get_safe_y(), false)
+	end
+end
+
+-- Goes up 1 visible directory (if any)
+-- Not local so it can be bound
+function goto_prev_dir()
+	if micro.CurPane() ~= tree_view or scanlist_is_empty() then
+		return
+	end
+
+	local cur_y = get_safe_y()
+	-- If they try to run it on the ".." do nothing
+	if cur_y ~= 0 then
+		local move_count = 0
+		for i = cur_y - 1, 1, -1 do
+			move_count = move_count + 1
+			-- If a dir, stop counting
+			if scanlist[i].dirmsg ~= "" then
+				-- Jump to its parent (the ownership)
+				tree_view.Cursor:UpN(move_count)
+				select_line()
+				break
+			end
+		end
+	end
+end
+
+-- Goes down 1 visible directory (if any)
+-- Not local so it can be bound
+function goto_next_dir()
+	if micro.CurPane() ~= tree_view or scanlist_is_empty() then
+		return
+	end
+
+	local cur_y = get_safe_y()
+	local move_count = 0
+	-- If they try to goto_next on "..", pretends the cursor is valid
+	if cur_y == 0 then
+		cur_y = 1
+		move_count = 1
+	end
+	-- Only do anything if it's even possible for there to be another dir
+	if cur_y < #scanlist then
+		for i = cur_y + 1, #scanlist do
+			move_count = move_count + 1
+			-- If a dir, stop counting
+			if scanlist[i].dirmsg ~= "" then
+				-- Jump to its parent (the ownership)
+				tree_view.Cursor:DownN(move_count)
+				select_line()
+				break
+			end
+		end
+	end
+end
+
+-- Goes to the parent directory (if any)
+-- Not local so it can be keybound
+function goto_parent_dir()
+	if micro.CurPane() ~= tree_view or scanlist_is_empty() then
+		return
+	end
+
+	local cur_y = get_safe_y()
+	-- Check if the cursor is even in a valid location for jumping to the owner
+	if cur_y > 0 then
+		-- Jump to its parent (the ownership)
+		tree_view.Cursor:UpN(cur_y - scanlist[cur_y].owner)
+		select_line()
+	end
+end
+
+function try_open_at_cursor()
+	if micro.CurPane() ~= tree_view or scanlist_is_empty() then
+		return
+	end
+
+	try_open_at_y(tree_view.Cursor.Loc.Y)
+end
+
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-- Shorthand functions for actions to reduce repeat code
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+-- Used to fail certain actions that we shouldn't allow on the tree_view
+local function false_if_tree(view)
+	if view == tree_view then
+		return false
+	end
+end
+
+-- Select the line at the cursor
+local function selectline_if_tree(view)
+	if view == tree_view then
+		select_line()
+	end
+end
+
+-- Move the cursor to the top, but don't allow the action
+local function aftermove_if_tree(view)
+	if view == tree_view then
+		if tree_view.Cursor.Loc.Y < 2 then
+			-- If it went past the "..", move back onto it
+			tree_view.Cursor:DownN(2 - tree_view.Cursor.Loc.Y)
+		end
+		select_line()
+	end
+end
+
+local function clearselection_if_tree(view)
+	if view == tree_view then
+		-- Clear the selection when doing a find, so it doesn't copy the current line
+		tree_view.Cursor:ResetSelection()
+	end
+end
+
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-- All the events for certain Micro keys go below here
+-- Other than things we flat-out fail
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+-- Close current
+function preQuit(view)
+	if view == tree_view then
+		-- A fake quit function
+		close_tree()
+		-- Don't actually "quit", otherwise it closes everything without saving for some reason
+		return false
+	end
+end
+
+-- Close all
+function preQuitAll(view)
+	close_tree()
+end
+
+-- FIXME: Workaround for the weird 2-index movement on cursordown
+function preCursorDown(view)
+	if view == tree_view then
+		tree_view.Cursor:Down()
+		select_line()
+		-- Don't actually go down, as it moves 2 indicies for some reason
+		return false
+	end
+end
+
+-- Up
+function onCursorUp(view)
+	selectline_if_tree(view)
+end
+
+-- Alt-Shift-{
+-- Go to target's parent directory (if exists)
+function preParagraphPrevious(view)
+	if view == tree_view then
+		goto_prev_dir()
+		-- Don't actually do the action
+		return false
+	end
+end
+
+-- Alt-Shift-}
+-- Go to next dir (if exists)
+function preParagraphNext(view)
+	if view == tree_view then
+		goto_next_dir()
+		-- Don't actually do the action
+		return false
+	end
+end
+
+-- PageUp
+function onCursorPageUp(view)
+	aftermove_if_tree(view)
+end
+
+-- Ctrl-Up
+function onCursorStart(view)
+	aftermove_if_tree(view)
+end
+
+-- PageDown
+function onCursorPageDown(view)
+	selectline_if_tree(view)
+end
+
+-- Ctrl-Down
+function onCursorEnd(view)
+	selectline_if_tree(view)
+end
+
+function onNextSplit(view)
+	selectline_if_tree(view)
+end
+
+function onPreviousSplit(view)
+	selectline_if_tree(view)
+end
+
+-- On click, open at the click's y
+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
+	end
+end
+
+-- Up
+function preCursorUp(view)
+	if view == tree_view then
+		-- Disallow selecting past the ".." in the tree
+		if tree_view.Cursor.Loc.Y == 2 then
+			return false
+		end
+	end
+end
+
+-- Left
+function preCursorLeft(view)
+	if view == tree_view then
+		-- +1 because of Go's zero-based index
+		-- False to not delete y
+		compress_target(get_safe_y(), false)
+		-- Don't actually move the cursor, as it messes with selection
+		return false
+	end
+end
+
+-- Right
+function preCursorRight(view)
+	if view == tree_view then
+		-- +1 because of Go's zero-based index
+		uncompress_target(get_safe_y())
+		-- Don't actually move the cursor, as it messes with selection
+		return false
+	end
+end
+
+-- Workaround for tab getting inserted into opened files
+-- Ref https://github.com/zyedidia/micro/issues/992
+local tab_pressed = false
+
+-- Tab
+function preIndentSelection(view)
+	if view == tree_view then
+		tab_pressed = true
+		-- Open the file
+		-- Using tab instead of enter, since enter won't work with Readonly
+		try_open_at_y(tree_view.Cursor.Loc.Y)
+		-- Don't actually insert a tab
+		return false
+	end
+end
+
+-- Workaround for tab getting inserted into opened files
+-- Ref https://github.com/zyedidia/micro/issues/992
+function preInsertTab(view)
+	if tab_pressed then
+		tab_pressed = false
+		return false
+	end
+end
+function preInsertNewline(view)
+    if view == tree_view then
+        return false
+    end
+    return true
+end
+-- CtrlL
+function onJumpLine(view)
+	-- Highlight the line after jumping to it
+	-- Also moves you to index 3 (2 in zero-base) if you went to the first 2 lines
+	aftermove_if_tree(view)
+end
+
+-- ShiftUp
+function preSelectUp(view)
+	if view == tree_view then
+		-- Go to the file/dir's parent dir (if any)
+		goto_parent_dir()
+		-- Don't actually selectup
+		return false
+	end
+end
+
+-- CtrlF
+function preFind(view)
+	-- Since something is always selected, clear before a find
+	-- Prevents copying the selection into the find input
+	clearselection_if_tree(view)
+end
+
+-- FIXME: doesn't work for whatever reason
+function onFind(view)
+	-- Select the whole line after a find, instead of just the input txt
+	selectline_if_tree(view)
+end
+
+-- CtrlN after CtrlF
+function onFindNext(view)
+	selectline_if_tree(view)
+end
+
+-- CtrlP after CtrlF
+function onFindPrevious(view)
+	selectline_if_tree(view)
+end
+
+-- NOTE: This is a workaround for "cd" not having its own callback
+local precmd_dir
+
+function preCommandMode(view)
+	precmd_dir = os.Getwd()
+end
+
+-- Update the current dir when using "cd"
+function onCommandMode(view)
+	local new_dir = os.Getwd()
+	-- Only do anything if the tree is open, and they didn't cd to nothing
+	if tree_view ~= nil and new_dir ~= precmd_dir and new_dir ~= current_dir then
+		update_current_dir(new_dir)
+	end
+end
+
+------------------------------------------------------------------
+-- Fail a bunch of useless actions
+-- Some of these need to be removed (read-only makes some useless)
+------------------------------------------------------------------
+
+function preStartOfLine(view)
+	return false_if_tree(view)
+end
+
+function preStartOfText(view)
+    return false_if_tree(view)
+end
+
+function preEndOfLine(view)
+	return false_if_tree(view)
+end
+
+function preMoveLinesDown(view)
+	return false_if_tree(view)
+end
+
+function preMoveLinesUp(view)
+	return false_if_tree(view)
+end
+
+function preWordRight(view)
+	return false_if_tree(view)
+end
+
+function preWordLeft(view)
+	return false_if_tree(view)
+end
+
+function preSelectDown(view)
+	return false_if_tree(view)
+end
+
+function preSelectLeft(view)
+	return false_if_tree(view)
+end
+
+function preSelectRight(view)
+	return false_if_tree(view)
+end
+
+function preSelectWordRight(view)
+	return false_if_tree(view)
+end
+
+function preSelectWordLeft(view)
+	return false_if_tree(view)
+end
+
+function preSelectToStartOfLine(view)
+	return false_if_tree(view)
+end
+
+function preSelectToStartOfText(view)
+    return false_if_tree(view)
+end
+
+function preSelectToEndOfLine(view)
+	return false_if_tree(view)
+end
+
+function preSelectToStart(view)
+	return false_if_tree(view)
+end
+
+function preSelectToEnd(view)
+	return false_if_tree(view)
+end
+
+function preDeleteWordLeft(view)
+	return false_if_tree(view)
+end
+
+function preDeleteWordRight(view)
+	return false_if_tree(view)
+end
+
+function preOutdentSelection(view)
+	return false_if_tree(view)
+end
+
+function preOutdentLine(view)
+	return false_if_tree(view)
+end
+
+function preSave(view)
+	return false_if_tree(view)
+end
+
+function preCut(view)
+	return false_if_tree(view)
+end
+
+function preCutLine(view)
+	return false_if_tree(view)
+end
+
+function preDuplicateLine(view)
+	return false_if_tree(view)
+end
+
+function prePaste(view)
+	return false_if_tree(view)
+end
+
+function prePastePrimary(view)
+	return false_if_tree(view)
+end
+
+function preMouseMultiCursor(view)
+	return false_if_tree(view)
+end
+
+function preSpawnMultiCursor(view)
+	return false_if_tree(view)
+end
+
+function preSelectAll(view)
+	return false_if_tree(view)
+end
+
+function init()
+    -- Let the user disable showing of dotfiles like ".editorconfig" or ".DS_STORE"
+    config.RegisterCommonOption("filemanager", "showdotfiles", true)
+    -- Let the user disable showing files ignored by the VCS (i.e. gitignored)
+    config.RegisterCommonOption("filemanager", "showignored", true)
+    -- Let the user disable going to parent directory via left arrow key when file selected (not directory)
+    config.RegisterCommonOption("filemanager", "compressparent", true)
+    -- Let the user choose to list sub-folders first when listing the contents of a folder
+    config.RegisterCommonOption("filemanager", "foldersfirst", true)
+    -- Lets the user have the filetree auto-open any time Micro is opened
+    -- false by default, as it's a rather noticable user-facing change
+    config.RegisterCommonOption("filemanager", "openonstart", false)
+
+    -- Open/close the tree view
+    config.MakeCommand("tree", toggle_tree, config.NoComplete)
+    -- Rename the file/dir under the cursor
+    config.MakeCommand("rename", rename_at_cursor, config.NoComplete)
+    -- Create a new file
+    config.MakeCommand("touch", new_file, config.NoComplete)
+    -- Create a new dir
+    config.MakeCommand("mkdir", new_dir, config.NoComplete)
+    -- Delete a file/dir, and anything contained in it if it's a dir
+    config.MakeCommand("rm", prompt_delete_at_cursor, config.NoComplete)
+    -- Adds colors to the ".." and any dir's in the tree view via syntax highlighting
+    -- TODO: Change it to work with git, based on untracked/changed/added/whatever
+    config.AddRuntimeFile("filemanager", config.RTSyntax, "syntax.yaml")
+
+    -- NOTE: This must be below the syntax load command or coloring won't work
+    -- Just auto-open if the option is enabled
+    -- This will run when the plugin first loads
+    if config.GetGlobalOption("filemanager.openonstart") then
+        -- Check for safety on the off-chance someone's init.lua breaks this
+        if tree_view == nil then
+            open_tree()
+            -- Puts the cursor back in the empty view that initially spawns
+            -- This is so the cursor isn't sitting in the tree view at startup
+            micro.CurPane():NextSplit()
+        else
+            -- Log error so they can fix it
+            micro.Log(
+                "Warning: filemanager.openonstart was enabled, but somehow the tree was already open so the option was ignored."
+            )
+        end
+    end
+end
diff --git a/micro/plug/filemanager/repo.json b/micro/plug/filemanager/repo.json
new file mode 100644
index 0000000..4bd7de2
--- /dev/null
+++ b/micro/plug/filemanager/repo.json
@@ -0,0 +1,45 @@
+[
+	{
+		"Name": "filemanager",
+		"Description": "File manager for Micro",
+		"Tags": ["filetree", "filemanager", "file", "manager"],
+        "Website": "",
+		"Versions": [
+			{
+				"Version": "2.1.1",
+				"Url": "https://github.com/NicolaiSoeborg/filemanager-plugin/archive/v2.1.1.zip",
+				"Require": {
+					"micro": ">=1.3.2"
+				}
+			},
+			{
+				"Version": "3.1.0",
+				"Url": "https://github.com/NicolaiSoeborg/filemanager-plugin/archive/v3.1.0.zip",
+				"Require": {
+					"micro": ">=1.3.5"
+				}
+			},
+			{
+				"Version": "3.4.0",
+				"Url": "https://github.com/NicolaiSoeborg/filemanager-plugin/archive/v3.4.0.zip",
+				"Require": {
+					"micro": ">=1.4.1"
+				}
+			},
+			{
+					"Version": "3.5.0",
+					"Url": "https://github.com/micro-editor/updated-plugins/releases/download/v1.0.0/filemanager-3.5.0.zip",
+					"Require": {
+							"micro": ">=2.0.0-1"
+					}
+			},
+			{
+					"Version": "3.5.1",
+					"Url": "https://github.com/micro-editor/updated-plugins/releases/download/v1.0.0/filemanager-3.5.1.zip",
+					"Require": {
+							"micro": ">=2.0.0-1"
+					}
+			}
+		]
+	}
+]
diff --git a/micro/plug/filemanager/syntax.yaml b/micro/plug/filemanager/syntax.yaml
new file mode 100644
index 0000000..da001cf
--- /dev/null
+++ b/micro/plug/filemanager/syntax.yaml
@@ -0,0 +1,9 @@
+filetype: filemanager
+
+detect:
+    filename: "^filemanager$"
+
+rules:
+    # The "..", the separator line thing, and directories
+    # Optionally, add this below to highlight the ascii line: "^─*$"
+    - special: "^\\.\\.$|\\-\\s.*|\\+\\s.*"
