qkzk / fm

dired/ranger like file manager
Other
16 stars 0 forks source link

FM: a file manager inspired by dired and ranger, written in rust

fm-tui on crates.io fm-tui on docs.rs

FM : a file manager inspired by ranger and dired

Config files   ~/.config/fm/
Documentation  https://github.com/qkzk/fm

Usage: fm [OPTIONS]

Options:
  -p, --path <PATH>      Starting path. directory or file [default: .]
  -s, --server <SERVER>  Nvim server [default: ]
  -A, --all              Display all files (hidden)
  -l, --log              Enable logging
      --neovim           Started inside neovim terminal emulator
      --keybinds         Print keybinds
      --cloudconfig      Configure a google drive client
  -h, --help             Print help
  -V, --version          Print version

Platform

Linux is the only supported platform. It may be usable on MacOS but I can't be sure.

Video

fm

Installation

cargo install fm-tui --locked

Usage

Start it from command line with no parameters :

fm

or with a path :

fm -p ~/Downloads

If you added the recommanded function to your bashrc/zshrc, simply use f and you will cd to the last visited directory when exiting.

Features

Some features depends on external programs to keep fm from being really bloated. I try to implement every feature I can think of.

Session

Display settings (use two panes, display metadata, use second pane as preview) are saved and restored when restarting the application.

Navigation

Moving

Many ways to jump somewhere :

File manipulation

Shell

Display

Fuzzy finders

We use a fork of skim, an fzf clone written in rust.

Neovim filepicker

When you open a file with i, it will send an event to Neovim and open it in a new buffer.

As long as Neovim is runnging, it should always work, even outside of neovim.

The RPC server address is found by looking for neovim in /proc. If it fails, we can still look for an environment variable set by neovim itself. Finally, it's also possible to pass the RPC server address with fm -s address.

cd on quit

When leaving fm, it prints the last visited path. If you add this function to your zshrc / bashrc, it will listen to stdout and cd to the last dir.

function f() {
  # start the fm filemanager, enabling cd on quit.
  dest=$(fm $@)
  if [[ ! -z $dest ]]
  then
   cd $dest
  fi
}

For fish users, this is the function to add to your config.fish

function f
  # start the fm filemanager, enabling cd on quit.
  set dest (fm $argv)
  if not test -z $dest
    cd $dest
  end
end

Archives

Custom binds

You can bind any unbound key to a shell command.

Expansions :

Logging

With -l or --log, logs are enabled. They are disabled by default.

Critical actions will be logged to ~/.config/fm/log/fm.log and actions affecting the file tree will be logged to ~/.config/fm/log/action_logger.log.

The last action is displayed at the bottom of the screen and can be read with Alt+l like a preview. Those logs can be seen even if logging is disabled, it just won't be up to date.

Google Drive

With the help of the amazing OpenDal library from Apache, you can access your remote GoogleDrive files within fm.

You must setup a client id and a client secret first. Once it's done, the helper fm --cloudconfig will create the configuration file for you. It uses a refresh token which will automatically be refreshed for you by OpenDal.

Open the Cloud menu with Shift-Alt-C and pick a valid config file. Once done, you can navigate your files with the arrow keys, download them with Return, upload the selected file with u, Delete a remote file with X (no confirmation !) and create a new directory with d.

You can setup many google drive accounts but only one can be opened at once. Use l to leave the current one and select another one.

This is an advanced user feature with rough edges.

Initial setup

You need to provide credentials to access a google drive account. The only way to get them is to create a project in Google Cloud and share the credentials.

  1. Open google cloud console and setup a new project for fm
  2. Add the google drive API for your project with the scopes https://www.googleapis.com/auth/drive and create credentials
  3. Add a tester with the same email account
  4. Add OAuth 2.0 credentials and copy the client id and client secret.
  5. Publish your application. It changes nothing but make the refresh tokens last longer.
  6. Run the helper fm --cloudconfig and provide the requested informations.

More infos about credentials can be found in the rclone documentation.

Multiple files having the same name

For some reason, GoogleDrive allows multiple files to have exactly the same name. ATM it crashes OpenDal in testing mode and those files are ignored in release mode. Only developpers of fm should be concerned.

Notes

More

Most of those features are inspired by ranger and alternatives (Midnight commander, nnn, lf etc.), the look and feel by dired.

