This commit is contained in:
2026-03-27 07:06:16 +01:00
commit 1541961403
340 changed files with 151916 additions and 0 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,330 @@
# Custom Keybinds
File-browser also supports custom keybinds. These keybinds send normal input commands, but the script will substitute characters in the command strings for specific values depending on the currently open directory, and currently selected item.
This allows for a wide range of customised behaviour, such as loading additional audio tracks from the browser, or copying the path of the selected item to the clipboard.
The feature is disabled by default, but is enabled with the `custom_keybinds` script-opt.
Keybinds are declared in the `~~/script-opts/file-browser-keybinds.json` file, the config takes the form of an array of json objects, with the following keys:
| option | required | default | description |
|---------------|----------|------------|--------------------------------------------------------------------------------------------|
| key | yes | - | the key to bind the command to - same syntax as input.conf |
| command | yes | - | json array of commands and arguments |
| name | no | numeric id | name of the script-binding - see [modifying default keybinds](#modifying-default-keybinds) |
| condition | no | - | a Lua [expression](#expressions) - the keybind will only run if this evaluates to true |
| flags | no | - | flags to send to the mpv add_keybind function - see [here](https://mpv.io/manual/master/#lua-scripting-[,flags]]\)) |
| filter | no | - | run the command on just a file (`file`) or folder (`dir`) |
| parser | no | - | run the command only in directories provided by the specified parser. |
| multiselect | no | `false` | command is run on all selected items |
| multi-type | no | `repeat` | which multiselect mode to use - `repeat` or `concat` |
| delay | no | `0` | time to wait between sending repeated multi commands |
| concat-string | no | `' '` (space) | string to insert between items when concatenating multi commands |
| passthrough | no | - | force or ban passthrough behaviour - see [passthrough](#passthrough-keybinds) |
| api_version | no | - | tie the keybind to a particular [addon API version](./addons.md#api-version), printing warnings and throwing errors if the keybind is used with wrong versions |
Example:
```json
{
"key": "KP1",
"command": ["print-text", "example"],
}
```
The command can also be an array of arrays, in order to send multiple commands at once:
```json
{
"key": "KP2",
"command": [
["print-text", "example2"],
["show-text", "example2"]
]
}
```
Filter should not be included unless one wants to limit what types of list entries the command should be run on.
To only run the command for directories use `dir`, to only run the command for files use `file`.
The parser filter is for filtering keybinds to only work inside directories loaded by specific parsers.
There are two parsers in the base script, the default parser for native filesystems is called `file`, while the root parser is called `root`.
Other parsers can be supplied by addons, and use the addon's filename with `-browser.lua` or just `.lua` stripped unless otherwise stated.
For example `ftp-browser.lua` would have a parser called `ftp`.
You can set the filter to match multiple parsers by separating the names with spaces.
```json
{
"key": "KP2",
"command": [ ["print-text", "example3"] ],
"parser": "ftp file"
}
```
The `flags` field is mostly only useful for addons, but can also be useful if one wants a key to be repeatable.
In this case the the keybind would look like the following:
```json
{
"key": "p",
"command": ["print-text", "spam-text"],
"flags": { "repeatable": true }
}
```
## Codes
The script will scan every string in the command for the special substitution strings, they are:
| code | description |
|--------|---------------------------------------------------------------------|
| `%%` | escape code for `%` |
| `%f` | filepath of the selected item |
| `%n` | filename of the selected item |
| `%p` | currently open directory |
| `%q` | currently open directory but preferring the directory label |
| `%d` | name of the current directory (characters between the last two '/') |
| `%r` | name of the parser for the currently open directory |
| `%x` | number of items in the currently open directory |
| `%i` | the 1-based index of the selected item in the list |
| `%j` | the 1-based index of the item in a multiselection - returns 1 for single selections |
Additionally, using the uppercase forms of those codes will send the substituted string through the `string.format("%q", str)` function.
This adds double quotes around the string and automatically escapes any characters which would break the string encapsulation.
This is not necessary for most mpv commands, but can be very useful when sending commands to the OS with the `run` command,
or when passing values into [expressions](#conditional-command-condition-command).
Example of a command to add an audio track:
```json
{
"key": "Ctrl+a",
"command": ["audio-add", "%f"],
"filter": "file"
}
```
Any commands that contain codes representing specific items (`%f`, `%n`, `%i` etc) will
not be run if no item is selected (for example in an empty directory).
In these cases [passthrough](#passthrough-keybinds) rules will apply.
## Multiselect Commands
When multiple items are selected the command can be run for all items in the order they appear on the screen.
This can be controlled by the `multiselect` flag, which takes a boolean value.
When not set the flag defaults to `false`.
There are two different multiselect modes, controlled by the `multi-type` option. There are two options:
### `repeat`
The default mode that sends the commands once for each item that is selected.
If time is needed between running commands of multiple selected items (for example, due to file handlers) then the `delay` option can be used to set a duration (in seconds) between commands.
### `concat`
Run a single command, but replace item specific codes with a concatenated string made from each selected item.
For example `["print-text", "%n" ]` would print the name of each item selected separated by `' '` (space).
The string inserted between each item is determined by the `concat-string` option, but `' '` is the default.
## Passthrough Keybinds
When loading keybinds from the json file file-browser will move down the list and overwrite any existing bindings with the same key.
This means the lower an item on the list, the higher preference it has.
However, file-browser implements a layered passthrough system for its keybinds; if a keybind is blocked from running by user filters, then the next highest preference command will be sent, continuing until a command is sent or there are no more keybinds.
The default dynamic keybinds are considered the lowest priority.
The `filter`, `parser`, and `condition` options can all trigger passthrough, as well as some [codes](#codes).
If a multi-select command is run on multiple items then passthrough will occur if any of the selected items fail the filters.
Passthrough can be forcibly disabled or enabled using the passthrough option.
When set to `true` passthrough will always be activate regardless of the state of the filters.
## Modifying Default Keybinds
Since the custom keybinds are applied after the default dynamic keybinds they can be used to overwrite the default bindings.
Setting new keys for the existing binds can be done with the `script-binding [binding-name]` command, where `binding-name` is the full name of the keybinding.
For this script the names of the dynamic keybinds are in the format `file_browser/dynamic/[name]` where `name` is a unique identifier documented in the [keybinds](README.md#keybinds) table.
For example to change the scroll buttons from the arrows to the scroll wheel:
```json
[
{
"key": "WHEEL_UP",
"command": ["script-binding", "file_browser/dynamic/scroll_up"]
},
{
"key": "WHEEL_DOWN",
"command": ["script-binding", "file_browser/dynamic/scroll_down"]
},
{
"key": "UP",
"command": ["osd-auto", "add", "volume", "2"]
},
{
"key": "DOWN",
"command": ["osd-auto", "add", "volume", "-2"]
}
]
```
Custom keybinds can be called using the same method, but users must set the `name` value inside the `file-browser-keybinds.json` file.
To avoid conflicts custom keybinds use the format: `file_browser/dynamic/custom/[name]`.
## Expressions
Expressions are used to evaluate Lua code into a string that can be used for commands.
These behave similarly to those used for [`profile-cond`](https://mpv.io/manual/master/#conditional-auto-profiles)
values. In an expression the `mp`, `mp.msg`, and `mp.utils` modules are available as `mp`, `msg`, and `utils` respectively.
Additionally, in mpv v0.38+ the `mp.input` module is available as `input`.
The file-browser [addon API](addons/addons.md#the-api) is available as `fb` and if [mpv-user-input](https://github.com/CogentRedTester/mpv-user-input)
is installed then user-input API will be available in `user_input`.
This example only runs the keybind if the browser is in the Windows C drive or if
the selected item is a matroska file:
```json
[
{
"key": "KP1",
"command": ["print-text", "in my C:/ drive!"],
"condition": "(%P):find('C:/') == 1"
},
{
"key": "KP2",
"command": ["print-text", "Matroska File!"],
"condition": "fb.get_extension(%N) == 'mkv'"
}
]
```
If the `condition` expression contains any item specific codes (`%F`, `%I`, etc) then it will be
evaluated on each individual item, otherwise it will evaluated once for the whole keybind.
If a code is invalid (for example using `%i` in empty directories) then the expression returns false.
There are some utility script messages that extend the power of expressions.
[`conditional-command`](#conditional-command-condition-command) allows one to specify conditions that
can apply to individual items or commands. The tradeoff is that you lose the automated passthrough behaviour.
There is also [`evaluate-expressions`](#evaluate-expressions-command) which allows one to evaluate expressions inside commands.
## Utility Script Messages
There are a small number of custom script messages defined by file-browser to support custom keybinds.
### `=> <command...>`
A basic script message that makes it easier to chain multiple utility script messages together.
Any `=>` string will be substituted for `script-message`.
```json
{
"key": "KP1",
"command": ["script-message", "=>", "delay-command", "%j * 2", "=>", "evaluate-expressions", "print-text", "!{%j * 2}"],
"multiselect": true
}
```
### `conditional-command [condition] <command...>`
Runs the following command only if the condition [expression](#expressions) is `true`.
This example command will only run if the player is currently paused:
```json
{
"key": "KP1",
"command": ["script-message", "conditional-command", "mp.get_property_bool('pause')", "print-text", "is paused"],
}
```
Custom keybind codes are evaluated before the expressions.
This example only runs if the currently selected item in the browser has a `.mkv` extension:
```json
{
"key": "KP1",
"command": ["script-message", "conditional-command", "fb.get_extension(%N) == 'mkv'", "print-text", "a matroska file"],
}
```
### `delay-command [delay] <command...>`
Delays the following command by `[delay]` seconds.
Delay is an [expression](#expressions).
The following example will send the `print-text` command after 5 seconds:
```json
{
"key": "KP1",
"command": ["script-message", "delay-command", "5", "print-text", "example"],
}
```
### `evaluate-expressions <command...>`
Evaluates embedded Lua expressions in the following command.
Expressions have the same behaviour as the [`conditional-command`](#conditional-command-condition-command) script-message.
Expressions must be surrounded by `!{}` characters.
Additional `!` characters can be placed at the start of the expression to
escape the evaluation.
For example the following keybind will print 3 to the console:
```json
{
"key": "KP1",
"command": ["script-message", "evaluate-expressions", "print-text", "!{1 + 2}"],
}
```
This example replaces all `/` characters in the path with `\`
(note that the `\` needs to be escaped twice, once for the json file, and once for the string in the lua expression):
```json
{
"key": "KP1",
"command": ["script-message", "evaluate-expressions", "print-text", "!{ string.gsub(%F, '/', '\\\\') }"],
}
```
### `run-statement <statement...>`
Runs the following string a as a Lua statement. This is similar to an [expression](#expressions),
but instead of the code evaluating to a value it must run a series of statements. Basically it allows
for function bodies to be embedded into custom keybinds. All the same modules are available.
If multiple strings are sent to the script-message then they will be concatenated together with newlines.
The following keybind will use [mpv-user-input](https://github.com/CogentRedTester/mpv-user-input) to
rename items in file-browser:
```json
{
"key": "KP1",
"command": ["script-message", "run-statement",
"assert(user_input, 'install mpv-user-input!')",
"local line, err = user_input.get_user_input_co({",
"id = 'rename-file',",
"source = 'custom-keybind',",
"request_text = 'rename file:',",
"queueable = true,",
"default_input = %N,",
"cursor_pos = #(%N) - #fb.get_extension(%N, '')",
"})",
"if not line then return end",
"os.rename(%F, utils.join_path(%P, line))",
"fb.rescan()"
],
"parser": "file",
"multiselect": true
}
```
## Examples
See [here](file-browser-keybinds.json).
@@ -0,0 +1,51 @@
[
{
"comment": "deletes the currently selected file",
"key": "Alt+DEL",
"command": ["script-message", "run-statement", "os.remove(%F) ; fb.rescan()"],
"multiselect": true,
"multi-type": "repeat"
},
{
"comment": "opens the currently selected items in a new mpv window",
"key": "Ctrl+ENTER",
"command": ["run", "mpv", "%F"],
"multiselect": true,
"multi-type": "concat"
},
{
"key": "Ctrl+c",
"command": [
["run", "powershell", "-command", "Set-Clipboard", "%F"],
["print-text", "copied filepath to clipboard"]
],
"condition": "fb.get_platform() == 'windows'",
"api_version": "1.9.0",
"multiselect": true,
"delay": 0.3
},
{
"key": "WHEEL_UP",
"command": ["script-binding", "file_browser/dynamic/scroll_up"],
"flags": { "repeat": true }
},
{
"key": "WHEEL_DOWN",
"command": ["script-binding", "file_browser/dynamic/scroll_down"],
"flags": { "repeat": true }
},
{
"key": "MBTN_LEFT",
"command": ["script-binding", "file_browser/dynamic/down_dir"]
},
{
"key": "MBTN_RIGHT",
"command": ["script-binding", "file_browser/dynamic/up_dir"]
},
{
"key": "MBTN_MID",
"command": ["script-binding", "file_browser/dynamic/play"]
}
]
+247
View File
@@ -0,0 +1,247 @@
#######################################################
# This is the default config file for mpv-file-browser
# https://github.com/CogentRedTester/mpv-file-browser
#######################################################
####################################
######## browser settings ##########
####################################
# Root directories, separated by commas.
# `C:/` and `/` are automatically added on Windows and non-windows systems, respectively.
# The order of automatically added items can be changed by entering them here manually.
root=~/
# characters to separate root directories, each character works individually
root_separators=,
# number of entries to show on the screen at once
num_entries=20
# number of directories to keep in the history.
# A size of 0 disables the history.
history_size=100
# wrap the cursor around the top and bottom of the list
wrap=no
# enables loading external addons
addons=yes
# enable custom keybinds
# the keybind json file must go in ~~/script-opts
custom_keybinds=yes
# Automatically detect windows drives and adds them to the root.
# Using Ctrl+r in the root will run another scan.
auto_detect_windows_drives=yes
# when opening the browser in idle mode prefer the current working directory over the root
# note that the working directory is set as the 'current' directory regardless, so `home` will
# move the browser there even if this option is set to false
default_to_working_directory=no
# When opening the browser prefer the directory last opened by a previous mpv instance of file-browser.
# Overrides the `default_to_working_directory` option.
# Requires `save_last_opened_directory` to be `yes`.
# Uses the internal `last-opened-directory` addon.
default_to_last_opened_directory=no
# Whether to save the last opened directory.
save_last_opened_directory=no
# Move the cursor to the currently playing item (if available) when the playing file changes.
cursor_follows_playing_item=no
####################################
########## filter settings #########
####################################
# only show files compatible with mpv in the browser
filter_files=yes
# file-browser only shows files that are compatible with mpv by default
# adding a file extension to this list will add it to the extension whitelist
# extensions are separated with commas, do not use any spaces
extension_whitelist=
# add file extensions to this list to disable default filetypes
# note that this will also override audio/subtitle_extension options below
extension_blacklist=
# files with these extensions will be added as additional audio tracks for the current file instead of appended to the playlist
# items on this list are automatically added to the extension whitelist
audio_extensions=mka,dts,dtshd,dts-hd,truehd,true-hd
# files with these extensions will be added as additional subtitle tracks for the current file instead of appended to the playlist
# items on this list are automatically added to the extension whitelist
subtitle_extensions=etf,etf8,utf-8,idx,sub,srt,rt,ssa,ass,mks,vtt,sup,scc,smi,lrc,pgs
# filter directories or files starting with a period like .config for linux systems
# auto will show dot entries on windows and hide them otherwise
filter_dot_dirs=auto
filter_dot_files=auto
####################################
###### file loading settings #######
####################################
# this option reverses the behaviour of the alt+ENTER keybind
# when disabled the keybind is required to enable autoload for the file
# when enabled the keybind disables autoload for the file
autoload=no
# experimental feature that recurses directories concurrently when appending items to the playlist
# this feature has the potential for massive performance improvements when using addons with asynchronous IO
concurrent_recursion=yes
# maximum number of recursions that can run concurrently
# if this number is too high it risks overflowing the mpv event queue, which will cause some directories to be dropped entirely
max_concurrency=16
# substitute forward slashes for backslashes when appending a local file to the playlist
# may be useful on windows systems
substitute_backslash=no
# if autoload is triggered by selecting the currently playing file, then
# the current file will have it's watch-later config saved before being closed and re-opened
# essentially the current file will not be restarted
autoload_save_current=yes
####################################
### directory parsing settings #####
####################################
# a directory cache to improve directory reading time,
# enable if it takes a long time to load directories.
# May cause 'ghost' files to be shown that no-longer exist or
# fail to show files that have recently been created.
# Reloading the directory with Ctrl+r will never use the cache.
# Use Ctrl+Shift+r to forcibly clear the cache.
cache=no
# Enables the internal `ls` addon that parses directories using the `ls` commandline tool.
# Allows directory parsing to run concurrently, which prevents the browser from locking up.
# Automatically disables itself on Windows systems.
ls_parser=yes
# Enables the internal `windir` addon that parses directories using the `dir` command in cmd.exe.
# Allows directory parsing to run concurrently, which prevents the browser from locking up.
# Automatically disables itself on non-Windows systems.
windir_parser=yes
# when moving up a directory do not stop on empty protocol schemes like `ftp://`
# e.g. moving up from `ftp://localhost/` will move straight to the root instead of `ftp://`
skip_protocol_schemes=yes
# map optical device paths to their respective file paths,
# e.g. mapping bd:// to the value of the bluray-device property
map_bd_device=yes
map_dvd_device=yes
map_cdda_device=yes
####################################
########## misc settings ###########
####################################
# turn the OSC idle screen off and on when opening and closing the browser
# this should only be enabled if file-browser is the only thing controlling the idle-screen,
# if multiple sources attempt to control the idle-screen at the same time it can cause unexpected behaviour.
toggle_idlescreen=no
# interpret backslashes `\` in paths as forward slashes `/`
# this is useful on Windows, which natively uses backslashes.
# As backslashes are valid filename characters in Unix systems this could
# cause mangled paths, though such filenames are rare.
# Use `yes` and `no` to enable/disable. `auto` tries to use the mpv `platform`
# property (mpv v0.36+) to decide. If the property is unavailable it defaults to `yes`.
normalise_backslash=auto
# Set the current open status of the browser in the `file_browser/open` field of the `user-data` property.
# This property is only available in mpv v0.36+.
set_user_data=yes
# Set the current open status of the browser in the `file_browser-open` field of the `shared-script-properties` property.
# This property is deprecated. When it is removed in mpv v0.37 file-browser will automatically disable this option.
set_shared_script_properties=no
####################################
########## file overrides #########
####################################
# directory to load external modules - currently just user-input-module
module_directory=~~/script-modules
addon_directory=~~/script-modules/file-browser-addons
custom_keybinds_file=~~/script-opts/file-browser-keybinds.json
last_opened_directory_file=~~state/file_browser-last_opened_directory
####################################
######### style settings ###########
####################################
# Replace the user's home directory with `~/` in the header.
# Uses the internal home-label addon.
home_label=yes
# force file-browser to use a specific alignment (default: top-left)
# set to auto to use the default mpv osd-align options
# Options: 'auto'|'top'|'center'|'bottom'
align_y=top
# Options: 'auto'|'left'|'center'|'right'
align_x=left
# The format string used for the header. Uses custom-keybind substitution codes to
# dynamically change the contents of the header (see: docs/custom-keybinds.md#codes)
# and supports the additional code `%^`which re-applies the default header ass style.
# The original style used before the current one was: %q\N----------------------------------------------------
format_string_header={\fnMonospace}[%i/%x]%^ %q\N------------------------------------------------------------------
# The format strings used for the wrappers. Supports custom-keybind substitution codes, and
# supports two additional codes: `%<` and `%>` to show the number of items before and after the visible list, respectively.
# Setting these options to empty strings will disable the wrappers.
# Original styles used before the current ones were:
# top: %< item(s) above\N
# bottom: \N%> item(s) remaining
format_string_topwrapper=...
format_string_bottomwrapper=...
# allows custom icons be set for the folder and cursor
# the `\h` character is a hard space to add padding
folder_icon={\p1}m 6.52 0 l 1.63 0 b 0.73 0 0.01 0.73 0.01 1.63 l 0 11.41 b 0 12.32 0.73 13.05 1.63 13.05 l 14.68 13.05 b 15.58 13.05 16.31 12.32 16.31 11.41 l 16.31 3.26 b 16.31 2.36 15.58 1.63 14.68 1.63 l 8.15 1.63{\p0}\h
cursor_icon={\p1}m 14.11 6.86 l 0.34 0.02 b 0.25 -0.02 0.13 -0 0.06 0.08 b -0.01 0.16 -0.02 0.28 0.04 0.36 l 3.38 5.55 l 3.38 5.55 3.67 6.15 3.81 6.79 3.79 7.45 3.61 8.08 3.39 8.5l 0.04 13.77 b -0.02 13.86 -0.01 13.98 0.06 14.06 b 0.11 14.11 0.17 14.13 0.24 14.13 b 0.27 14.13 0.31 14.13 0.34 14.11 l 14.11 7.28 b 14.2 7.24 14.25 7.16 14.25 7.07 b 14.25 6.98 14.2 6.9 14.11 6.86{\p0}\h
cursor_icon_flipped={\p1}m 0.13 6.86 l 13.9 0.02 b 14 -0.02 14.11 -0 14.19 0.08 b 14.26 0.16 14.27 0.28 14.21 0.36 l 10.87 5.55 l 10.87 5.55 10.44 6.79 10.64 8.08 10.86 8.5l 14.21 13.77 b 14.27 13.86 14.26 13.98 14.19 14.06 b 14.14 14.11 14.07 14.13 14.01 14.13 b 13.97 14.13 13.94 14.13 13.9 14.11 l 0.13 7.28 b 0.05 7.24 0 7.16 0 7.07 b 0 6.98 0.05 6.9 0.13 6.86{\p0}\h
# set the opacity of fonts in hexadecimal from 00 (opaque) to FF (transparent)
font_opacity_selection_marker=99
# print the header in bold font
font_bold_header=yes
# scale the size of the browser; 2 would double the size, 0.5 would halve it, etc.
# the header and wrapper scaling is relative to the base scaling
scaling_factor_base=1
scaling_factor_header=1.4
scaling_factor_wrappers=1
# set custom font names, blank is the default
# setting custom fonts for the folder/cursor can fix broken or missing icons
font_name_header=
font_name_body=
font_name_wrappers=
font_name_folder=
font_name_cursor=
# set custom font colours
# colours are in hexadecimal format in Blue Green Red order
# note that this is the opposite order to RGB colour codes
font_colour_header=00ccff
font_colour_body=ffffff
font_colour_wrappers=00ccff
font_colour_cursor=00ccff
font_colour_escape_chars=413eff
# these are colours applied to list items in different states
font_colour_selected=fce788
font_colour_multiselect=fcad88
font_colour_playing=33ff66
font_colour_playing_multiselected=22b547