On OpenBSD at least one of O_RDONLY, O_WRONLY or O_RDWR is needed to open a file.
In creating a new file none of those is set, which leads to an EINVAL error ("invalid argument").
Since the new file is only created and never read, I chose to use O_WRONLY.
* Changed exa from grid to tree view (preview-tui)
* Update plugins/preview-tui
Change also eza
Co-authored-by: blissful <blissful@sunsetglow.net>
* Changed maximum depth in exa and eza
* Added fifo_pager to exa and eza
---------
Co-authored-by: blissful <blissful@sunsetglow.net>
This moves setting PWD environment variable closer to the places where child process (that needs PWD correctly set) is started instead of start it on browse.
This is to cd to path as it pointed by symlink, not to it's real path. Bookmarked directory may itself contain symlinks in path, which should be respected.
For example: if directory is physically in /mnt/storage/some and it's symlinked to ~/some and directory ~/some/dir added to bookmarks, it's expected that when following bookmark directory will be changed to ~/some/dir (as in bookmark's link) not to /mnt/storage/some/dir (as dir real path).
If `path` is not provided to `abspath`, later will do `getcwd`, and it's result will differ from `path`. This causes problem that when creating directory inside path reached with symlink, subsequent call to get_cwd_entry does not recognize newly created path as subpath of current path, thus not selecting newly created element.
the size of g_buf depends on PATH_MAX and NAME_MAX which on certain
platforms (such as mac) might not be big enough to decode the help
string. use an explicit buffer with proper size instead.
Closes: https://github.com/jarun/nnn/issues/1768
This is useful for situations where the executable is compiled with
readline support but the user wants to use the native prompt. Often
this happens because packagers build without readline disabled.
Forward jumping to the next young file is implemented. The starting
position from which the next young file is searched is the next
position. If no young file has been found, the search starts from the
beginning. It stops at the initial position where the search has
started.
according to the manpage, it won't have any effect on 64bit system
anyways. and musl always uses 64bit so this macro doesn't have any
effect there either.
this avoids multiple printf calls and instead decodes the buffer
natively. using %NN instead of %-NNc also saves two bytes per run.
helpstr is also made `static` to avoid unnecessary stack allocation.
this makes it so that if the cp/mv commands are changed the in the
future, it will continue to work reliably instead of having hardcoded
indexes to modify the array.
the `#ifdef __linux__` is also removed, compilers should be smart enough
to see that PROGRESS_{CP,MV} are unused (on non-linux systems) and
optimize it out.
This commit makes the following changes to quitcd.bash_zsh:
- POSIX compliance and an according rename of the script
- Enforces consistent if-then statements and indentation
- Minor comment fixes
Signed-off-by: J. Brock <joseph.brock@protonmail.com>
- Clear filter only when a plugin is selected manually.
Plugin dir should be unfiltered when opened.
- Plugins invoked by keys don't require clearing filter
of original context. If a new context is opened using
the plugin, it will be unfiltered by default. If the
same context is re-used (when all the contexts are in
use) the filter should be cleared so the the new path
is opened unfiltered.
This commit makes the script more resistant to naughty filenames.
The script now depends on bash for the following features:
- Arrays
Correctly creating and passing argument lists is now simple
- Parameter transformation
`${parameter@Q}` makes it easy to correctly quote a string so that it
can be safely re-evaluated by the interpreter later.
On iTerm, the shell command used to render the preview is now passed to
osascript via a named pipe: `$FIFO_OSASCRIPT`. By not embedding the
shell command directly, we now no longer need to worry about osascript's
quoting rules. It's not perfect, because $SHELL and $TMPDIR might
contain naughty characters, but it's quite unlikely to happen.
the rename plugin always asks for "selection vs current" even when -u
flag is active. pass it to the plugin via `NNN_PREFER_SELECTION` so that
there's less distracting prompts.
Problem: List of environment variables is copied for each previewer.
Environment variable names are too general.
Solution: Parameterize environment variable flags with static list of
variables. Prepend user-facing variables with `NNN_`.
in case the rotation is 0, `v >> (32 - r)` would end up doing a 32 right
shift which is equal to the width of `v` and thus undefined behavior.
ref: https://blog.regehr.org/archives/1063
* icons-hash: take total probe count into account as well
* icons-hash: use a better PRNG
the older method was using a multiplicative congruential generator (MCG)
which doesn't work too well especially with just 32 bits of state.
change it to a PCG instead with 64 bits of state (and 32 bits of output)
which should give better results.
and since we should get better rng - the search iteration has been
halved as well to save some build time.
* icons-hash: use an xor-rotate hash function
* icons-hash: fix some compiler warnings
* plugins/nmount: keep `while` & `do` on one line for consistency
* plugins/nmount: sync only that device, which user wants to unmount
* plugins/nmount: replace all instances of `$dev` with `/dev/$dev`
* plugins/nmount: add `--no-user-interaction` option to `udisksctl`
Otherwise the user will be asked for authentication each time he wants
to unmount, say, HDD, since `udisksctl` will try to power it off.
* plugins/nmount: try to mount only existing block devices
* plugins/nmount: do not invoke `lsblk` immediately after mounting
Sometimes `lsblk` fails to provide mountpoint in such a short time frame.
* plugins/nmount: simplify pipe
* plugins/nmount: keep `echo` arguments in a single pair of quotes
* plugins/nmount: report mountpoint only if mounting was successful
- Work with multiple connected devices by sending files to the first
device
- Support multi-files selection
- Support sending hovered file in case no file is selected
Co-authored-by: NRK <nrk@disroot.org>
Co-authored-by: Arun Prakash Jana <engineerarun@gmail.com>
1. hover on entry created in cwd
2. check user input doesn't end with /
3. check user input len < PATH_MAX
4. support creation in ~ directory
5. handle filter mode after creation
6. ensure absolute path len < PATH_MAX
nnn source code already uses C11, which introduced `_Alignas` [^0] as a
standardized alternative to __attribute__((aligned)).
there are no other usage of `__attribute__` in the nnn source code, so
in theory this should make things more portable across compilers.
also removes an unnecessary usage of `alloca()` with an aligned constant
sized buffer instead.
[^0]: https://en.cppreference.com/w/c/language/_Alignas
Found memory deallocation edge case
Update and move chunk limit check
Generalize maximum size of input
Remove hard-coded values
Remove superfluous check before free
Let the kernel deal with extra data
Handle signals while reading
Conform to the manpage
Make CI happy
use `size_t` instead of `ssize_t`
`ssize_t` was used just so `--i` when `i` was zero would become -1
instead of SIZE_MAX. for looping through something in reverse order, the
"goes-to" operator (`-->`) can be used instead which doesn't require `i`
to be signed anymore.
remove useless blank line
use a normal loop
don't see any reason why freeing in reverse order would've been needed.
Co-authored-by: N-R-K <nrk@disroot.org>
- support listing maximum 16K files
- check if target directory exists before directory tree creation
in most of the cases many files will be under the same directory
- make frequently used function 'inline'
* Added icons for erlang, elixir and lockfile
* Lockfile icon updated
* Added colors for Erlang and elixir
* Added few more color variations and configured colors and file
extensions
* remove erlang and lock, use 1 color for elixir
Co-authored-by: Tharindu Abeydeera <tharindu.a@vizuamatix.com>
Co-authored-by: NRK <nrk@disroot.org>
a lot of the extension use the same icon. this can be exploited via
having an array with all the unique icons and then storing a single byte
index into the unique array.
when using `O_EMOJI` this results in around ~1.7KiB drop in the total
table size. `O_NERD` and `O_ICONS` get roughly ~0.5KiB savings.
This pretty much reworks the entire icon system. Some notable changes:
* The extensions are put into a statically generated hash-table instead
of a sorted array. We use Robin-Hood insertion to reduce the max probe
length. Currently we need to probe only 2 slots for `O_EMOJI` and only
3 for `O_NERD`/`O_ICONS`.
* I've opted not to use a perfect-hash since the perfect hashes
generated by [`gperf`](https://www.gnu.org/software/gperf) used some
huge lookup table. The hash function also wasn't as minimal as I'd
like.
* Colors are now using X-Macros. This should speed up startup since we
don't have to search `icons_ext` linearly to find unique colors.
* The hash-table generator outputs a more space optimized `struct
icon_pair` using a char array instead of char pointer. This brings
down the binary size from `145KiB` when using `O_NERD` down to
`137KiB`.
* Some unnecessary duplication and indirection has been reduced by using
the `ICON_STR()` macro.
reduces some unncessary code. and when initializing larger objects,
compilers (gcc and clang at least) typically tend to compile it down to
a memset anyways.
anything not explicitly initialized will be implicitly initialized to
zero. this makes things more robust since comments are not checked by
the compiler and can be incorrect.
Reasons:
1. `b` is not a special key and will be interpreted as a filter
2. with this change pressing the standard `-` inside a symlinked
bookmark takes back to the bookmarks directory. This deviates
from the regular bookmarks behaviour.
have been using the %j substitution for a bit now, it's quite nice :)
but it's also quite annoying when doing something like
mv "%j" ./
in this case, the files have been moved but the selection is incorrectly
points to them.
when there's a successful operation made on the selection via the native
prompt, it makes sense to clear the selection.
i've noticed that there's a non-trival amount of issues user face
related to preview-tui. allowing all the null redirection to be easily
switched on/off can make debugging much easier, both for the users and
for us.
The check is done when traversing directories in preorder i.e before the files
inside are enumerated. Postorder traversal is unwinding, so mostly we are done
with the calculation and finishing off the thread.
`nuke` and `preview-tabbed` works as expected. I would assume `imgview`
should work as expected as well since `nsxiv` (at the moment at least)
is a drop-in replacement for sxiv, but I haven't tested it.
Closes: https://github.com/jarun/nnn/issues/1229
this commit is mostly porting over some recent performance improvements
from `sxiv-rifle`: https://github.com/ranger/ranger/pull/2411
there's one "bug-fix" in this commit. currently a file named "afilejpeg"
would be matched due to the `-iregex` in listimages. this commit changes
that so only extensions would match, so for example "afile.jpeg" would
match but not "afilejpeg".
As for performance, there's a couple things this commit does:
* store the result of listimages into a tmp file instead of calling that
function twice, this is probably the biggest performance improvement.
especially when loading large directories.
* abspath now sets the var abs_target instead of calling printf. since
abspath is only called from load_dir, we can go one step further and
inline it. but i haven't done that since the function might be useful
later on.
* avoid call to dirname and use parameter subsitution instead inside
`listimages`
* use grep instead of `-iregex`, it's POSIX compliant and can be faster.
i've tested this out with sxiv and everything seems to be working as
expected.
we need to signal mouse event by printing these escape codes. the X10
escape code seems to be legacy format only used as fallback incase SGR
extended coordinates aren't supported.
Mainly so that pressing 'e' due to muscle memory on nnn.vim doesn't nest
a new editor instance inside the embedded vim terminal.
However invoking nnn with picker mode implies that the intention is to
pick file(s), there shouldn't be any business trying to edit things on
the fly. And if editing a file while in picker mode is desirable, then
'l' can be used for that instead.
I've extended the use of nerdfont icon for tex to other common tex extensions.
I don't know how to do the same for icons-in-terminal.
Additionally, since the list is growing I have alphabetize the list of common
icons, used in icons-nerdfont.h.
* Signal CWD change to terminal via OSC-7
Closes#1147
* Make OSC-7 emission gated by NOX11
* Use newpath variable in gethostname()
Use dynamic memory for hostname
* Branched v4.2
Added workaround for Mac OS X < 10.12.0
(Only tested on 10.11.6, lower versions may need more workaround)
* Added *.dSYM to .gitignore
* Added comments for the macosx detection in Makefile
* Fixed indentation, formatting and missing newline at eof
* Moved includes inside include guard
Co-authored-by: elder-n00b <elder-n00b@yandex.com>
I run into many premature optimizations in our codebase which are
unnecessary.
In this particular case `strlen()` is optimized at compile time even at
`-O0` with `gcc`.
I would value higher code quality than dealing with these things in our
future endeavours. If this is accepted I may supply some more
readability patches.
Most *.desktop entries have same name as their application name so this
is not an issue most of the time. However in the case of Neovim, the
application name is "Neovim" while the desktop entry is "nvim.desktop"
Since dmenu is case sensitive by default this means that searching
"neovim" will not show any results since the N is not capitalized and
the desktop entry name is "nvim"
fzf doesn't have this issue since its case-insensitive/fuzzy by
default. Making dmenu case-insensitive solves this.
Also fix the indentation to be consistent with the rest of the script.
* xdgdefault plugin: add dmenu support
use fzf if available. otherwise, if available, use dmenu.
should be possible to use rofi as well, but i don't use rofi nor do i
have it installed for testing.
* xdgdefault plugin: add GUI flag
* update xdgdefault requirement
* Add persistsel
* Fix Makefile spacing
* Update Haiku Makefile
* Do a double pass on inversion
* Split single and double pass for easier testing
Removed lastappendpos
Eliminate suffix matches
* Check if dir is in selection before searching for files
Fix double pass
* Switch to mainline
Optimize memory moving
Handle large selection in invertsel()
Going forward with 2pass
* Update Makefiles
* Fix style
* Move forward declarations
* Remove edit selection in inversion
Replace buf with g_buf to fix CI
Fix CI
* Style changes
* Comment the code
* Style fixes
* Fix infinite loop
* Fix crash on empty invert
* Fix off-by-one-in-two-places
Off-by-twice?
* Adopt changes from master
* Only check directory if entry in it is selected
* Better organization
* Wrong variable
* Tiny optimizations
* Style fixes and updated man page
* Update man page
* Remember where we found directory path in selection
Add in progress message on invert
* Refactor fifo code and add explorer
* add explorer option and flag
* notify explorer fifo on selection
* close explorer fifo file descriptor
* Try to create explorer fifo if doesn't exist
This doesn't quite work
* Allow uncreated fifos
* delete persistence fifo on cleanup
with correct formatting
Co-authored-by: luukvbaal <31730729+luukvbaal@users.noreply.github.com>
* Work correctly with NOFIFO
* Refactor variable names
* fix
* Use -X flag for explorer mode
* Update manpage with explorer mode
Co-authored-by: luukvbaal <31730729+luukvbaal@users.noreply.github.com>
- rename `wall` to `wallpaper`
- remove `upgrade` - packaging is on OBS now
- remove `treeview` - needs minor preview-tui tweak
- remove `picker` - `nnn -p -` does the same
Even if selection mode is not on, it helps to show
number of files currently selected in local buffer.
Say, after running a plugin selection mode goes off.
However, if the plugin doesn't clear the selection
buffer, the files still remain selected in buffer.
Implements pthreads based du using FTS. Currently 4 threads are used.
NFTW is dropped as there is no way to pass any custom values to fn().
FTS does not require any per entry function callback.
The performance numbers are best with FTS:
./nnn-fts -T d / 5.29s user 0.94s system 116% cpu 5.335 total
1/21 du:102.402G free:8.476G files:397644 101132550144B
./nnn-ftw -T d / 5.52s user 0.94s system 116% cpu 5.534 total
1/21 du:102.400G free:8.474G files:397653 101133148160B
./nnn-4.0 -T d / 0.20s user 2.27s system 24% cpu 10.241 total
1/21 du:102.400G free:8.475G files:397654 101133299712B
Plugins like fzopen have the capability to pick files.
This comes handy if nnn is executing as a file picker.
This is a 2-way communication:
- nnn sends the picker output file to plugin ("-" for stdout)
- the plugin tells nnn if it has overwritten the output file
If NNN_TMPFILE is exported, the selection buffer gets cleared as it is
combined with `^G` (clear picked files and exit). So even when 'q' is
pressed to quit the program the selection is lost. This was introduced
in commit d1d491c102 after release v2.7.
* More minimal bat previews, minor improvements to fzplug
* Use BAT_STYLE if set, better fzplug formatting
* Fix linebreak in single quotes
* Fix line numbers in comments
* Readability and shellcheck warning
* Fix line numbers in comments
* Breaking typo
* Pre-existing BAT_STYLE would not be honored in tmux
netbsd-curses sends a NULL (key value 0) following the KEY_RESIZE.
The keybind ^Space also issues a 0. It seems even the key ^@ sends
the same. Dropping this ambiguous keybind in favour of alternative
key m (more appropriate for 'm'ark anyway). Keys with value 0 will
now be ignored in the filter function.
* Fuzzy find plugins and run them
* Hide find warning when $otherplugins is not set
* Fix prompt on error 2
* Use /home/mathieu
* unmount-parent plugin
* Add dependencies and shell description
* Add dependencies and fix CI issue?
* Improve fzfplug prompt, fix shellcheck warnings, restore mistakenly deleted line in README
* Typo
* Make both scripts POSIX-compliant and small improvements
* Final cosmetic changes
* bis
* Clarify description
* Typo
* Typo
* Better support for custom dirs and use bat if available
Co-authored-by: M <>
Changes:
- reverse only the file name in detail view
- don't apply reverse to details, show an arrow to the left
- always show selection ('+' symbol) in bright
- delegate showing selection '+' to printent()
* Add new plugin
* Small cdpath refactoring
* Change the default CDPATH value, remove string indexing.
* Remove readlink() call to be POSIX compliant.
* Fix the comment
* plugins: cleanfilename: clean filename to be more shell-friendly
* plugins: cleanfilename: clean filename to be more shell-friendly
* plugins: cleanfilename: clean filename to be more shell-friendly
* plugins: cleanfilename: clean filename to be more shell-friendly
* plugins: cleanfilename: clean filename to be more shell-friendly
* plugins: mtpmount: toggle mount of MTP devices
* plugins: mtpmount: added some quotes
* plugins: mtpmount: toggle mount of MTP devices
* plugins: mtpmount: toggle mount of MTP devices
* plugins: mtpmount: toggle mount of MTP devices
* plugins: mtpmount: toggle mount of MTP devices
* Update preview-tui
* trap SIGWINCH
* Update preview-tui
fix CircleCI test
* fix CircleCI...
* add pdf/epub
forgot to add pdf/epub when adpating my own working script to the upstream version
* add USE tests
* add office preview
allows preview of ods, odt, docx, pptx, etc
* remove resize trap, show static gif
Removed the faulty resize code and show static gif when USE_GIFPREVIEW is not set.
* loop gif playback
* refactor imagepreview
* scale kitty preview
* fix ueberzug_remove regression
* add optional atool support
* single depth, colorized tree preview
also empty pager prompt
* atool optional
* window resize working
* USE_UEBERZUG check
* conditional trap
I can't fully explain the behavior I'm seeing but this seems to work as its supposed to.
* adopt TMPDIR
* prevent extra readline after window resize
* shellcheck fix
* clear preview pane after resize
prevents (seemingly random) pager previews from showing after resize
* fix stray fifo from subshells
* add preview-tui-ext
If you have selected some files, you intend to work on them. Also, this prompt
expects <kbd>c</kbd> / <kbd>s</kbd> which should cancel the next prompt in the
delete workflow. Rest of the three workflows are non-fatal.
Benefits of removing this option:
- code reduction
- one less step in the relevant workflows (more than one prompt feels dragged)
This prompt shows in the following workflows:
- delete: users have explicitly requested to prefer sel over current
- batch rename: key <kbd>^R</kbd> renames a single file
- archive: in most of the cases the user would want to archive the selection
- create sym/hard link: not a frequently used workflow (in general)
If an input stream is available, prioritize that over sessions. find/grep
syntax can be very complex and can be scripted. On the contrary, sessions
can be loaded at runtime and the persistent session can be "restored".
An interesting use case is the listing is done in picker mode from a script
and the user expects to "pick" some entries among the listed search results.
Another important change is - if the user tries to load the "last session"
explicitly by name instead of using the session option _restore_, we should
not overwrite the "last session" ("@") before loading the it.
* Add support for Alexey Tourbin's QSORT code
See https://github.com/svpv/qsort
* Add benchmark scripts and compilation mode
Compile with `make O_BENCHMARK=1`, and run benchmarks with e.g.:
./misc/test/benchmark.sh ./nnn '/' '/usr/bin' '/usr/lib' > benchdata
You can then plot basic violin graphs with:
./misc/test/plot-bench.py benchdata
* Update style, doc, haiku support, fix lint
* Haiku: Some small fixes to the recipe and resource file
Whoops...just some small fixes.
* Update nnn.rdef
Co-authored-by: Jana <engineerarun@gmail.com>
* nuke: use macOS open when GUI enabled
* nuke: use is_mac function to test for macOS
This is consistent with how the imgur plugin does detection.
* Add macOS open command to plugins
* pskill: only execute if input is non-empty
* Add icons
* Fix build break
* Fix icon position in detailed mode
* Various fixes
* Provision for icon specific colors
No icons with oldcolor. Small optimizatons
* Update Makefiles
Small refinement for other matching
- Add a native vector icon for Haiku (it hasn't been Haiku-ified yet however)
- Add a rdef file (specifies application metadata)
- Add clipboard support, notififcation support, and basic nuke support
- Fix support for fortunes on Haiku ("-s" option is not available on Haiku)
- Cleanup Haiku recipe
Without this, there is a conflict with using the `-u` option (use selection).
After copying selected files, the selection is intact and if the user issues
a deletion next, the source files (meant for copying) are deleted.
* Allow absolute paths returned by fzf in fzcd plugin
* Fix issue with POSIX syntax
* Add descriptive comment
* Add comment
* Remove description
* Add new line at the end of the file
Co-authored-by: Jan Meischner <jan.meischner@verimi.com>
If char is unsigned (as on ARM) subtracting a larger number would
result in a wrap around, not a negative value.
src/nnn.c: In function 'readpipe':
src/nnn.c:4325:11: warning: comparison is always false due to limited
range of data type [-Wtype-limits]
if (ctx < 0 || ctx > CTX_MAX)
^
Fixes the build on NetBSD 9 on arm64.
GCC expands alloca() to __builtin_alloca() but only in nonstandard mode,
e.g. when -std=... is not supplied. In standards mode (with -std=...)
alloca() is left undefined by GCC. The C library may define it but it
also may not, as on NetBSD on arm64:
$ uname -srp
NetBSD 9.0 aarch64
$ cat alloca.c
#include <stdlib.h>
int main() { char *p = alloca(10); }
$ gcc alloca.c
$ gcc -std=c99 alloca.c
alloca.c:(.text+0xc): warning: Warning: reference to the libc
supplied alloca(3); this most likely will not work. Please use the
compiler provided version of alloca(3), by supplying the
appropriate compiler flags (e.g. not -std=c89).
ld: alloca.c:(.text+0xc): undefined reference to `alloca'
The fix is to either not use standards mode (undesirable) or to
explicitly use the builtin, which is what this patch does.
This is also sufficient for Solarius/Illumos so that check and include
are removed.
Selection is cleared after successful:
- file removal
- batch rename
- link creation
However, selection is not cleared after:
- archive creation: user may want to delete the files after archiving
Both Pistol and `scope.sh` are run `file --mimetype` or an equivalent, internally.
Thus, for speed, it's better to run them before almost anything else.
* Unified preview-tui and preview-kitty
* Remove preview-kitty
* No need to set $TERMINAL
* fix undeclared variable
* Integrated support for scope.sh
* Review fixes
* allow_remote_control must be enabled on kitty
* Documentation, kitty splits and images fallback
* fix restoring kitty layout
* preview-tui: simplify, add generic fifo_pager()
I've commented new filetype checks for now, as we need to discuss which ones
should be included by default, keeping in mind that this is supposed to be a
minimal, adaptable plugin.
* preview-tui: preview with man, tar, unzip by default
This supports using a power of 2 number of contexts like 2, 4 or 8.
Note that the number of contexts are not backward compatible. So if
user is having 8 contexts and plans to use 4, his sessions with > 1
contexts open may break.
We can have a make option to enable 8 contexts. 4 remains default.
It's a little annoying that one has to press ^L followed by Esc to go back
to the normal view. We cannot reload the directory on Esc because that will
break the filter filtered view feature. So we take this route.
* Add -a option to generate a temporary NNN_FIFO
* Add documentation for -a option
* plugins/README.md: promote the use of -a
This obsoletes the global FIFO unlink trick, so I remove mentions of it.
@jarun update:
Polish -a
* Allow launching plugins with Alt + plugin's key
* Fix Alt key in filter/prompts modes
* Fix handling Alt key in nextsel()
In filter mode: run the associated plugin.
In prompt mode: just throw out the Alt+key input.
In nextsel(): differentiate Alt+key and Esc
* Add a tabbed/xembed based file previewer plugin
This plugin is written in bash, because job control is not well
specified in POSIX sh (`jobs` can return anything).
We use `tabbed` [1] as a xembed [2] host, to have a single window
owning each previewer window.
Uses mpv, sxiv, zathura, and the nuke plugin.
[1]: http://tools.suckless.org/tabbed/
[2]: https://specifications.freedesktop.org/xembed-spec/xembed-spec-latest.html
* tabbed-preview: prevent focus steal with xdotool
* preview-tabbed: tabs->4 spaces
* preview-tabbed: add focus prevention timeout
* Add an option to print hovered files to a FIFO
This adds an env variable, `NNN_FIFO`, that can be set to a path that
`nnn` will open/create as a FIFO, and where every hovered file's path is
printed. This allows creating external perview/quick open plugins, ...
It can be compiled out with the make variable `O_NOFIFO`.
* Check filename ptr instead of full path (for FIFO)
* Add documentation to use NNN_FIFO in plugins
* Fix path sent to FIFO in empty dirs
The current code will start editor if the mime doesn't start with
"text/". But, we want the opposite.
Simplify the check by using `strncmp` instead.
We may improve by writing a helper: `start_withs` in the future.
This change also cleans -Wstrict-aliasing on Ubuntu 16.04 LTS
Support `$_Z_DATA` environment variable per z's documentation dcd5541e7d/z.1 (L78).
`$_Z_DATA` allows changing the default location of the z database file.
* Add nvim as a diff tool for getplugs plugin
* Comment out `is_cmd_exists()`
* Add nvim diff tool for diffs plugin
* Add $EDITOR to nuke plugin for editing/reading text file format
* Modify diff command to fix CircleCI failures
* Fix getplugs prompt
* Allow nuke to use custom $PAGER
* Unvectorize xstrlcpy
On all libcs I could find, memcpy does a better job than we can.
* Rename xstrlcpy to xstrsncpy to avoid confusion
The semantics of our xstrlcpy differed slightly from strlcpy; we return
the number of copied characters; strlcpy returns the strlen(src).
strscpy from Linux is similar except it returns the number of copied
characters sans the NUL byte, so this is named strsncpy to be different.
* Added fzfz plugin
* Fixed shellcheck errors
* Fixed copy/paste error
* Added support for fzy, also renamed plugin since it's not specific to fzf anymore
* Refactored code
* Clean spillovers (jarun)
* Add middle click copy
* Make middle click action configurable
This introduces the NNN_MIDDLECLICK environment variable, containing the
key that middle mouse click emulates. Only the first character is read.
* Document NNN_MIDDLECLICK in nnn.1
* Use NNN_MCLICK instead of NNN_MIDDLECLICK
* Add '^key' syntax to set middle click to Ctrl+Key
The previous implementation was inconsistent, sometimes it would
inherit the name of the parent folder of the current directory.
Other scenarios i encountered were:
1. Yield a empty search result, and try to edit. It would seemingly
randomly select a file or folder
2. What would happen in a root path without any files residing?
* Start implementation on show list of files as input
* Remove tmp dir on exit, set global flag
* Bug fixes and improvements
* Follow symlinks when in list paths mode
* Fix bugs
* Add flag check
* Add message for invalid paths and style fixes
* Change the message
* Addressing review comments
* Handle errno being set
* Fix CI break
* Decreased startup memory usage and removed loops
* Fix CI break
The NNN_PIPE file gets deleted after spawning a child in NOWAIT mode. Steps:
- open `nnn` with option `-x`
- press `;o` (custom binding) to open fzopen plugin
- press `^J` to select a file; it will spawn plugin `.cbcp` in NOWAIT mode
- when the intermediate child quits, the NNN_PIPE of parent is also deleted
The following changes are made:
- STDOUT and STDIN are redirected to /dev/null when spawning rclone
rclone blocks and also shows error/warning messages. nnn needs to spawn
rclone and return without waiting. To avoid the rclone messages from
corrupting the screen nnn makes the child silent.
Note: sshfs returns after mount with a proper error code
- prompt only if both sshfs and rclone are installed
* Fallbacks for absent NAME_MAX and PATH_MAX
Certainly NAME_MAX isn't guaranteed to exist and on (some versions of?)
Illumos and SmartOS it doesn't, so provide some reasonably accommodating
fallbacks.
* Smaller limits
* Remove now redundant PATH_MAX definition for Hurd
* Quit with an error code
* Use `Q` as "quit with err"
* Remove extra var and simplify conditions
* Revert combining conditions
* Fix formatting
* Format help with as much tabs as possible
* Don't pack sources (github does it better), sign sources
* Make CircleCI generate the same git archive as Github, return make dist
* Revert make clean too
* Upload signature to Github release
* Read Github token from an env variable
- replace bools for internal non-persistent binary states with an uchar
- do not store path to session, derive from config path in tmp buffer
- program option to load session is not `-s`
- remove auto-stored session "@" on restore
- minor help update
- reduce 4 spaces between help columns as it's too wide for handhelds
- support `]` as prompt in nav-as-you-type-mode when filter is empty
- update plugin docs
* Cleanup unused MSG_
* Print only plugin keys
* Speed up preparing keys prompt
* Show prompt for bookmarks
* Don't error when user interactively pressed non-existent bookmark key
Update the selection buffer and file in-place:
- Append file path when one is added.
- Remember the last position in selection buffer at which the next filename
is to be appended when a directory/context change happens (lastappendpos).
So in case of a de-selection we can go back to that position and scan all
the entries to add only the ones which are selected.
Please provide the environment details. **If that's missing, the issue will be closed without any cited reason.**
If we need more information and there is no communication from the bug reporter within 7 days from the date of request, we will close the issue. If you have relevant information, resume discussion any time.
#### FEATURE REQUESTS
Please consider contributing the feature back to `nnn` yourself. Feel free to discuss in the ToDo list thread. We are more than happy to help.
--- PLEASE DELETE THIS LINE AND EVERYTHING ABOVE ---
#### Environment details (Put `x` in the checkbox along with the information)
`nnn` comes with excellent documentation (including a Troubleshooting section). If you have a _How to do x_ question, it may have already been answered. Wiki: https://github.com/jarun/nnn/wiki
If it looks like a local environment issue, please try to debug yourself. Debugging local setup issues is not our top priority.
If you are looking for a new feature or program option, ensure you have the correct version with the feature installed. Refer to the release notes to confirm.
Before opening an issue, please try to reproduce on latest master. The bug you noticed might have already been fixed.
Useful links:
- compile `nnn` from source - https://github.com/jarun/nnn/wiki/Usage#from-source
Please provide the environment details. **If that's missing, the issue will be closed without any cited reason.**
If we need more information and there is no communication from the bug reporter within 7 days from the date of request, we will close the issue. If you have relevant information, resume discussion any time.
--- PLEASE DELETE THIS LINE AND EVERYTHING ABOVE ---
#### Environment details (Put `x` in the checkbox along with the information)
# Access more recent gcc and clang via a Xenial image
#- os: linux
# dist: trusty
# compiler: gcc
#- os: linux
# dist: trusty
# compiler: clang
- os:osx
compiler:gcc
- os:osx
compiler:clang
install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then if [[ "$CC" == "clang" ]]; then brew update; brew install llvm; export PATH="/usr/local/opt/llvm/bin:$PATH"; fi; fi
script:
- export CFLAGS=-Werror;
- make clean; make;
- make clean;
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then if [[ "$CC" == "clang" ]]; then clang-tidy src/* -- -I/usr/include; fi; fi
- remove mount point on successful unmount of remote/archive
- show error and prompt user if `cp`/`mv`/`rm` operation fails
- support absolute/relative paths in cp/mv as
- mark current path automatically on archive/remote mount
- mark current path automatically on target file visit in _find and list_ mode
- option `-C` to place HW cursor on hovered for screen readers and braille displays
- option `-u` to use selection (if available) and skip `current/sel` prompt
- key <kbd>Alt+Esc</kbd> to clear filter prompt and redraw
- support <kbd>Esc</kbd> to cancel remove operation
- `gpge` & `gpgd`: encrypt and decrypt with GPG
- `blknew`: create new files and directories in bulk
- `preview-tui`
- unified to support `tmux`/`kitty`/`xterm`/`$TERMINAL`
- auto-determine split orientation based on terminal height and width
- provision to use [`scope.sh`](https://github.com/ranger/ranger/blob/master/ranger/data/scope.sh) and [`pistol`](https://github.com/doronbehar/pistol)
- various other improvements
- `upload`: send to Firefox Send if [`ffsend`](https://github.com/timvisee/ffsend) is found
- `hexview`: add [`hx`](https://github.com/krpors/hx) as alternative hex viewer
- `nuke` and `imgview`: add [`imv`](https://github.com/eXeC64/imv) as alternative image viewer
- add find (with `fd`) and grep (with `rg`) examples in plugins doc
- key <kbd>Esc</kbd> or left click to resend hovered file path to `NNN_FIFO`
- show `+` instead of `s` in status bar on selection
`nnn` is a full-featured terminal file manager. It's tiny and nearly 0-config with an [incredible performance](https://github.com/jarun/nnn/wiki/Performance).
`nnn`(_n³_) is a full-featured terminal file manager. It's tiny, nearly 0-config and [incredibly fast](https://github.com/jarun/nnn/wiki/Performance).
`nnn` is also a du analyzer, a fuzzy app launcher, a batch renamer and a file picker. The [plugin repository](https://github.com/jarun/nnn/tree/master/plugins#nnn-plugins) has tons of plugins and documentation to extend the capabilities further. You can _plug_ new functionality _and play_ with a custom keybind instantly. There's an independent [(neo)vim plugin](https://github.com/mcchrish/nnn.vim).
It is designed to be unobtrusive with smart workflows to match the trains of thought.
It runs smoothly on the Raspberry Pi, Termux [on Android](https://www.youtube.com/watch?v=AbaauM7gUJw), Linux, macOS, BSD, Cygwin, WSL and works seamlessly with DEs and GUI utilities.
`nnn` can analyze disk usage, batch rename, launch apps and pick files. The plugin repository has tons of plugins to extend the capabilities further e.g. [live previews](https://github.com/jarun/nnn/wiki/Live-previews), (un)mount disks, find & list, file/dir diff, upload files. A [patch framework](https://github.com/jarun/nnn/tree/master/patches) hosts sizable user-submitted patches which are subjective in nature.
Add to that an awesome [Wiki](https://github.com/jarun/nnn/wiki)!
*Love smart and efficient utilities? Explore [my repositories](https://github.com/jarun?tab=repositories). Buy me a cup of coffee if they help you.*
Runs on the Pi, [Termux](https://www.youtube.com/embed/AbaauM7gUJw) (Android), Linux, macOS, BSD, Haiku, Cygwin, WSL, across DEs or a strictly CLI env.
<palign="center">
<ahref="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=RMLTQ76JSXJ4Q"><imgsrc="https://img.shields.io/badge/PayPal-donate-1eb0fc.svg"alt="Donate via PayPal!"/></a>
- Dir updates, notification on `cp`, `mv`, `rm` completion
- Copy file paths to system clipboard on select
- Launch apps, run commands, spawn a shell, toggle exe
- Access context paths/files at prompt or spawned shell
- Lock terminal after configurable idle timeout
- Capture and show output of a program in help screen
- Basic support for screen readers and braille displays
## Quickstart
1. Install the [utilities you may need](https://github.com/jarun/nnn#utility-dependencies) based on your regular workflows.
2. Configure [cd on quit](https://github.com/jarun/nnn/wiki/Basic-use-cases#configure-cd-on-quit).
3. Optionally open all text files in `$EDITOR` (fallback vi): `export NNN_USE_EDITOR=1`.
4. For additional functionality [install plugins](https://github.com/jarun/nnn/tree/master/plugins#installing-plugins) and the GUI app launcher [`nlaunch`](https://github.com/jarun/nnn/tree/master/misc/nlaunch).
1. [Install](https://github.com/jarun/nnn/wiki/Usage) `nnn` and the dependencies you need.
2. The desktop opener is default. Use `-e` to open text files in the terminal. Optionally [open detached](https://github.com/jarun/nnn/wiki/Basic-use-cases#detached-text).
3. Configure [`cd` on quit](https://github.com/jarun/nnn/wiki/Basic-use-cases#configure-cd-on-quit).
4. [Sync subshell `$PWD`](https://github.com/jarun/nnn/wiki/Basic-use-cases#sync-subshell-pwd) to `nnn`.
6. Use `-x` to sync selection to clipboard, show notis on `cp`, `mv`, `rm` and set xterm title.
7. For a CLI-only environment, set [`NNN_OPENER`](https://github.com/jarun/nnn/wiki/Usage#configuration) to [`nuke`](https://github.com/jarun/nnn/blob/master/plugins/nuke). Use option `-c`.
9. Visit the [Live previews](https://github.com/jarun/nnn/wiki/Live-previews) and [Troubleshooting](https://github.com/jarun/nnn/wiki/Troubleshooting) Wiki pages.
1. Don't memorize keys. Arrows, <kbd>/</kbd> and <kbd>q</kbd> suffice. Press <kbd>?</kbd> for help on keyboard shortcuts anytime.
2. To set `nnn` as the default file manager, follow these [instructions](https://github.com/jarun/nnn/wiki/Advanced-use-cases#configure-as-default-fm).
Packages for Arch Linux, CentOS, Debian, Fedora and Ubuntu are auto-generated with the [latest stable release](https://github.com/jarun/nnn/releases/latest).
#### From source
Download the latest stable release or clone this repository (*risky*), install deps and compile. On Ubuntu 18.04:
| `NNN_TRASH=1` | trash files to the desktop Trash [default: delete] |
#### Cmdline options
```
usage: nnn [OPTIONS] [PATH]
The missing terminal file manager for X.
positional args:
PATH start dir [default: .]
optional args:
-a use access time
-b key open bookmark key
-c cli-only opener
-d detail mode
-e name load session by name
-E use EDITOR for undetached edits
-f run filter as cmd on prompt key
-H show hidden files
-i nav-as-you-type mode
-K detect key collision
-n version sort
-o open files on Enter
-p file selection file [stdout if '-']
-r use advcpmv patched cp, mv
-R disable rollover at edges
-s string filters [default: regex]
-S du mode
-t disable dir auto-select
-v show version
-h show help
```
#### Keyboard and mouse
The list below is from the **dev branch**. Press <kbd>?</kbd> in `nnn` to see the keybinds in your installed version.
```
NAVIGATION
Up k Up PgUp ^U Scroll up
Down j Down PgDn ^D Scroll down
Left h Parent ~ ` @ - HOME, /, start, last
Ret Right l Open . Toggle show hidden
g ^A First entry G ^E Last entry
b Pin current dir ^B Go to pinned dir
(Sh)Tab Cycle context d Toggle detail view
, ^/ Lead key N LeadN Context N
/ Filter/Lead Ins ^N Toggle nav-as-you-type
Esc Exit prompt ^L F5 Redraw/clear prompt
? Help, conf ' Lead' First file
Q ^Q Quit ^G QuitCD q Quit context
FILES
^O Open with... n Create new/link
D File details ^R F2 Rename/duplicate
Space ^J/a Sel toggle/all r Batch rename
m ^K Sel range, clear M List selection
P Copy selection K Edit, flush sel
V Move selection w Copy/move sel as
X Del selection ^X Del entry
f Create archive T Mount archive
^F Extract archive F List archive
e Edit in EDITOR p Open in PAGER
ORDER TOGGLES
A Apparent du S du
z Size E Extn t Time
MISC
! ^] Shell ;K :K xK Execute plugin K
C Execute entry R ^V Pick plugin
U Manage session = Launch
c Remote mount u Unmount
] ^P Prompt/run cmd L Lock
```
Notes:
1. Help & settings, file details and archive listing are shown in the `$PAGER`.
2. To change shortcuts modify key bindings in `nnn.h` and compile.
| Mouse click | Function |
|---| --- |
| Left single on context number | Visit context |
| Left single on top row after context numbers | Visit parent |
| Left single/double on last 2 rows | Toggle nav-as-you-type |
| Left single | Select context or entry |
| Left double | Select context or open entry |
#### Lead key
The Lead/Leader key provides a powerful multi-functional navigation mechanism. It is case-sensitive and understands contexts, bookmarks and location shortcuts.
| Follower key | Function |
|:---:| --- |
| <kbd>1-4</kbd> | Go to/create selected context |
| key | Go to bookmarked location |
| <kbd>'</kbd> | Go to first file in directory |
| <kbd>~</kbd><kbd>`</kbd><kbd>@</kbd><kbd>-</kbd> | Visit HOME, `/`, start, last visited dir |
| <kbd>.</kbd> | Toggle show hidden files |
When the filter is on, <kbd>/</kbd> works as an additional Lead key.
#### Help
$ nnn -h
$ man nnn
To lookup keyboard shortcuts at runtime, press <kbd>?</kbd>.
- [nnn file manager on Termux (Android)](https://www.youtube.com/embed/AbaauM7gUJw)
`nnn` is actively developed. Visit the to the [ToDo list](https://github.com/jarun/nnn/issues/386) to contribute or see the features in progress.
Visit the [Tracker](https://github.com/jarun/nnn/issues/1546) thread for a list of features in progress and anything up for grabs. Feel free to [discuss](https://github.com/jarun/nnn/discussions) new ideas or enhancement requests.
Contributions to nnn are welcome! There's always an open issue with the current ToDo list, which contains the proposed features for the next release you can get your hands on. Any small changes or ideas should go in there, rather than in a separate issue.
Before suggesting changes, please read a bit about [the design principles nnn follows](https://github.com/jarun/nnn/wiki/concepts#design), and make sure you aren't breaking any of them.
Feel free to join the [Discussions](https://github.com/jarun/nnn/discussions). We highly recommended a discussion before raising a PR.
## Coding standard
`nnn` follows the Linux kernel coding style closely. The C source code uses TABs and the plugins use 4 spaces for indentation.
- Code changes should not break the patch framework. Please run `make checkpatches` to ensure.
- Run `make shellcheck` if adding/modifying plugins.
CI runs patch framework sanity test and `shellcheck`. Please watch out for any failures after raising the PR.
## Resources
The [wiki](https://github.com/jarun/nnn/wiki/Developer-guides) has some resources for developers you might be interested in: building, debugging...
## Communication
* [Gitter chat](https://gitter.im/jarun/nnn)
* [GitHub team](https://github.com/nnn-devs) (if you plan on contributing regularly, ask for an invitation).
`nlaunch` is an independent POSIX-compliant GUI application launcher shell script. To use it with `nnn` you need to mark the file executable and drop it somewhere in your `$PATH`.
It requires [`fzy`](https://github.com/jhawthorn/fzy) to show a fuzzy drop-down menu.
To use `nlaunch` as an independent launcher add a keybind to open `nlaunch` in a terminal e.g.
- simple to modify (extensive in-file notes, comments and indicative code)
- handle files by category (e.g. plaintext, search, screensaver)
- support for multiple apps by order of preference
- run app in the foreground or silently detached in the background
- optionally add app arguments
### Tips to modify
- set `app=` in any category to change the player
- set `opts=` to use app options
- toggle `bg=` to enable or disable running app silently (`stdout` and `stderr` redirected to `/dev/null`) in background. E.g., vim (CLI) should be verbose and in the foreground while Sublime Text (GUI) can be started silently in the background.
- enable the commented out code under `ENABLE_FILE_TYPE_HANDLING` to handle specific file extensions e.g. use a different app than the one used for the category.
is shipped with \fInnn\fR to deliver a level of flexibility to users to choose their own apps when running some actions, run some commands or custom scripts. It has provisions to handle text files too. However, the capability is not used in the latest releases. Now
.Nm
is invoked to run a desktop search (\fIgnome-search-tool\fR or \fIcatfish\fR) or screen locker (\fIvlock\fR or \fIbashlock\fR or \fIlock\fR) utility. However,
.Nm
can run independently and can be highly customized for personal usage.
.Pp
.Nm
supports the following options:
.Pp
"file/path"
The first argument can be the file or path to pass as an argument to the app. It can also be an empty string e.g., while locking the terminal.
.Pp
"type/action"
This can be any of the strings \fItext\fR, \fIsearch\fR, \fIscript\fR or \fIlocker\fR.
(Nnn's Not Noice) is a performance-optimized, feature-packed fork of noice (http://git.2f30.org/noice/) with seamless desktop integration, simplified navigation, \fInavigate-as-you-type\fR mode with auto select, disk usage analyzer mode, bookmarks, contexts, application launcher, familiar navigation shortcuts, subshell spawning and much more. It remains a simple and efficient file manager that stays out of your way.
.PqNnn'sNotNoice
is a performance-optimized, feature-packed fork of noice
.Emhttp://git.2f30.org/noice/
with seamless desktop integration, simplified navigation,
.Emtype-to-nav
mode with dir auto-enter, disk usage analyzer mode, bookmarks,
use selection if available, don't prompt to choose between selection and hovered entry
.Pp
.FlU
show user and group names in status bar
.Pp
.FlV
show version and exit
.Pp
.Flx
show notifications on selection cp, mv, rm completion (requires \fI.ntfy\fR plugin)
copy path to system clipboard on selection (requires \fI.cbcp\fR plugin)
show xterm title (if non-picker mode)
.Pp
.Flh
show program help and exit
.ShCONFIGURATION
.Nm
uses \fIxdg-open\fR (on Linux) and \fIopen(1)\fR (on macOS) as the desktop opener.
There is no configuration file. Associated files are at
.Pp
There is no configuration file. Associated files are stored in \fB${XDG_CONFIG_HOME:-$HOME/.config}/nnn/\fR. Settings work on environment variables. See ENVIRONMENT section below.
.Pa${XDG_CONFIG_HOME:-$HOME/.config}/nnn/
.Pp
Configuration is done using a few optional (set if you need) environment
variables. See ENVIRONMENT section.
.Pp
.Nm
uses \fIxdg-open\fR (on Linux), \fIopen(1)\fR (on macOS), \fIcygstart\fR on
(Cygwin) and \fIopen\fR on (Haiku) as the desktop opener. It's also possible
to specify a custom opener. See ENVIRONMENT section.
.ShCONTEXTS
Contexts serve the purpose of exploring multiple directories simultaneously. 4 contexts
are available. The status of the contexts are shown in the top left corner:
Open multiple locations with 4 contexts. The status is shown in the top left
corner:
.Pp
- the current context is in reverse video
.br
@ -117,137 +189,428 @@ are available. The status of the contexts are shown in the top left corner:
.br
- rest are inactive
.Pp
On context creation, the state of the previous context is copied. Each context remembers its last visited directory.
.Pp
Each context can have its own directory color specified. See ENVIRONMENT section below.
A new context copies the state of the previous context. Each context can have
its own color. See ENVIRONMENT section.
.ShSESSIONS
Sessions are a way to save and restore states of work. A session stores the settings and contexts.
Sessions are a way to save and restore states of work. A session stores the
settings and contexts. Sessions can be loaded at runtime or with a program
option.
.Pp
Sessions can be loaded dynamically from within a running
.Nm
instance, or with a program option.
- When a session is loaded at runtime, the last working state is saved
automatically to a dedicated "auto session" session file. Session option
\fIrestore\fR would restore the "auto session".
.br
- The persistent session option is global. If it is used, the last active session
will be updated with the final state at program quit.
.br
- The "auto session" is used in persistent session mode if no session is active.
.br
- Listing input stream and opening a bookmark by key have a higher priority to
session options (-s/-S).
.Pp
When a session is loaded dynamically, the last working session is saved automatically to a dedicated
-- "last session" -- session file.
All the session files are located by session name in the directory
.Pp
All the session files are located in the \fB${XDG_CONFIG_HOME:-$HOME/.config}/nnn/sessions\fR directory by the session name.
(1) To list all matches starting with the filter expression, start the expression
with a '^' (caret) symbol.
Special keys at \fBempty filter prompt\fR:
.Bd-literal
------ + ---------------------------------------
Key | Function
------ + ---------------------------------------
? | Show help and config screen
/ | Toggle between string and regex
: | Toggle case-sensitivity
^L | Clear filter (\fIif prompt is non-empty\fR)
| OR apply last filter
Bksp | Stay at filter prompt and refresh dir
Del | Stay at filter prompt and refresh dir
------ + ---------------------------------------
.Ed
.Pp
Common regex use cases:
.Pp
(1) To list all matches starting with the filter expression,
start the expression with a '^' (caret) symbol.
.br
(2) Type '\\.mkv' to list all MKV files.
.br
(3) Use '.*' to match any character (\fIsort of\fR fuzzy search).
.Pp
There is a program option to filter entries by substring match instead of regex.
.Pp
There is a program option to execute the current filter as a command when the prompt key is pressed.
.Pp
In the \fInavigate-as-you-type\fR mode directories are opened in filter mode,
allowing continuous navigation. Works best with the \fBarrow keys\fR.
.br
When there's a unique match and it's a directory,
.Nm
auto selects the directory and enters it in this mode.
.ShSELECTION
There are 3 groups of shortcuts to add files to selection:
(4) Exclude filenames having 'nnn' (compiled with PCRE lib): '^(?!nnn)'
.Pp
(1) hovered file selection toggle (deselects if '+' is visible before the entry, else adds to selection)
In the \fBtype-to-nav\fR mode directories are opened in filter
mode, allowing continuous navigation.
.Pp
Additional special keys at \fBempty filter prompt\fR
in \fBtype-to-nav\fR mode:
.Bd-literal
------ + ------------------------
Key | Function
------ + ------------------------
' | Go to first non-dir file
+ | Toggle file selection
, | Mark CWD
- | Go to last visited dir
. | Show hidden files
; | Run a plugin by its key
= | Launch a GUI application
> | Export file list
@ | Visit start dir
] | Show command prompt
` | Visit /
~ | Go HOME
------ + ------------------------
.Ed
.ShSELECTION
.Nm
allows file selection across directories and contexts!
.Pp
There are 3 groups of keybinds to add files to selection:
.Pp
(1) hovered file selection toggle
- deselects if '+' is visible before the entry, else adds to selection
.br
(2) add a range of files to selection
- repeat the range key on the same entry twice to clear selection completely
.br
(3) add all files in the current directory to selection
.Pp
The selection can now be listed, copied, moved, removed, archived or linked.
A selection can be edited, copied, moved, removed, archived or linked.
.Pp
Absolute paths of the selected files are copied to the temporary file \fB.selection\fR in the config directory. The path is shown in the help and configuration screen. If \fB$NNN_COPIER\fR is set (see ENVIRONMENT section below) the file paths are also copied to the system clipboard.
Absolute paths of the selected files are copied to \fB.selection\fR file in
the config directory. The selection file is shared between multiple program
instances. Selection from multiple instances are not merged. The last instance
writing to the file overwrites earlier contents. If you have 2 instances of
.Nm
\fIopen\fR in 2 panes of a terminal multiplexer, you can select in one pane and
use the selection in the other pane. The selection gets cleared in the
.Nm
instance where the selection was made on mv/rm (but not on cp).
.Pp
To flush the selection without running any operation use the _edit, flush selection_ key. The list is flushed even if unchanged. Use this key to remove a file from selection after you navigate away from its directory. Flushing doesn't end the selection mode. You can add more files to the selection and edit/flush the list again. Flushing doesn't end the selection mode. You can add more files to the selection and edit/flush the list again.
.Nm
clears the selection after a successful operation with the selection. Plugins
are allowed to define the behaviour individually.
.Pp
Repeat range selection on the same entry twice to clear selection completely.
.ShFILESIZE
The minimum file size unit is byte (B). The rest are K, M, G, T, P, E, Z, Y (powers of 1024), same as the default units in \fIls\fR.
To edit the selection use the _edit selection_ key. Editing doesn't end the
selection mode. You can add more files to the selection and edit the list
again. If no file is selected in the current session, this option attempts
to list the selection file.
.Pp
.Nm
can show the total size of non-filtered selected files listed in a
directory. For directories, only the size of the directory is added by
default. To add the size of the contents of a directory, switch to du mode.
.ShFINDANDLIST
There are two ways to search and list:
.Pp
- feed a list of file paths as input
.br
- search using a plugin (e.g. \fIfinder\fR) and list the results
.Pp
File paths must be NUL-separated ('\\0'). Paths and can be relative to the
current directory or absolute. Invalid paths in the input are ignored. Input
processing limit is 16,384 paths or 64 MiB (max_paths x max_path_len) of data.
.Pp
To list the input stream, start
.Nm
by writing to its standard input. E.g., to list files in current
directory larger than
1M:
.Bd-literal
find -maxdepth 1 -size +1M -print0 | nnn
.Ed
.Pp
or redirect a list from a file:
.Bd-literal
nnn < files.txt
.Ed
.Pp
Handy bash/zsh shell function to list files by mime-type in current directory:
This directory contains sizable user submitted patches that were rejected from mainline as they tend to be more subjective in nature.
The patches will be adapted on each release when necessary (v4.1 onwards). Each patch can be applied through its respective make variable during compilation. In case inter-patch merge conflicts occur, a compatibility patch is provided and will automatically be applied.
| gitstatus | Add git status column to the detail view. Provides command line flag `-G` to show column in normal mode. | `O_GITSTATUS` |
| namefirst | Print filenames first in the detail view. Print user/group columns when a directory contains different users/groups. | `O_NAMEFIRST` |
| restorepreview | Add pipe to close and restore [`preview-tui`](https://github.com/jarun/nnn/blob/master/plugins/preview-tui) for internal undetached edits (<kbd>e</kbd> key)| `O_RESTOREPREVIEW` |
To apply a patch, use the corresponding make variable, e.g.:
make O_NAMEFIRST=1
When contributing/adding a new patch, make sure to add the make variable to the patches array in `./misc/test/check-patches.sh` as well so that patch failures can be easily tested.
## Resolving patch conflicts
Patch conflicts can be checked locally by running `make checkpatches` or by running `./patches/check-patches.sh` manually.
Whenever patch conflicts occur on the latest master, pull requests resolving them are welcome. Let's say a conflict occurs in the `restorepreview` patch. The best way to resolve this conflict would be something along the lines of:
- Ensure you're on latest master and run `PATCH_OPTS="--merge" make O_RESTOREPREVIEW=1`. This will generate the conflict markers in `src/nnn.c`.
- Next edit `src/nnn.c`, resolve the conflicts around the conflict markers(`<<<<<<<`), and save.
- Then run `git diff > patch.diff && sed -i -e "/^$/{r patch.diff" -e "q;}" patches/restorepreview/mainline.diff` to update the patch.
<palign="center"><i>image preview with plugin imgthumb</i></p>
## Introduction
Plugins extend the capabilities of `nnn`. They are _executable_ scripts (or binaries) which `nnn` can communicate with and trigger. This mechanism fits perfectly with the fundamental design to keep the core file manager lean and fast, by delegating repetitive (but not necessarily file manager-specific) tasks to the plugins.
Plugins extend the capabilities of `nnn`. They are _executable_ scripts (or binaries) `nnn` can communicate with and trigger. This mechanism fits perfectly with the fundamental design to keep the core file manager lean and fast, by delegating repetitive (but not necessarily file manager-specific) tasks to the plugins which can be run with custom hotkeys.
`nnn` is _**language-agnostic**_ when it comes to plugins. You can write a plugin in any (scripting) language you are comfortable in!
| exetoggle | Toggle executable status of hovered file | sh | chmod |
| fzcd | Change to the directory of a fuzzy-selected file/dir | sh | fzy/fzf<br>(optional fd) |
| fzhist | Fuzzy-select a cmd from history, edit in `$EDITOR` and run | sh | fzy |
| fzopen | Fuzzy find a file in dir subtree and edit or open | sh | fzy, xdg-open |
| getplugs | Update plugins | sh | curl |
| gutenread | Browse, download, read from Project Gutenberg | sh | curl, unzip, w3m<br>[epr](https://github.com/wustho/epr) (optional) |
| hexview | View a file in hex in `$PAGER` | sh | xxd |
| imgresize | Resize images in dir to screen resolution | sh | [imgp](https://github.com/jarun/imgp) |
| imgsxiv | Browse images, set wallpaper, copy path ([config](https://wiki.archlinux.org/index.php/Sxiv#Assigning_keyboard_shortcuts)), [rename](https://github.com/jarun/nnn/wiki/Basic-use-cases#browse-rename-images)| sh | sxiv |
| imgthumb | View thumbnail of an image or dir of images | sh | [lsix](https://github.com/hackerb9/lsix) |
| imgur | Upload an image to imgur (from [imgur-screenshot](https://github.com/jomo/imgur-screenshot)) | bash | - |
| imgviu | View an image or images in dir in `$PAGER` | sh | [viu](https://github.com/atanunq/viu), less |
| ipinfo | Fetch external IP address and whois information | sh | curl, whois |
| kdeconnect | Send selected files to an Android device | sh | kdeconnect-cli |
| mediainf | Show media information | sh | mediainfo |
| moclyrics | Show lyrics of the track playing in moc | sh | [ddgr](https://github.com/jarun/ddgr), [moc](http://moc.daper.net/) |
| mocplay | Append (and/or play) selection/dir/file in moc | sh | [moc](http://moc.daper.net/) |
| nmount | Toggle mount status of a device as normal user | sh | pmount, udisks2 |
| notes | Open a quick notes file/dir in `$EDITOR` | sh | - |
| oldbigfile | List large files by access time | sh | find, sort |
| organize | Auto-organize files in directories by file type | sh | file |
| pastebin | Paste contents of a text a file ix.io | sh | - |
| pdfread | Read a PDF or text file aloud | sh | pdftotext, mpv,<br>pico2wave |
| pdfview | View PDF file in `$PAGER` | sh | pdftotext/<br>mupdf-tools |
| picker | Pick files and list one per line (to pipe) | sh | nnn |
| pskill | Fuzzy list by name and kill process or zombie | sh | fzy, sudo/doas |
| renamer | Batch rename selection or files in dir | sh | [qmv](https://www.nongnu.org/renameutils/)/[vidir](https://joeyh.name/code/moreutils/) |
| ringtone | Create a variable bitrate mp3 ringtone from file | sh | date, ffmpeg |
| splitjoin | Split file or join selection | sh | split, cat |
| suedit | Edit file using superuser permissions | sh | sudoedit/sudo/doas |
| transfer | Upload file to transfer.sh | sh | curl |
| treeview | Informative tree output in `$EDITOR` | sh | tree |
| uidgid | List user and group of all files in dir | sh | ls, less |
| upgrade | Upgrade nnn manually on Debian 9 Stretch | sh | curl |
| vidthumb | Show video thumbnails in terminal | sh | [ffmpegthumbnailer](https://github.com/dirkvdb/ffmpegthumbnailer),<br>[lsix](https://github.com/hackerb9/lsix) |
| wall | Set wallpaper or change colorscheme | sh | nitrogen/pywal |
## Installing plugins
The following command installs all plugins:
curl -Ls https://raw.githubusercontent.com/jarun/nnn/master/plugins/getplugs | sh
Plugins are installed to `${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins`. You can run the `getplugs` plugin later to update the plugins. It backs up earlier plugins.
**NOTE:** `getplugs` also downloads the launcher `nlaunch` and tries to place it at `/usr/local/bin/` using `sudo`. If it fails you have to place `nlauch` manually somewhere in your `$PATH`.
Now plugin `fzopen` can be run with the keybind <kbd>:o</kbd>, `mocplay` can be run with <kbd>:p</kbd> and so on... The key vs. plugin pairs are shown in the help and config screen.
**Method 2:** Use the _pick plugin_ shortcut to visit the plugin directory and execute a plugin. Repeating the same shortcut cancels the operation and puts you back in the original directory.
## Running commands as plugin
To assign keys to arbitrary non-background cli commands (non-shell-interpreted) and invoke like plugins, add `_` (underscore) before the command. For example:
Now <kbd>:x</kbd> can be used to make a file executable, <kbd>:g</kbd> can be used to the git log of a git project directory, <kbd>:s</kbd> can be used to preview a partially downloaded media file.
| [autojump](autojump) | Navigate to dir/path | sh | [jump](https://github.com/gsamokovarov/jump)/autojump/<br>zoxide/z/[z.lua](https://github.com/skywind3000/z.lua) |
| [boom](boom) | Play random music from dir | sh | [moc](http://moc.daper.net/) |
| [bulknew](bulknew) | Create multiple files/dirs at once | bash | sed, xargs, mktemp |
| [cbcopy-mac](cbcopy-mac) | Copy the hovered file to MacOS clipboard | applescript | macos |
| [cbpaste-mac](cbpaste-mac) | Pastes files from MacOS clipboard into currect directory | macos |
| [cdpath](cdpath) | `cd` to the directory from `CDPATH` | sh | fzf |
| [chksum](chksum) | Create and verify checksums [✓] | sh | md5sum,<br>sha256sum |
| [cmusq](cmusq) | Queue/play files/dirs in cmus player [✓] | sh | cmus, pgrep |
| [diffs](diffs) | Diff for selection (limited to 2 for directories) [✓] | sh | vimdiff, mktemp |
| [preview-tui](preview-tui) | Preview with Tmux/kitty/[QuickLook](https://github.com/QL-Win/QuickLook)/xterm/`$TERMINAL` | sh | _see in-file docs_ |
| [pskill](pskill) | Fuzzy list by name and kill process or zombie | sh | fzf, ps, sudo/doas |
| [renamer](renamer) | Batch rename selection or files in dir [✓] | sh | [qmv](https://www.nongnu.org/renameutils/)/[vidir](https://joeyh.name/code/moreutils/) |
| [ringtone](ringtone) | Create a variable bitrate mp3 ringtone from file | sh | date, ffmpeg |
- [Access level of plugins](#access-level-of-plugins)
- [Create your own plugins](#create-your-own-plugins)
- [Send data to `nnn`](#send-data-to-nnn)
- [Get notified on file hover](#get-notified-on-file-hover)
- [Examples](#examples)
- [Contributing plugins](#contributing-plugins)
## Installation
The following command installs or updates (after backup) all plugins:
```sh
sh -c "$(curl -Ls https://raw.githubusercontent.com/jarun/nnn/master/plugins/getplugs)"
```
Plugins are installed to `${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins`.
## Configuration
Set environment variable `NNN_PLUG` to assign keybinds and invoke plugins directly using the plugin shortcut (<kbd>;</kbd>) followed by the assigned key character. E.g., with the below config:
plugin `finder` can be invoked with the keybind <kbd>;f</kbd>, `fzopen` can be run with <kbd>;o</kbd> and so on... The key vs. plugin pairs are shown in the help and config screen.
Alternatively, combine with <kbd>Alt</kbd> (i.e. <kbd>Alt+key</kbd>).
To pick and run an unassigned plugin, press <kbd>Enter</kbd> (to _enter_ the plugin dir) at the plugin prompt.
To run a plugin at startup, use the option `-P` followed by the plugin key.
If the plugins list gets too long, try breaking them up into sections:
Now <kbd>;x</kbd> can be used to make a file executable, <kbd>;g</kbd> can be used to the git log of a git project directory, <kbd>;s</kbd> can be used to preview a partially downloaded media file.
#### Skip user confirmation after command execution [`*`]
`nnn` waits for user confirmation (the prompt `Press Enter to continue`) after it executes a command as plugin (unlike plugins which can add a `read` to wait). To skip this, add a `*` after the command.
| `n:-!vi /home/user/Dropbox/dir/note*` | Take quick notes in a synced file/dir of notes |
| `p:-!less -iR "$nnn"*` | Page through hovered file in less |
| `s:-!&smplayer -minigui "$nnn"` | Play hovered media file, even unfinished download |
| `x:!chmod +x "$nnn"` | Make the hovered file executable |
| `y:-!sync*` | Flush cached writes |
## Access level of plugins
When `nnn` executes a plugin, it does the following:
- Change to the directory where the plugin is to be run (`$PWD` pointing to the active directory)
- Passes two arguments to the script:
1. The hovered file's name.
2. The working directory (might differ from `$PWD` in case of symlinked paths; non-canonical). Note that the second argument is not passed in case of commands starting with `_`.
- Changes to the directory where the plugin is to be run (`$PWD` pointing to the active directory)
- Passes three arguments to the script:
1. `$1`: The hovered file's name.
2. `$2`: The working directory (might differ from `$PWD` in case of symlinked paths; non-canonical).
3. `$3`: The picker mode output file (`-` for stdout) if `nnn` is executed as a file picker.
- Sets the environment variable `NNN_PIPE` used to control `nnn` active directory.
- Sets the environment variable `NNN_INCLUDE_HIDDEN` to `1` if hidden files are active, `0` otherwise.
- Sets the environment variable `NNN_PREFER_SELECTION` to `1` if user prefers to use selection (see nnn's `-u` flag), `0` otherwise.
- Exports the [special variables](https://github.com/jarun/nnn/wiki/Concepts#special-variables).
Plugins can also access the current selections by reading the `.selections` file in the config directory (See the `diffs` plugin for example).
Plugins can also read the `.selection` file in the config directory.
## Create your own plugins
Plugins are scripts that can be written in any scripting language. However, POSIX-compliant shell scripts runnable in `sh` are preferred.
Plugins can be written in any scripting language. However, POSIX-compliant shell scripts runnable in `sh` are preferred.
Once it's ready, drop the plugin in `${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins` and make it executable. Optionally add a custom keybind in `$NNN_PLUG` if you intend to use the plugin frequently.
**Make the file executable**. Drop it in the plugin directory. Optionally add a hotkey in `$NNN_PLUG` for frequent usage.
#### Controlling `nnn`'s active directory
`nnn` provides a mechanism for plugins to control its active directory.
#### Send data to `nnn`
`nnn` provides a mechanism for plugins to send data to `nnn` to control its active directory or invoke the list mode.
The way to do so is by writing to the pipe pointed by the environment variable `NNN_PIPE`.
The plugin should write a single string in the format `<number><path>` without a newline at the end. For example, `1/etc`.
The number indicates the context to change the active directory of (0 is used to indicate the current context).
The plugin should write a single string in the format `(<->)<ctxcode><opcode><data>` without a newline at the end. For example, `1c/etc`.
The optional `-` at the **beginning of the stream** instructs `nnn` to clear the selection.
In cases where the data transfer to `nnn` has to happen while the selection file is being read (e.g. in a loop), the plugin should
create a tmp copy of the selection file, inform `nnn` to clear the selection and then do the subsequent processing with the tmp file.
A paged [`|`] or GUI [`&`] cmd run as plugin cannot clear selection.
The `ctxcode` indicates the context to change the active directory of.
For convenience, we provided a helper script named `.nnn-plugin-helper` and a function named `nnn_cd` to ease this process. `nnn_cd` receives the path to change to as the first argument, and the context as an optional second argument.
If a context is not provided, it is asked for explicitly.
If a context is not provided, it is asked for explicitly. To skip this and choose the current context, set the `CUR_CTX` variable in `.nnn-plugin-helper` (or in the specific plugin after sourcing `.nnn-plugin-helper`) to 1.
Usage examples can be found in the Examples section below.
#### Examples
#### Get notified on file hover
If `NNN_FIFO` is set, `nnn` will open it and write every hovered files. This can be used in plugins and external scripts, e.g. to implement file previews.
Don't forget to fork in the background to avoid blocking `nnn`.
For more details on configuration and usage of the preview plugins, visit [Live Previews](https://github.com/jarun/nnn/wiki/Live-previews).
## Examples
There are many plugins provided by `nnn` which can be used as examples. Here are a few simple selected examples.
- Show the git log of changes to the particular file along with the code for a quick and easy review.
```sh
#!/usr/bin/env sh
git log -p -- "$1"
```
#### Show the git log of changes to the particular file along with the code for a quick and easy review.
- Change to directory in clipboard using helper script
```sh
#!/usr/bin/env sh
. $(dirname $0)/.nnn-plugin-helper
```sh
#!/usr/bin/env sh
nnn_cd "$(xsel -ob)"
```
git log -p -- "$1"
```
- Change direcory to the location of a link using helper script with specific context (current)
```sh
#!/usr/bin/env sh
. $(dirname $0)/.nnn-plugin-helper
#### Change to directory in clipboard using helper script
nnn_cd "$(dirname $(readlink -fn $1))" 0
```
```sh
#!/usr/bin/env sh
- Change to arbitrary directory without helper script
```sh
#!/usr/bin/env sh
printf "cd to: "
read -r dir
. $(dirname $0)/.nnn-plugin-helper
printf "%s" "0$dir" > "$NNN_PIPE"
```
nnn_cd "$(xsel -ob)"
```
#### Change directory to the location of a link using helper script with specific context (current)
```sh
#!/usr/bin/env sh
. $(dirname $0)/.nnn-plugin-helper
nnn_cd "$(dirname $(readlink -fn $1))" 0
```
#### Change to arbitrary directory without helper script
```sh
#!/usr/bin/env sh
printf "cd to: "
read -r dir
printf "%s" "0c$dir" > "$NNN_PIPE"
```
#### Send every hovered file to X selection
```sh
#!/usr/bin/env sh
if [ -z "$NNN_FIFO" ] ; then
exit 1
fi
while read FILE ; do
printf "%s" "$FILE" | xsel
done < "$NNN_FIFO" &
disown
```
#### Quick `find` the first match in subtree and open in `nuke`
Add informative sections like _Description_, _Notes_, _Dependencies_, _Shell_, _Author_ etc. in the plugin as applicable. Add an entry in the table above. Please keep non-portable commands (like `notify-send`) commented so users from any other OS/DE aren't surprised.
The plugins should be executable.
1. Add informative sections like _Description_, _Notes_, _Dependencies_, _Shell_, _Author_ etc. in the plugin.
2. Add an entry in the table above. Note that the list is alphabetically ordered by plugin name.
3. Keep non-portable commands (like `notify-send`) commented so users from any other OS/DE aren't surprised.
4. The plugin file should be executable.
5. If your plugin stores data, use `${XDG_CACHE_HOME:-$HOME/.cache}/nnn`. Document it _in-file_.
# Description: Send the selected files to your Android device using kdeconnect-cli. You must have installed and configured kdeconnect both on the Android device and on the PC.
# Description: Send files or folders to your Android device using kdeconnect-cli.
# kdeconnect must be configured on the Android device and the PC.
#
# Usage:
# - Hover over a file or a folder and call the plugin.
# - Alternatively, select the files and folders you would like to send, and activate the plugin.