fman's new file system API
After months of hard work, fman's file system API is finally available. It lets you add support for non-standard file systems such as Dropbox, SFTP, ... by means of plugins. This really sets fman apart from other file managers, where you are dependent on the respective vendor to offer new integrations.
A huge boon of the API is how little code it requires. fman's own implementation for handling local files is only 181 lines long. Basic SFTP support can be added in 75 lines. The new ProcessFS plugin is a file system for managing the programs currently running on your computer. It's a mere 84 lines of code.
Here's an example of a very simple custom file system:
from fman.fs import FileSystem class Example(FileSystem): scheme = 'example://' def iterdir(self, path): return ['File.txt', 'Image.jpg']
When you
create a plugin
with these contents and
navigate to example://
, you
get:
Note how the two "files" from the code snippet are shown. Of course, the files don't actually exist. But fman doesn't care: It simply displays what the code tells it to.
To make the example more interesting, let us introduce a directory structure:
class Example(FileSystem): scheme = 'example://' def iterdir(self, path): if path == '': return ['Directory', 'File.txt', 'Image.jpg'] elif path == 'Directory': return ['File in directory.txt'] def is_dir(self, path): return path == 'Directory'
When you reload your plugin with the built-in
Reload plugins
command, you then get the following:
We now have a directory that is also displayed as such. What's even better, you can open it to see:
Note how the location has changed to
example://Directory
and the file inside the
directory is displayed.
So what happened behind the scenes? When you open a URL
example://Directory
, fman sees that it should be handled by the
example://
file system. That's why we have
scheme = 'example://
in the code above.
Next, fman calls our implementation of
iterdir(path)
. The path it passes is everything
after the example://
prefix; So
'Directory'
in the example. Looking at the code, we see that it
returns ['File in directory.txt']
in this case.
Finally, fman invokes is_dir(path)
for each
file in the directory. In the example, fman passes
path = 'Directory/File in directory.txt'
.
Because this is not equal to 'Directory'
, our
code returns False
, and so fman treats it as a
file and not a folder.
This completes the simple example. File systems can obviously do much more:
You can for instance tell fman how your file system implements the
Copy
and Move
commands. For more information,
please refer to the
API documentation. If you
have any questions,
get in touch! I would love to help
you get started.
Footnote: Navigating to example://
You currently need a separate command to navigate to
example://
. This will do:
from fman import DirectoryPaneCommand class OpenExample(DirectoryPaneCommand): def __call__(self): self.pane.set_path('example://')
Copy this code into your plugin, then use the
Command Palette to run
Reload plugins
and then Open example
.