mirror of
https://github.com/jarun/nnn.git
synced 2024-11-28 13:51:31 +00:00
desktop opener - xdg-open on Linux and open(1) on OS X
This commit is contained in:
parent
94ed36b498
commit
fe775ccf1f
45
README.md
45
README.md
|
@ -37,7 +37,7 @@ Noice is Not Noice, a noicer fork...
|
||||||
- [copy file path to clipboard](#copy-file-path-to-clipboard)
|
- [copy file path to clipboard](#copy-file-path-to-clipboard)
|
||||||
- [file copy, move, delete](#file-copy-move-delete)
|
- [file copy, move, delete](#file-copy-move-delete)
|
||||||
- [boost chdir prompt](#boost-chdir-prompt)
|
- [boost chdir prompt](#boost-chdir-prompt)
|
||||||
- [change file associations](#change-file-associations)
|
- [change text file association](#change-text-file-association)
|
||||||
- [set idle timeout](#set-idle-timeout)
|
- [set idle timeout](#set-idle-timeout)
|
||||||
- [Why fork?](#why-fork)
|
- [Why fork?](#why-fork)
|
||||||
- [Mentions](#mentions)
|
- [Mentions](#mentions)
|
||||||
|
@ -47,7 +47,7 @@ Noice is Not Noice, a noicer fork...
|
||||||
|
|
||||||
`nnn` is a fork of [noice](http://git.2f30.org/noice/), a blazing-fast lightweight terminal file browser with easy keyboard shortcuts for navigation, opening files and running tasks. noice is developed considering terminal based systems. There is no config file and mime associations are hard-coded. However, the incredible user-friendliness and speed make it a perfect utility on modern distros.
|
`nnn` is a fork of [noice](http://git.2f30.org/noice/), a blazing-fast lightweight terminal file browser with easy keyboard shortcuts for navigation, opening files and running tasks. noice is developed considering terminal based systems. There is no config file and mime associations are hard-coded. However, the incredible user-friendliness and speed make it a perfect utility on modern distros.
|
||||||
|
|
||||||
`nnn` can use the default desktop opener at runtime and handle media types with [nlay](https://github.com/jarun/nnn/wiki/all-about-nlay), a customizable bash script. `nnn` adds new navigation options, [navigate-as-you-type](#navigate-as-you-type-mode) mode, enhanced DE integration, a disk usage analyzer mode, comprehensive file details and much more. Add to that a huge [performance](#performance) boost. For a detailed comparison, visit [nnn vs. noice](https://github.com/jarun/nnn/wiki/nnn-vs.-noice).
|
`nnn` can use the desktop opener at runtime and handle text files or actions with [nlay](https://github.com/jarun/nnn/wiki/all-about-nlay), a customizable bash script. `nnn` adds new navigation options, [navigate-as-you-type](#navigate-as-you-type-mode) mode, enhanced DE integration, a disk usage analyzer mode, comprehensive file details and much more. Add to that a huge [performance](#performance) boost. For a detailed comparison, visit [nnn vs. noice](https://github.com/jarun/nnn/wiki/nnn-vs.-noice).
|
||||||
|
|
||||||
If you want to edit a file in vim with some soothing music in the background while referring to a spec in your GUI PDF viewer, `nnn` got it! All from the same terminal session. Follow the instructions in the [quickstart](#quickstart) section and see how `nnn` simplifies those long desktop sessions...
|
If you want to edit a file in vim with some soothing music in the background while referring to a spec in your GUI PDF viewer, `nnn` got it! All from the same terminal session. Follow the instructions in the [quickstart](#quickstart) section and see how `nnn` simplifies those long desktop sessions...
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ Have fun with it! PRs are welcome. Check out [#1](https://github.com/jarun/nnn/i
|
||||||
- Desktop search (default gnome-search-tool, customizable) integration
|
- Desktop search (default gnome-search-tool, customizable) integration
|
||||||
- Mimes
|
- Mimes
|
||||||
- Desktop opener integration
|
- Desktop opener integration
|
||||||
- Customizable bash script [nlay](https://github.com/jarun/nnn/wiki/all-about-nlay) to handle media type or action
|
- Customizable bash script [nlay](https://github.com/jarun/nnn/wiki/all-about-nlay) to handle text files or actions
|
||||||
- Information
|
- Information
|
||||||
- Basic and detail view
|
- Basic and detail view
|
||||||
- Detailed file information
|
- Detailed file information
|
||||||
|
@ -215,26 +215,13 @@ The following abbreviations are used in the detail view:
|
||||||
|
|
||||||
#### File handling
|
#### File handling
|
||||||
|
|
||||||
`nnn` is designed to play files using multiple strategies (in order of decreasing priority):
|
- `nnn` uses `xdg-open` on Linux and `open(1)` on OS X as the desktop opener. To let the desktop opener handle everything:
|
||||||
- Set `NNN_OPENER` to let a desktop opener handle it all. E.g.:
|
|
||||||
|
|
||||||
export NNN_OPENER=xdg-open
|
export NNN_OPENER=1
|
||||||
export NNN_OPENER="gio open"
|
- If `NNN_OPENER` is not set:
|
||||||
export NNN_OPENER=gvfs-open
|
- If `nnn` recognizes a text file by extension, it invokes nlay, which in turn opens the file in vim.
|
||||||
- If `nnn` recognizes the file extension, it invokes nlay (which invokes the players). Default apps:
|
|
||||||
- mpv - audio and video
|
|
||||||
- viewnior, fim - image
|
|
||||||
- [zathura](https://pwmt.org/projects/zathura/) - pdf
|
|
||||||
- vim - plain text
|
|
||||||
- gnome-search-tool, catfish - search
|
|
||||||
- vlock - terminal screensaver
|
|
||||||
- to add, remove recognized extensions in `nnn`, see [how to change file associations](#change-file-associations)
|
|
||||||
- If a file without any extension is a plain text file, it is opened in EDITOR (fallback vi)
|
- If a file without any extension is a plain text file, it is opened in EDITOR (fallback vi)
|
||||||
- Set `NNN_FALLBACK_OPENER` as the fallback opener. E.g.:
|
- All other files are handled by desktop opener
|
||||||
|
|
||||||
export NNN_FALLBACK_OPENER=xdg-open
|
|
||||||
export NNN_FALLBACK_OPENER="gio open"
|
|
||||||
export NNN_FALLBACK_OPENER=gvfs-open
|
|
||||||
- To enable the desktop file manager key, set `NNN_DE_FILE_MANAGER`. E.g.:
|
- To enable the desktop file manager key, set `NNN_DE_FILE_MANAGER`. E.g.:
|
||||||
|
|
||||||
export NNN_DE_FILE_MANAGER=thunar
|
export NNN_DE_FILE_MANAGER=thunar
|
||||||
|
@ -253,9 +240,9 @@ Add the following to your shell's rc file for the best experience:
|
||||||
1. Always open `nnn` in detail mode:
|
1. Always open `nnn` in detail mode:
|
||||||
|
|
||||||
alias n='nnn -d'
|
alias n='nnn -d'
|
||||||
2. Set preferred desktop opener as fallback. E.g.:
|
2. Set desktop opener as default:
|
||||||
|
|
||||||
export NNN_FALLBACK_OPENER=xdg-open
|
export NNN_OPENER=1
|
||||||
3. Set a desktop file manager to open directories with (if you need one). E.g.:
|
3. Set a desktop file manager to open directories with (if you need one). E.g.:
|
||||||
|
|
||||||
export NNN_DE_FILE_MANAGER=thunar
|
export NNN_DE_FILE_MANAGER=thunar
|
||||||
|
@ -277,7 +264,7 @@ As you might notice, `nnn` uses the environment variable `NNN_TMPFILE` to write
|
||||||
|
|
||||||
#### customize nlay
|
#### customize nlay
|
||||||
|
|
||||||
nlay is a tiny standalone media type *player* by itself. To know how to customize or extend its functionality, please visit [nlay on wiki](https://github.com/jarun/nnn/wiki/all-about-nlay).
|
nlay is a tiny standalone text file and action handler. To know how to customize or extend its functionality, please visit [nlay on wiki](https://github.com/jarun/nnn/wiki/all-about-nlay).
|
||||||
|
|
||||||
#### copy file path to clipboard
|
#### copy file path to clipboard
|
||||||
|
|
||||||
|
@ -289,9 +276,9 @@ Sample Linux copier script:
|
||||||
|
|
||||||
echo -n $1 | xsel --clipboard --input
|
echo -n $1 | xsel --clipboard --input
|
||||||
|
|
||||||
export `NNN_OPENER`:
|
export `NNN_COPIER`:
|
||||||
|
|
||||||
export NNN_COPIER="/home/vaio/copier.sh"
|
export NNN_COPIER="/path/to/copier.sh"
|
||||||
|
|
||||||
Start `nnn` and use <kbd>^K</kbd> to copy the absolute path (from `/`) of the file under the cursor to clipboard.
|
Start `nnn` and use <kbd>^K</kbd> to copy the absolute path (from `/`) of the file under the cursor to clipboard.
|
||||||
|
|
||||||
|
@ -307,11 +294,11 @@ Start `nnn` and use <kbd>^K</kbd> to copy the absolute path (from `/`) of the fi
|
||||||
|
|
||||||
`nnn` uses libreadline for the chdir prompt input. So all the fantastic features of readline (e.g. case insensitive tab completion, history, reverse-i-search) is available to you based on your readline [configuration](https://cnswww.cns.cwru.edu/php/chet/readline/readline.html#SEC9).
|
`nnn` uses libreadline for the chdir prompt input. So all the fantastic features of readline (e.g. case insensitive tab completion, history, reverse-i-search) is available to you based on your readline [configuration](https://cnswww.cns.cwru.edu/php/chet/readline/readline.html#SEC9).
|
||||||
|
|
||||||
#### change file associations
|
#### change text file association
|
||||||
|
|
||||||
If `NNN_OPENER` is not set, `nnn` tries to recognize a file by the file extension and invokes nlay. To change the extensions recognized by `nnn`, modify the `assocs` structure in [config.def.h](https://github.com/jarun/nnn/blob/master/config.def.h) (it's easy). Then re-compile and install.
|
If `NNN_OPENER` is not set, `nnn` tries to recognize text files by extension and invokes nlay. To add a new extension mainline, please raise a bug. Without it `nnn` will not invoke nlay.
|
||||||
|
|
||||||
If you want to add a file extension mainline, please raise a bug. Without it `nnn` will not invoke nlay.
|
Text files are opened in vim by default. You can easily change it in nlay.
|
||||||
|
|
||||||
nlay has provisions (disabled by default) to handle a specific file extension too. However, the extension should be recognized by `nnn` first.
|
nlay has provisions (disabled by default) to handle a specific file extension too. However, the extension should be recognized by `nnn` first.
|
||||||
|
|
||||||
|
|
|
@ -13,10 +13,6 @@ static int showdetail = 0; /* Set to show additional file info */
|
||||||
|
|
||||||
static struct assoc assocs[] = {
|
static struct assoc assocs[] = {
|
||||||
{ "\\.(c|cpp|h|log|md|py|sh|txt)$", "text" },
|
{ "\\.(c|cpp|h|log|md|py|sh|txt)$", "text" },
|
||||||
{ "\\.(3g2|3gp|asf|avi|divx|flv|m2v|m4v|mkv|mov|mp4|mp4v|mpeg|mpg|ogv|qt|rm|rmvb|vob|webm|wmv)$", "video" },
|
|
||||||
{ "\\.(aac|ac3|amr|flac|m4a|m4b|m4p|mp3|mp4a|ogg|opus|ra|wav|wma)$", "audio" },
|
|
||||||
{ "\\.(bmp|gif|jpeg|jpg|pbm|pgm|png|svg|tiff|webp)$", "image" },
|
|
||||||
{ "\\.pdf$", "pdf" },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct key bindings[] = {
|
static struct key bindings[] = {
|
||||||
|
|
58
nlay
58
nlay
|
@ -22,10 +22,7 @@
|
||||||
# 2. Detached apps are not killed when nnn exits. Use kill(1) or killall(1) to
|
# 2. Detached apps are not killed when nnn exits. Use kill(1) or killall(1) to
|
||||||
# to stop console based background apps.
|
# to stop console based background apps.
|
||||||
#
|
#
|
||||||
# 3. Assuming you don't to play multiple audio/video files simultaneously,
|
# 3. nlay is OVERWRITTEN during nnn upgrade. You can store your custom nlay in a
|
||||||
# nlay kills any running instances of the audio/video player in bg mode.
|
|
||||||
#
|
|
||||||
# 4. nlay is OVERWRITTEN during nnn upgrade. You can store your custom nlay in a
|
|
||||||
# location other than the default and have an alias with nnn option '-p' to
|
# location other than the default and have an alias with nnn option '-p' to
|
||||||
# invoke it. Remember it might break or lack new capabilities added to nlay
|
# invoke it. Remember it might break or lack new capabilities added to nlay
|
||||||
# in future releases. Check the file diff once in a while.
|
# in future releases. Check the file diff once in a while.
|
||||||
|
@ -56,59 +53,8 @@ ext="${ext,,}"
|
||||||
ENABLE_FILE_TYPE_HANDLING
|
ENABLE_FILE_TYPE_HANDLING
|
||||||
|
|
||||||
|
|
||||||
#------------------ AUDIO -------------------
|
|
||||||
if [ "$2" == "audio" ]; then
|
|
||||||
app=mpv
|
|
||||||
|
|
||||||
# To start mpv in a window enable opts
|
|
||||||
#opts="--no-terminal --force-window"
|
|
||||||
|
|
||||||
#bg=">/dev/null 2>&1 &"
|
|
||||||
|
|
||||||
if [ -n "$bg" ]; then
|
|
||||||
killall -9 $app >/dev/null 2>&1
|
|
||||||
fi
|
|
||||||
|
|
||||||
eval $app $opts "\"$1\"" $bg
|
|
||||||
exit 0
|
|
||||||
|
|
||||||
#------------------ VIDEO -------------------
|
|
||||||
elif [ "$2" == "video" ]; then
|
|
||||||
app=mpv
|
|
||||||
|
|
||||||
# To start mpv in a window enable opts
|
|
||||||
#opts="--no-terminal --force-window"
|
|
||||||
|
|
||||||
#bg=">/dev/null 2>&1 &"
|
|
||||||
|
|
||||||
if [ -n "$bg" ]; then
|
|
||||||
killall -9 $app >/dev/null 2>&1
|
|
||||||
fi
|
|
||||||
|
|
||||||
eval $app $opts "\"$1\"" $bg
|
|
||||||
exit 0
|
|
||||||
|
|
||||||
#------------------ IMAGE -------------------
|
|
||||||
elif [ "$2" == "image" ]; then
|
|
||||||
app=("viewnior"
|
|
||||||
"fim")
|
|
||||||
|
|
||||||
opts=(""
|
|
||||||
"-a --cd-and-readdir")
|
|
||||||
|
|
||||||
bg=(">/dev/null 2>&1 &"
|
|
||||||
">/dev/null 2>&1 &")
|
|
||||||
|
|
||||||
#------------------- PDF --------------------
|
|
||||||
elif [ "$2" == "pdf" ]; then
|
|
||||||
app=("zathura")
|
|
||||||
|
|
||||||
opts=("")
|
|
||||||
|
|
||||||
bg=(">/dev/null 2>&1 &")
|
|
||||||
|
|
||||||
#---------------- PLAINTEXT -----------------
|
#---------------- PLAINTEXT -----------------
|
||||||
elif [ "$2" == "text" ]; then
|
if [ "$2" == "text" ]; then
|
||||||
app=("vim")
|
app=("vim")
|
||||||
|
|
||||||
opts=("")
|
opts=("")
|
||||||
|
|
30
nnn.1
30
nnn.1
|
@ -15,7 +15,7 @@
|
||||||
.Op Ar PATH
|
.Op Ar PATH
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
(Noice is Not Noice) is a performance-optimized fork of the noice terminal file browser with improved desktop integration, customizable media type handler, simplified navigation, navigate-as-you-type mode, disk usage analyzer mode, comprehensive file details and much more. It remains a simple and efficient file browser that stays out of your way.
|
(Noice is Not Noice) is a performance-optimized fork of the noice terminal file browser with extensive desktop integration, customizable text file or action handler, simplified navigation, navigate-as-you-type mode, disk usage analyzer mode, comprehensive file details and much more. It remains a simple and efficient file browser that stays out of your way.
|
||||||
.Pp
|
.Pp
|
||||||
.Nm
|
.Nm
|
||||||
defaults to the current directory if
|
defaults to the current directory if
|
||||||
|
@ -118,23 +118,18 @@ supports the following options:
|
||||||
show program help and exit
|
show program help and exit
|
||||||
.Sh CONFIGURATION
|
.Sh CONFIGURATION
|
||||||
.Nm
|
.Nm
|
||||||
|
uses \fIxdg-open\fR (on Linux) and \fIopen(1)\fR (on OS X) as the desktop
|
||||||
|
opener. If \fBNNN_OPENER\fR (see ENVIRONMENT section below) is not set,
|
||||||
|
.Nm
|
||||||
invokes
|
invokes
|
||||||
.Pa nlay
|
.Pa nlay
|
||||||
to play files recognized by extension. It is a highly customizable bash shell
|
to view text files (recognized by extension) or run actions. It is a highly
|
||||||
script which invokes a player depending on the
|
customizable bash shell script. Read more on
|
||||||
type of file. Read more on
|
|
||||||
.Pa nlay
|
.Pa nlay
|
||||||
at:
|
at:
|
||||||
.br
|
.br
|
||||||
.Em https://github.com/jarun/nnn/wiki/all-about-nlay
|
.Em https://github.com/jarun/nnn/wiki/all-about-nlay
|
||||||
.Pp
|
.Pp
|
||||||
.Nm
|
|
||||||
is configured by modifying
|
|
||||||
.Pa config.def.h
|
|
||||||
and recompiling the code. config.h is generated as a backup of config.def.h.
|
|
||||||
.Pp
|
|
||||||
See the environment and examples sections below for more options and information.
|
|
||||||
.Pp
|
|
||||||
Configuring
|
Configuring
|
||||||
.Nm
|
.Nm
|
||||||
to change to the last visited directory on quit requires shell integration in a
|
to change to the last visited directory on quit requires shell integration in a
|
||||||
|
@ -169,14 +164,11 @@ when dealing with the !, e and p commands respectively.
|
||||||
\fBNNN_DE_FILE_MANAGER:\fR set to a desktop file manager to open the current
|
\fBNNN_DE_FILE_MANAGER:\fR set to a desktop file manager to open the current
|
||||||
directory with.
|
directory with.
|
||||||
.Pp
|
.Pp
|
||||||
\fBNNN_OPENER:\fR set to your desktop environment's default
|
\fBNNN_OPENER:\fR set \fIxdg-open\fR (on Linux) or \fIopen(1)\fR desktop opener
|
||||||
mime opener to override all custom mime associations.
|
to handle all file types.
|
||||||
.br
|
.Bd -literal
|
||||||
Examples: xdg-open, gio open, gvfs-open.
|
export NNN_OPENER=1
|
||||||
.Pp
|
.Ed
|
||||||
\fBNNN_FALLBACK_OPENER:\fR set to your desktop environment's default
|
|
||||||
mime opener to use as a fallback when no association is set for a file
|
|
||||||
type. Custom associations are listed in the EXAMPLES section below.
|
|
||||||
.Pp
|
.Pp
|
||||||
\fBNNN_IDLE_TIMEOUT:\fR set idle timeout (in seconds) to invoke terminal
|
\fBNNN_IDLE_TIMEOUT:\fR set idle timeout (in seconds) to invoke terminal
|
||||||
screensaver.
|
screensaver.
|
||||||
|
|
38
nnn.c
38
nnn.c
|
@ -151,9 +151,7 @@ extern int wget_wch(WINDOW *, wint_t *);
|
||||||
static struct entry *dents;
|
static struct entry *dents;
|
||||||
static int ndents, cur, total_dents;
|
static int ndents, cur, total_dents;
|
||||||
static int idle;
|
static int idle;
|
||||||
static char *opener;
|
static int opener;
|
||||||
static char *fb_opener;
|
|
||||||
static char *nlay="nlay";
|
|
||||||
static char *player;
|
static char *player;
|
||||||
static char *copier;
|
static char *copier;
|
||||||
static char *desktop_manager;
|
static char *desktop_manager;
|
||||||
|
@ -162,6 +160,15 @@ static size_t fs_free;
|
||||||
static int open_max;
|
static int open_max;
|
||||||
static const double div_2_pow_10 = 1.0 / 1024.0;
|
static const double div_2_pow_10 = 1.0 / 1024.0;
|
||||||
|
|
||||||
|
static char *utils[] = {
|
||||||
|
#ifdef __APPLE__
|
||||||
|
"/usr/bin/open",
|
||||||
|
#else
|
||||||
|
"/usr/bin/xdg-open",
|
||||||
|
#endif
|
||||||
|
"nlay"
|
||||||
|
};
|
||||||
|
|
||||||
/* For use in functions which are isolated and don't return the buffer */
|
/* For use in functions which are isolated and don't return the buffer */
|
||||||
static char g_buf[MAX_CMD_LEN];
|
static char g_buf[MAX_CMD_LEN];
|
||||||
|
|
||||||
|
@ -1659,11 +1666,11 @@ nochange:
|
||||||
{
|
{
|
||||||
/* If NNN_OPENER is set, use it */
|
/* If NNN_OPENER is set, use it */
|
||||||
if (opener) {
|
if (opener) {
|
||||||
spawn(opener, newpath, NULL, NULL, 4);
|
spawn(utils[0], newpath, NULL, NULL, 4);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Play with nlay if identified */
|
/* Play text-based files with nlay */
|
||||||
mime = getmime(dents[cur].name);
|
mime = getmime(dents[cur].name);
|
||||||
if (mime) {
|
if (mime) {
|
||||||
exitcurses();
|
exitcurses();
|
||||||
|
@ -1672,8 +1679,7 @@ nochange:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If nlay doesn't handle it, open plain text
|
/* Recognize and open plain text files with vi */
|
||||||
files with vi, then try NNN_FALLBACK_OPENER */
|
|
||||||
if (get_output(g_buf, MAX_CMD_LEN, "file", "-bi",
|
if (get_output(g_buf, MAX_CMD_LEN, "file", "-bi",
|
||||||
newpath, 0) == NULL)
|
newpath, 0) == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1684,13 +1690,11 @@ nochange:
|
||||||
spawn(run, newpath, NULL, NULL, 0);
|
spawn(run, newpath, NULL, NULL, 0);
|
||||||
initcurses();
|
initcurses();
|
||||||
continue;
|
continue;
|
||||||
} else if (fb_opener) {
|
|
||||||
spawn(fb_opener, newpath, NULL, NULL, 4);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printmsg("No association");
|
/* Invoke desktop opener as last resort */
|
||||||
goto nochange;
|
spawn(utils[0], newpath, NULL, NULL, 4);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
printmsg("Unsupported file");
|
printmsg("Unsupported file");
|
||||||
|
@ -2165,15 +2169,13 @@ main(int argc, char *argv[])
|
||||||
showhidden = 1;
|
showhidden = 1;
|
||||||
initfilter(showhidden, &ifilter);
|
initfilter(showhidden, &ifilter);
|
||||||
|
|
||||||
/* Get the default desktop mime opener, if set */
|
/* Always use desktop opener, if opted */
|
||||||
opener = getenv("NNN_OPENER");
|
if (getenv("NNN_OPENER"))
|
||||||
|
opener = 1;
|
||||||
|
|
||||||
/* Set player if not set already */
|
/* Set player if not set already */
|
||||||
if (!player)
|
if (!player)
|
||||||
player = nlay;
|
player = utils[1];
|
||||||
|
|
||||||
/* Get the fallback desktop mime opener, if set */
|
|
||||||
fb_opener = getenv("NNN_FALLBACK_OPENER");
|
|
||||||
|
|
||||||
/* Get the desktop file browser, if set */
|
/* Get the desktop file browser, if set */
|
||||||
desktop_manager = getenv("NNN_DE_FILE_MANAGER");
|
desktop_manager = getenv("NNN_DE_FILE_MANAGER");
|
||||||
|
|
Loading…
Reference in a new issue