Default keybindings

Press ctrl-h to display the help. Your current keybindings are shown. Here are the default ones.

Char('q') :      quit
Ctrl('h') :      help

- Navigation -
Left      :      cd to parent directory
Char('l') :      cd to child directory
Up        :      one line up
Char('j') :      one line down
Home      :      go to first line
Char('G') :      go to last line
PageUp    :      10 lines up
Char('J') :      10 lines down
Tab       :      cycle tab

- Actions -
Alt('d')  :      toggle dual pane - if the width is sufficiant
Alt('p')  :      toggle a preview on the second pane
Char('E') :      toggle metadata on files
Char('a') :      toggle hidden
Char('s') :      shell in current directory
Char('o') :      open the selected file with :
    - default       xdg-open
    - audio         mocp
    - images        viewnior
    - office        libreoffice
    - pdf, ebooks   zathura
    - text          nvim
    - video         mpv
    - vectorials
    - compressed files are decompressed
    - iso images are mounted
Char('i') :      open in current nvim session
Char('I') :      setup the nvim rpc address
Char('P') :      preview this file
Char('-') :      move back to previous dir
Char('~') :      move to $HOME
Char('`') :      move to root (/)
Char('@') :      move to starting point
Char('M') :      mark current path
Char('\''):      jump to a mark
Char('f') :      search next matching element
Ctrl('f') :      fuzzy finder for file
Ctrl('s') :      fuzzy finder for line
Char('H') :      fuzzy finder from help
Ctrl('r') :      refresh view
Ctrl('c') :      copy filename to clipboard
Ctrl('p') :      copy filepath to clipboard
Alt('c')  :      open the config file

- Action on flagged files -
Char(' ') :      toggle flag on a file
Char('*') :      flag all
Char('u') :      clear flags
Char('v') :      reverse flags
Char('L') :      symlink to current dir
Char('c') :      copy to current dir
Char('m') :      move to current dir
Char('x') :      delete files permanently
Char('X') :      move to trash
Char('C') :      compress into an archive

- Trash -
Alt('o')  :      Open the trash (enter to restore, del clear)
Alt('x')  :      Empty the trash

- Tree -
Navigate as usual. Most actions works as in 'normal' view.
Char('t') :      Toggle tree mode
Char('z') :      Fold a node
Ctrl('z') :      Fold every node
Char('Z') :      Unfold every node

    - DISPLAY MODES -
Different modes for the main window
Ctrl('q') :      NORMAL
Char('t')  :      TREE
Char('F') :      FLAGGED
Char('P') :      PREVIEW

    - EDIT MODES -
Different modes for the bottom window
Alt('m')  :      CHMOD
Char('e') :      OPEN WITH
Char('d') :      NEWDIR
Char('n') :      NEWFILE
Char('r') :      RENAME
Alt('g')  :      CD
Char('w') :      REGEXMATCH
Alt('j')  :      JUMP
Char('O') :      SORT
Alt('h')  :      HISTORY
Ctrl('g') :      SHORTCUT
Alt('e')  :      ENCRYPTED DRIVE
    (m: open & mount,  u: unmount & close, g: go there)
Alt('R')  :      REMOVABLE MTP DEVICES
    (m: mount,  u: unmount, g: go there)
Char('/') :      SEARCH
Char(':') :      ACTION
Alt('b')  :      BULK
Alt('s')  :      TUI APPS
Alt('i')  :      CLI APPS
Alt('r')  :      MOUNT REMOTE PATH
Alt('f')  :      FILTER
    (by name "n name", by ext "e ext", "d only directories" or "a all" for reset)
Enter     :      Execute mode then NORMAL

- CUSTOM ACTIONS -
%s: the selected file,
%f: the flagged files,
%e: the extension of the file,
%n: the filename only,
%p: the full path of the current directory.
%t: the currently set terminal & its flags.
Alt('u'):        /usr/bin/google-chrome-stable %s
Char('D'):        /usr/bin/dragon-drop %s

Configuration

Every configuration file is saved in ~/.config/fm/

You can configure :

External dependencies

Most of the openers and tui applications are configurable from config files. Some are hardcoded if their command is quite specific or if I couldn't find a workaround.

Contribution

Any help is appreciated.

I comment everything I do in dev.md.

It's my first "published" program, so don't get upset by the code quality.