forked from onivim/oni2
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add [WIP] file explorer * Switch to scroll view * Add working toggleable tree nodes * Add general treeview component and initial fileexplorer * Remove unused open * Add generalised tree item * Initial rendering of FileExplorer with real fs list * Add icons and increase explorer size * Render folder icon if folder otherwise render file icon * Add reminder todo comment * Return and use icon definition not raw code * Filter out ignore files and add children per dir * Add descendants to fs tree * Handle node click in parent element * Fix duplicate entries in fs tree * Create helper functions to neaten tree generation * Initial Hack to get files opening on click * Slightly improve ref used in update function * Move state into isolinear thread * Rename oniTree to UiTree * Fix comment in explorer connector * Move explorer logic out of connector into FileExplorer * Remove lwt from store dune file * Include Revery tree in Oni UiTree * Fix comment typo * Remove unnecessary second open * Remove references to ReveryTree use UiTree instead * Remove unused icon * add binding for explorer * Add toggle open and closed functionality to explorer * Add explanatory comments and fix explorer close * Revert changes to UI/dune * remove unused variables * Remove more unused vars * Only open files not directories * Fix recursive subdir opening * Remove some more unused variables * Add ignored files to configuration * Fix unbound labels error * Replace FontAwesome back where it was initially * Add primary and secondary root icon props * Separate out nodeRenderer function * Toggle explorer on dock icon click * Add spacing to comment * Use sprintf for formatting error message * Add initial implementation of depth limit to tree * use more robost check for isDirectory * Save max depth in Constants and on each node * Add progressive fetching/updating of nodes For nodes beyond the max depth on click of their parents populate the subdirectories * Fix bad rebase changes * update comment for getFiles function * Reduce explorer depth * Remove unused children variable
- Loading branch information
Showing
22 changed files
with
670 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
open Revery; | ||
open Oni_Core; | ||
|
||
type t = { | ||
directory: UiTree.t, | ||
isOpen: bool, | ||
}; | ||
|
||
module ExplorerId = | ||
UniqueId.Make({}); | ||
|
||
let toFsNode = node => | ||
switch (node) { | ||
| UiTree.FileSystemNode(n) => n | ||
}; | ||
|
||
let getFileIcon = (languageInfo, iconTheme, filePath) => { | ||
let fileIcon = | ||
LanguageInfo.getLanguageFromFilePath(languageInfo, filePath) | ||
|> IconTheme.getIconForFile(iconTheme, filePath); | ||
|
||
switch (fileIcon) { | ||
| Some(_) as x => x | ||
| None => None | ||
}; | ||
}; | ||
|
||
let createFsNode = | ||
(~children, ~depth, ~path, ~displayName, ~fileIcon, ~isDirectory) => { | ||
/** | ||
TODO: Find an icon theme with folders and use those icons | ||
Fallbacks are used for the directory icons. FontAwesome is not | ||
accessible here so we specify no icons for directories. | ||
*/ | ||
let (primary, secondary) = isDirectory ? (None, None) : (fileIcon, None); | ||
|
||
UiTree.FileSystemNode({ | ||
path, | ||
depth, | ||
displayName, | ||
children, | ||
isDirectory, | ||
icon: primary, | ||
secondaryIcon: secondary, | ||
}); | ||
}; | ||
|
||
let isDir = path => Sys.file_exists(path) ? Sys.is_directory(path) : false; | ||
|
||
/** | ||
getFilesAndFolders | ||
This function uses Lwt to get all the files and folders in a directory | ||
then for each we check if it is a file or folder. | ||
if it is a directory we recursively call getFilesAndFolders on it | ||
to resolves its subfolders and files. We do this concurrently using | ||
Lwt_list.map_p. The recursion is gated by the depth value so it does | ||
not recurse too far. | ||
*/ | ||
let getFilesAndFolders = (~maxDepth, ~ignored, cwd, getIcon) => { | ||
let rec getDirContent = (~depth, cwd, getIcon) => { | ||
Lwt_unix.files_of_directory(cwd) | ||
/* Filter out the relative name for current and parent directory*/ | ||
|> Lwt_stream.filter(name => name != ".." && name != ".") | ||
/* Remove ignored files from search */ | ||
|> Lwt_stream.filter(name => !List.mem(name, ignored)) | ||
|> Lwt_stream.to_list | ||
|> ( | ||
promise => | ||
Lwt.bind(promise, files => | ||
Lwt_list.map_p( | ||
file => { | ||
let path = Filename.concat(cwd, file); | ||
let isDirectory = isDir(path); | ||
let nextDepth = depth + 1; | ||
let notMaximumDepth = nextDepth < maxDepth; | ||
|
||
let%lwt children = | ||
isDirectory && notMaximumDepth | ||
? getDirContent(~depth=nextDepth, path, getIcon) | ||
: Lwt.return([]); | ||
|
||
createFsNode( | ||
~path, | ||
~children, | ||
~isDirectory, | ||
~depth=nextDepth, | ||
~displayName=file, | ||
~fileIcon=getIcon(path), | ||
) | ||
|> Lwt.return; | ||
}, | ||
files, | ||
) | ||
) | ||
); | ||
}; | ||
|
||
try%lwt (getDirContent(~depth=0, cwd, getIcon)) { | ||
| Failure(e) => | ||
Log.error(e); | ||
Lwt.return([]); | ||
| Unix.Unix_error(error, fn, arg) => | ||
Printf.sprintf( | ||
"Error: %s encountered in %s called with %s", | ||
Unix.error_message(error), | ||
fn, | ||
arg, | ||
) | ||
|> Log.error; | ||
Lwt.return([]); | ||
}; | ||
}; | ||
|
||
let rec listToTree = (~status, nodes, parent) => { | ||
open UiTree; | ||
let parentId = ExplorerId.getUniqueId(); | ||
let children = | ||
List.map( | ||
node => { | ||
let fsNode = toFsNode(node); | ||
let descendantNodes = List.map(toFsNode, fsNode.children); | ||
let descendants = | ||
List.map( | ||
descendant => | ||
listToTree( | ||
~status=Closed, | ||
descendant.children, | ||
FileSystemNode(descendant), | ||
), | ||
descendantNodes, | ||
); | ||
|
||
let id = ExplorerId.getUniqueId(); | ||
Node({id, data: node, status: Closed}, descendants); | ||
}, | ||
nodes, | ||
); | ||
|
||
Node({id: parentId, data: parent, status}, children); | ||
}; | ||
|
||
let getDirectoryTree = (cwd, languageInfo, iconTheme, ignored) => { | ||
let getIcon = getFileIcon(languageInfo, iconTheme); | ||
let maxDepth = Constants.default.maximumExplorerDepth; | ||
let directory = | ||
getFilesAndFolders(~maxDepth, ~ignored, cwd, getIcon) |> Lwt_main.run; | ||
|
||
createFsNode( | ||
~depth=0, | ||
~path=cwd, | ||
~displayName=Filename.basename(cwd), | ||
~isDirectory=true, | ||
~children=directory, | ||
~fileIcon=getIcon(cwd), | ||
) | ||
|> listToTree(~status=Open, directory); | ||
}; | ||
|
||
let getNodePath = node => { | ||
UiTree.( | ||
switch (node) { | ||
| Node({data: FileSystemNode({path, _}), _}, _) => Some(path) | ||
| Empty => None | ||
} | ||
); | ||
}; | ||
|
||
let getNodeId = node => { | ||
UiTree.( | ||
switch (node) { | ||
| Node({id, _}, _) => Some(id) | ||
| Empty => None | ||
} | ||
); | ||
}; | ||
|
||
let create = () => {directory: UiTree.Empty, isOpen: true}; | ||
|
||
let reduce = (state: t, action: Actions.t) => { | ||
switch (action) { | ||
| SetExplorerTree(tree) => {directory: tree, isOpen: true} | ||
| RemoveDockItem(WindowManager.ExplorerDock) => {...state, isOpen: false} | ||
| _ => state | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.