Compare commits

...

140 Commits
v4.8 ... master

Author SHA1 Message Date
Arun e27d059552
Merge pull request #1881 from N-R-K/colemak-collision
fix collision in colemak patch
2024-05-18 05:43:44 +05:30
NRK 4f3662cf88 fix collision in colemak patch
Closes: https://github.com/jarun/nnn/issues/1876
2024-05-11 11:46:11 +00:00
Arun 9e95578c22
Merge pull request #1879 from N-R-K/use_stdio
use buffered io to reduce syscalls
2024-05-10 17:33:32 +05:30
NRK 78b9677abd use buffered io to reduce syscalls 2024-05-10 08:37:21 +00:00
Arun Prakash Jana 55137600e0
Fix #1877: use dprintf() instead of write() 2024-05-06 19:05:46 +05:30
Arun Prakash Jana be6988d1c8
Fix #1877: malloc: error pointer being freed was not allocated 2024-05-05 18:40:52 +05:30
Arun Prakash Jana 191e77ec5d
Fix CI error 2024-04-28 20:37:53 +05:30
Arun Prakash Jana 46b5255814
Add comma 2024-04-28 20:25:08 +05:30
Arun 2fb7490bf0
Merge pull request #1834 from TheUtopian/master
preview-tabbed: show sxiv/nsxiv in thumbnail mode when watching Pictures folder
2024-04-28 18:16:36 +05:30
Arun d61c983dd0
Merge pull request #1872 from N-R-K/manpage_sort
clarify au and du in manpage
2024-04-24 18:12:53 +05:30
NRK e60be2eaa2 silence new clang-tidy warnings 2024-04-24 07:31:15 +00:00
NRK 72ee94ed6e clarify au and du in manpage
Closes: https://github.com/jarun/nnn/issues/1855
Closes: https://github.com/jarun/nnn/issues/1290
Closes: https://github.com/jarun/nnn/discussions/1750
2024-04-24 06:16:00 +00:00
Oktay Imanzade b20886a29c
preview-tabbed: show (n)sxiv in thumbnail mode when watching "Pictures" directory 2024-04-18 20:18:24 +04:00
Arun ad04944bdf
Merge pull request #1865 from flipflop133/patch-1
preview-tui: add svg support
2024-04-08 18:04:00 +05:30
François Bechet 133c0d329b preview-tui: add full svg support 2024-04-08 13:55:21 +02:00
Arun 5853ac8e48
Merge pull request #1864 from horrad/master
Fix file creation on OpenBSD
2024-04-05 23:31:08 +05:30
Martin Ziemer 28d993a8e8 Fix file creation on OpenBSD
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.
2024-04-04 15:57:36 +02:00
Arun 22aa1455a6
Merge pull request #1861 from KlzXS/makefile_icons
Prevent multiple icons options being selected at the same time
2024-03-30 01:33:20 +05:30
KlzXS 7806d5d371
Prevent multiple icons options being selected at the same time 2024-03-28 18:20:21 +01:00
Arun 5456ba4582
Merge pull request #1830 from c79cea05/master
nuke: use sort -V
2024-03-05 23:31:45 +05:30
c79cea05 297b85492f nuke: use sort -V 2024-02-23 09:21:15 +09:00
Arun Prakash Jana f71b1309a9
Fix deletion prompt when rm is used 2024-02-18 06:32:49 +05:30
Arun eb66598145
Merge pull request #1821 from KlzXS/cpmvrm_dashes
Added dashes to progress versions of cp and mv
2024-02-16 19:17:39 +05:30
KlzXS 3d6777920a
Add -- to mvg and cpg which were missed 2024-02-13 18:49:02 +01:00
Arun 4a9587a5e6
Merge pull request #1820 from KlzXS/cpmvrm_dashes
Add -- to cp, mv and rm
2024-02-13 19:45:38 +05:30
KlzXS b392dd3723
Added -- to all instances of cp, mv or rm dealing with user provided paths 2024-02-13 14:32:42 +01:00
Arun 0f62c6258a
Merge pull request #1806 from BeyondMagic/master
quitcd: fix old bug and feat. for modular export for nushell
2024-02-12 22:24:53 +05:30
João F. (BeyondMagic/koetemagie) 2a442ec30c quitcd: fix bugs and feat. for modular export and selective quit 2024-02-10 18:59:26 -03:00
Michel DHOOGE 5b05c8b9b1
fix: use a more generic way to print NUL with awk
Only gawk undestands the \0 syntax
feat(mimelist): use `mimetype` for better type detection
docs(mimelist): add author & dependencies
2024-02-09 23:14:58 +05:30
90 eb3888cb09
Add option to `rm -rf` irrespective of trash setting 2024-02-09 23:14:56 +05:30
Arun Prakash Jana 94aeaccdbd
Fix #1765: detect and ignore false mouse click 2024-02-09 23:14:49 +05:30
NRK 0738f39cf0 show relative line numbering when jumping
Co-authored-by: Darukutsu <darupeter@pm.me>
Closes: https://github.com/jarun/nnn/pull/1804
Closes: https://github.com/jarun/nnn/discussions/1708
2024-02-03 09:53:11 +00:00
Antonio Mancera Gamez e76d7bbf1d
Changed exa from grid to tree view (preview-tui) (#1803)
* 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>
2024-02-02 21:11:18 +05:30
Arun f2a8648861
Merge pull request #1783 from 7ocb/alternative-setenv-pwd-3
Setting PWD: set on use case, not on browse
2023-12-15 06:07:44 +05:30
Arun 82f9e544f2
Merge pull request #1782 from BeyondMagic/master
fix nushell quitcd script: remove deprecated keywords
2023-12-15 06:06:09 +05:30
me 3d2caf861d Setting PWD: set on use case, not on browse
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.
2023-12-14 11:03:38 +03:00
João F. (BeyondMagic/koetemagie) eb775914af fix nu quitcd: remove deprecated keywords 2023-12-13 21:18:29 -03:00
Arun 5595d93d29
Merge pull request #1778 from 7ocb/set-PWD-to-current-path
Set PWD environment variable
2023-12-08 19:38:46 +05:30
Arun bb650eb9dd
Merge pull request #1775 from JefeDavis/master
feat(preview-tui): allow image previews inside tmux on kitty terminal
2023-12-08 18:21:29 +05:30
me ab718387c2 Set PWD environment variable
This is to make spawned shells and processes to see "logical" path.
2023-12-04 14:09:37 +03:00
Jeff Davis 3849430ebc feat(preview-tui): allow image previews inside tmux on kitty terminal
Signed-off-by: Jeff Davis <mr.jefedavis@gmail.com>
2023-12-03 00:51:27 -05:00
Arun f2a909dafd
Merge pull request #1770 from 7ocb/pass-path-to-abspath
When handling SEL_NEW pass `path` to `abspath` call
2023-11-25 18:36:52 +05:30
Arun 404eed5fc7
Merge pull request #1773 from 7ocb/handle-link-by-readlink-not-realpath-mk2
When handling bookmark, use readlink, not realpath
2023-11-25 18:34:01 +05:30
me 9aaf9491ad When handling bookmark, use readlink, not realpath
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).
2023-11-22 20:41:49 +03:00
Arun 485079d3ec
Merge pull request #1769 from N-R-K/fix-helpstr
fix buffer overflow on certain platforms
2023-11-21 22:11:12 +05:30
me bca441e00f When handling SEL_NEW pass `path` to `abspath` call
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.
2023-11-21 19:26:20 +03:00
NRK 60eabb6170 silence ci warning 2023-11-21 20:50:45 +06:00
NRK 3665541dac fix buffer overflow on certain platforms
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
2023-11-21 19:32:00 +06:00
Arun 744a7554ef
Merge pull request #1762 from azuline/sortctx
restore sort function pointers when restoring cfg
2023-11-19 13:39:24 +05:30
blissful c0b3cc8689
factor out a `setcfg` function for setting the cfg global 2023-11-18 16:34:17 -05:00
blissful 703d349389
restore sort function pointers when restoring cfg 2023-11-17 17:45:06 -05:00
Arun Prakash Jana 9259170afd Add example: run cmd as plugin to change directory 2023-11-18 01:00:03 +05:30
Arun 2f22afcacc
Merge pull request #1755 from cronyakatsuki/alacritty
preview-tabbed: Add alacritty as xembed client for text-based preview
2023-11-17 19:08:03 +05:30
luukvbaal 4009e211f3
Merge pull request #1749 from abhinav3398/master
preview-tui: tmux sixel support for img, gif & vid preview
preview-tui: mpv kitty backend and better previewer handling
2023-11-16 15:50:08 +01:00
Luuk van Baal 3160442f0c
preview-tui: mpv kitty backend and better previewer handling 2023-11-16 15:40:03 +01:00
Abhinav Lakhani 9ff81ca1f9 preview-tui: tmux sixel support for img, gif & vid preview 2023-11-12 14:40:31 -07:00
CronyAkatsuki 8e8289373a
Add alacritty as xembed client for text-based preview 2023-11-03 12:08:09 +00:00
Arun 1051d7213d
Merge pull request #1747 from luukvbaal/master
Preview-tui avoid early exit after SIGWINCH
2023-10-18 06:53:33 +05:30
Luuk van Baal f8f6d6a482
Preview-tui avoid early exit after SIGWINCH 2023-10-11 01:20:44 +02:00
Arun 7f63bef4d6
Merge pull request #1744 from s-hamann/fix-colemak-patch
Fix colemak patch
2023-10-08 17:33:02 +05:30
black bfb46159a1
Fix colemak patch 2023-10-08 09:28:58 +02:00
Arun f3397d5ea4
Merge pull request #1741 from N-R-K/rm-colemak-dh
rm colemak-dh
2023-09-30 22:12:55 +05:30
NRK 336ec8be5d rm colemak-dh
one colemak patch ought to be enough.

Closes: https://github.com/jarun/nnn/issues/1735
2023-09-30 22:25:23 +06:00
J-Kappes afe84862ff
fix nu quitcd: switched quotes (#1737)
Closes: https://github.com/jarun/nnn/issues/1736
2023-09-30 16:19:01 +00:00
Arun 3176eaa85c
Merge pull request #1732 from N-R-K/pr-clang-tidy
Fix CI
2023-09-23 13:54:39 +05:30
NRK 4d5e29c3dd fix CI 2023-09-23 12:26:58 +06:00
NRK 6d6fc3419e split clang-tidy checks into multiple lines
makes it more readable and more easily editable. also produces better
diff when editing.
2023-09-23 12:26:29 +06:00
Arun Prakash Jana 9b921761b6
Update CI name 2023-09-23 08:21:20 +05:30
Arun 09bf8fe469
Merge pull request #1729 from azuline/eza
Add support for eza as a replacement for exa
2023-09-21 09:39:44 +05:30
blissful 3b3ad9ccc6
Add support for eza as a replacement for exa 2023-09-20 15:50:58 -04:00
Arun Prakash Jana dd07aeb703
Fix patch build errors 2023-09-20 23:41:54 +05:30
Arun Prakash Jana 9c7c7284c0
Option `-N` to use native prompt
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.
2023-09-20 23:02:04 +05:30
Arun ba439084c5
Merge pull request #1728 from Xerillic/master
wallpaper plugin: remove unneeded code
2023-09-20 17:51:22 +05:30
Xerillic 06d8da9052 wallpaper plugin: remove unneeded code 2023-09-13 19:53:55 -04:00
Arun ed59aa2ac3
Merge pull request #1727 from Xerillic/master
wallpaper plugin: add ability to set wallpaper for specific monitors
2023-09-13 22:44:55 +05:30
umaranis a06af824ee
plugins for integration with MacOS clipboard 2023-09-13 18:01:35 +05:30
Xerillic 66447d52a7 wallpaper plugin: add ability to set wallpaper for specific monitors using nitrogen 2023-09-12 20:58:37 -04:00
Syed Umar Anis 547508aa78
fzhist plugin: add support for zsh history #1721 (#1722)
* fzhist plugin: add support for zsh history

* fzhist plugin: check $HISTFILE for history file location

* fzhist plugin: remove extra trailing spaces
2023-09-07 18:03:01 +05:30
Arun Prakash Jana d72ab3497a
Use CircleCI parallelism 2023-08-27 18:58:15 +05:30
Arun Prakash Jana 2472554e9a
Use identifiable CircleCI test name 2023-08-27 18:08:27 +05:30
Arun Prakash Jana 785dd3ddf1
Update Haiku nnn.rdef 2023-08-27 10:09:11 +05:30
Arun Prakash Jana 33126ee813
Prepare for release v4.9 Elixir 2023-08-27 09:55:13 +05:30
Arun d8c1c99e45
Merge pull request #1719 from umaranis/master
Update finder plugin find command with default path #1718
2023-08-27 09:12:40 +05:30
Syed Umar Anis b28f209c84
Update finder plugin find command with default path #1718 2023-08-27 10:00:12 +10:00
Arun 1ba85825c5
Merge pull request #1711 from quantonganh/dup-first-char-macOS
Double-width icons can cause duplicated first characters in the filename on macOS
2023-08-20 17:59:30 +05:30
Arun 66f636de13
Merge pull request #1712 from Rahlir/plugin-fzopen-fix
Fix bug in fzopen when selection is canceled
2023-08-17 05:09:19 +05:30
Tadeas Uhlir e500179188 Fix bug in fzopen when selection is canceled 2023-08-12 17:45:14 +02:00
Quan Tong d220c50773 Double-width icons can cause duplicated first characters in the filename on macOS 2023-08-11 06:54:15 +07:00
Arun Prakash Jana 186f9d01ea
Move to Ubuntu 22.04 on Circle CI 2023-08-07 06:16:34 +05:30
Arun Prakash Jana 693ba757c0
Fix #1704 - Show only selected file name if sel is preferred 2023-08-05 23:53:01 +05:30
Arun Prakash Jana 3539e5c1b1
Update help 2023-07-28 20:52:21 +05:30
Arun d65a095d9b
Merge pull request #1698 from ANtlord/young-files
Jump to the next young file
2023-07-28 20:39:29 +05:30
ANtlord dedf0554e5 Jump to the next young file
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.
2023-07-25 08:17:21 +06:00
Arun b835cfcc2a
Merge pull request #1686 from Anomalocaridid/nmount-replace-pmount
nmount: make `pmount` optional
2023-07-16 00:20:50 +05:30
Anomalocaridid 80bbf76b5b nmount: add support for luks volumes for udisksctl 2023-07-09 19:57:57 -04:00
Anomalocaridid 5723023491 nmount: update dependencies in plugins/README.md 2023-07-08 19:55:10 -04:00
Anomalocaridid 280068c5da nmount: make pmount optional 2023-07-08 19:55:07 -04:00
Arun 53e4fec75b
Merge pull request #1679 from N-R-K/ifdef_fixes
Remove some unnecessary ifdefs
2023-07-04 20:21:43 +05:30
NRK db8b61866b define _FILE_OFFSET_BITS 64 unconditionally
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.
2023-07-01 08:56:18 +06:00
Arun 26d5b5c614
Merge pull request #1668 from N-R-K/better_compress
better and faster string compression
2023-06-16 12:14:02 +05:30
Arun 899fd5b4cf
Merge pull request #1673 from JingMatrix/master
Add djvu icon
2023-06-16 12:12:41 +05:30
JingMatrix e6ce7a614e Add djvu icon
Use paperclip as icon since it is used by DjVuLibre.
2023-06-15 16:56:51 +02:00
NRK 5e3ee08e64 fix failing colemak patches 2023-06-15 08:57:48 +06:00
NRK 4c2ce0a84d better helpstring compression
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.
2023-06-15 08:49:30 +06:00
Arun 0dfc6881b4
Merge pull request #1672 from luukvbaal/preview-tui
Preview-tui add -C to NNN_PAGER
2023-06-14 16:20:15 +05:30
Luuk van Baal 05990dc9e5
Preview-tui add -C to NNN_PAGER
This makes it so that when the paged text is fewer lines than the preview pane, it is placed at the top instead of at the bottom
2023-06-14 09:24:23 +02:00
Arun fb6e7403cf
Merge pull request #1658 from N-R-K/chmod_fix
fix: properly update mode after xchmod
2023-05-27 04:44:56 +05:30
NRK b2b830e69d fix: properly update mode after xchmod
xchmod now returns the new mode through a pointer, no need to assume all
executable bits were toggled.

Closes: https://github.com/jarun/nnn/issues/1657
2023-05-26 19:31:00 +06:00
Arun 4149a2619d
Merge pull request #1655 from mistersmee/gitstatus-nerd
patches/gitstatus: Fix nerd fonts broken by 3.0.0 update
2023-05-22 18:08:39 +05:30
Aseem Athale aed2725cb3 patches/gitstatus: Fix nerd fonts broken by 3.0.0 update
Signed-off-by: Aseem Athale <athaleaseem@gmail.com>
2023-05-22 14:22:13 +05:30
Arun 04d9f6738d
Merge pull request #1650 from leo-arch/master
Fix crash when PWD is set to empty string
2023-05-19 01:57:34 +05:30
Arun e013a867da
Merge pull request #1651 from N-R-K/cp_mv
make the cp/mv modification more robust
2023-05-19 01:56:53 +05:30
Arun ed58e07a98
Merge pull request #1646 from Delgan/patch-2
Fix some broken table links in docs
2023-05-19 01:53:48 +05:30
NRK 16899bda53 make the cp/mv modification more robust
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.
2023-05-15 11:29:47 +06:00
Arun 4c0305f11c
Merge pull request #1648 from N-R-K/g3_debug
Makefile: use -g3 for debug builds
2023-05-15 06:38:03 +05:30
leo-arch 4babedc3e4
Fix crash when PWD is set to empty string
nnn crashes when PWD is set to empty string: `PWD="" nnn`
2023-05-14 20:12:04 +00:00
NRK ddcf331205 Makefile: use -g3 for debug builds
-g3 builds additional information such as macro definition and so on.
2023-05-14 22:13:44 +06:00
Delgan bd4a4454fe
Fix some broken table links in docs 2023-05-13 17:25:59 +02:00
Arun aaf60b93d7
Merge pull request #1645 from Delgan/patch-1
Add "$NNN_TERMINAL_ARGS" for "preview-tui" plugin
2023-05-12 22:03:22 +05:30
Arun 145ea41490
Merge pull request #1644 from jaspwr/master
Update Haskell icon colour
2023-05-12 22:02:52 +05:30
Arun 29779acc57
Merge pull request #1643 from UnleashedMarf/iconlookup-fix
Fix syntax-error in .iconlookup
2023-05-12 21:07:29 +05:30
Delgan a7262eb4ee Allow $NNN_TERMINAL additional arguments for "preview-tui" plugin
This can be used to start terminal with a custom title and prevent focus switch with i3 window manager.
2023-05-12 15:53:45 +02:00
Jasper fb3a648756 Update Haskell icon color 2023-05-12 15:19:04 +10:00
UnleashedMarf 9be3ee9abf
Fix another typo
Co-authored-by: luukvbaal <luukvbaal@gmail.com>
2023-05-11 19:44:17 +02:00
UnleashedMarf d873eb393d
Fix syntax-error in .iconlookup
Fixed syntax-error that prevented .iconlookup from executing.
2023-05-11 18:58:11 +02:00
Arun Prakash Jana efd5bc9db1 Update docs 2023-05-06 17:56:21 +05:30
Arun 737ebaa9ef
Merge pull request #1639 from atomcult/posix-quitcd
quitcd.bash_zsh: make POSIX compliant; minor fixes and style changes
2023-05-06 08:34:31 +05:30
J. Brock 95183fbef8 quitcd.bash_zsh: make POSIX compliant; minor fixes and style changes
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>
2023-05-05 14:42:13 -04:00
Arun fe96bd6bc7
Merge pull request #1638 from luukvbaal/nerdfix
Update nerd-font icons to v3
2023-05-05 05:36:27 +05:30
Luuk van Baal 20e944f5e5
Update nerd-font icons to v3
This is an upstream breaking change.
Update your font to the latest version if you see missing icons.
2023-05-05 01:01:43 +02:00
Arun Prakash Jana 5d81aeb477 Filter adjustment when opening context from plugin
- 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.
2023-04-29 21:53:49 +05:30
Arun 8fd1822ca6
Merge pull request #1633 from N-R-K/assert_fix
icons-hash: replace assert with handmade version
2023-04-23 21:01:27 +05:30
NRK 20725b0b4d icons-hash: replace assert with handmade version
since 2fc9d51, the hash-table generator inherits environmental
CFLAGS and so we shouldn't disallow setting -DNDEBUG.

fixes: https://github.com/jarun/nnn/issues/1632
2023-04-22 17:08:00 +06:00
Arun 6a8d74a43a
Merge pull request #1630 from musjj/preview-tui-escape
feat(preview-tui): handle quoting in `start_preview` more robustly
2023-04-22 03:02:37 +05:30
Luuk van Baal d3b5d0e49d
perf(preview-tui): replace env for loop with parameter expansion 2023-04-21 10:39:10 +02:00
musjj 432b0755d3 feat(preview-tui): handle quoting in start_preview more robustly
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.
2023-04-19 08:20:41 +07:00
Arun 621dbba02e
Merge pull request #1628 from spfanning/patch-1
Support wezterm split size percentage in preview-tui
2023-04-14 18:54:22 +05:30
spfanning 63891578d7
Support wezterm split size percentage 2023-04-13 15:50:31 -05:00
Arun Prakash Jana 8a1dce888a
config option to specify archive mounter utility 2023-04-14 01:47:50 +05:30
Arun Prakash Jana 9319b638e7
Revert variety 2023-04-13 19:10:07 +05:30
50 changed files with 1035 additions and 829 deletions

View File

@ -3,10 +3,11 @@ version: 2
jobs:
compile:
docker:
- image: ubuntu:20.04
- image: ubuntu:22.04
working_directory: ~/nnn
environment:
CI_FORCE_TEST: 1
parallelism: 4
steps:
- run:
command: |
@ -14,24 +15,14 @@ jobs:
DEBIAN_FRONTEND="noninteractive" TZ="America/New_York" apt-get -y install tzdata
apt install -y --no-install-recommends software-properties-common wget gpg-agent shellcheck
apt install -y --no-install-recommends git make pkg-config libncurses-dev libreadline-dev
apt install -y --no-install-recommends gcc-7 gcc-8 gcc-9 gcc-10
apt install -y --no-install-recommends clang-6.0 clang-7 clang-8 clang-9 clang-10 clang-11 clang-tidy-11
apt install -y --no-install-recommends gcc-9 gcc-10 gcc-11 gcc-12
apt install -y --no-install-recommends clang-11 clang-12 clang-13 clang-14 clang-15 clang-tidy-15
- checkout
- run:
command: |
export CFLAGS=-Werror
make clean
echo
echo "########## gcc-7 ##########"
CC=gcc-7 make strip
ls -l nnn
make clean
echo
echo "########## gcc-8 ##########"
CC=gcc-8 make strip
ls -l nnn
make clean
echo
echo "########## gcc-9 ##########"
CC=gcc-9 make strip
ls -l nnn
@ -42,28 +33,13 @@ jobs:
ls -l nnn
make clean
echo
echo "########## clang-6 ##########"
CC=clang-6.0 make strip
echo "########## gcc-11 ##########"
CC=gcc-11 make strip
ls -l nnn
make clean
echo
echo "########## clang-7 ##########"
CC=clang-7 make strip
ls -l nnn
make clean
echo
echo "########## clang-8 ##########"
CC=clang-8 make strip
ls -l nnn
make clean
echo
echo "########## clang-9 ##########"
CC=clang-9 make strip
ls -l nnn
make clean
echo
echo "########## clang-10 ##########"
CC=clang-10 make strip
echo "########## gcc-12 ##########"
CC=gcc-12 make strip
ls -l nnn
make clean
echo
@ -72,10 +48,25 @@ jobs:
ls -l nnn
make clean
echo
echo "########## clang-tidy-11 ##########"
clang-tidy-11 src/* -- -I/usr/include -I/usr/include/ncursesw
echo "########## clang-12 ##########"
CC=clang-12 make strip
ls -l nnn
make clean
echo
echo "########## clang-13 ##########"
CC=clang-13 make strip
ls -l nnn
make clean
echo
echo "########## clang-14 ##########"
CC=clang-14 make strip
ls -l nnn
make clean
echo
echo "########## clang-tidy-15 ##########"
clang-tidy-15 src/* -- -I/usr/include -I/usr/include/ncursesw
echo "########## shellcheck ##########"
find plugins/ -type f -not -name "*.md" -exec shellcheck {} +
find plugins/ -type f ! \( -name "*.md" -o -name "*-mac" \) -exec shellcheck {} +
package-and-publish:
machine: true
@ -107,7 +98,7 @@ jobs:
workflows:
version: 2
test:
CircleCI:
jobs: &all-tests
- compile

View File

@ -1,4 +1,4 @@
name: ci
name: GitHubCI
on:
push:
@ -30,8 +30,9 @@ jobs:
# see: https://github.com/actions/setup-python/issues/577
brew update || true
brew install llvm || true
brew link --overwrite python@3.11
brew unlink python@3.11 && brew link python@3.11
export PATH="/usr/local/opt/llvm/bin:$PATH"
export PATH="/opt/homebrew/opt/llvm/bin:$PATH"
export CFLAGS="$CFLAGS -Werror"
make clean
make

View File

@ -1,3 +1,23 @@
nnn v4.9 Elixir
2023-08-27
- config option `NNN_ARCHMNT` to specify archive mounter utility
- key <kbd>^y</kbd> to jump to next young file
- filter adjustment when opening context from plugin
- properly update mode after `chmod`
- pre-fill selected file name to create link if sel is preferred over hovered
- fix crash when `PWD` is empty
- make `quitcd.bash_zsh` POSIX-compliant
- `nmount` - support `udiskctl` as default
- `preview-tui` - support wezterm split size percentage
- `preview-tui` - move to bash for environment manipulation through arrays
- `fzopen` - handle empty selection
- `finder` - use default path to find
- add icons for `djvu` files
- support Nerd Fonts v3.0.0 and above (older versions are broken by v3.0.0)
-------------------------------------------------------------------------------
nnn v4.8 Spritz
2023-04-13

View File

@ -32,11 +32,12 @@ O_NOSORT := 0 # disable sorting entries on dir load
# User patches
O_COLEMAK := 0 # change key bindings to colemak compatible layout
O_COLEMAK-DH := 0 # change key bindings to colemak-dh compatible layout
O_GITSTATUS := 0 # add git status to detail view
O_NAMEFIRST := 0 # print file name first, add uid and guid to detail view
O_RESTOREPREVIEW := 0 # add preview pipe to close and restore preview pane
T_ICONS := 0 # test if multiple icons options are set and fail
# convert targets to flags for backwards compatibility
ifneq ($(filter debug,$(MAKECMDGOALS)),)
O_DEBUG := 1
@ -51,7 +52,7 @@ endif
ifeq ($(strip $(O_DEBUG)),1)
CPPFLAGS += -DDEBUG
CFLAGS += -g
CFLAGS += -g3
endif
ifeq ($(strip $(O_NORL)),1)
@ -98,16 +99,28 @@ endif
ifeq ($(strip $(O_ICONS)),1)
ICONS_INCLUDE = icons-generated-icons-in-term.h
CPPFLAGS += -DICONS_IN_TERM -DICONS_INCLUDE=\"$(ICONS_INCLUDE)\"
ifeq ($(strip $(T_ICONS)),1)
$(error Choose only one system for icons (O_ICONS, O_NERD or O_EMOJI))
endif
T_ICONS := 1
endif
ifeq ($(strip $(O_NERD)),1)
ICONS_INCLUDE = icons-generated-nerd.h
CPPFLAGS += -DNERD -DICONS_INCLUDE=\"$(ICONS_INCLUDE)\"
ifeq ($(strip $(T_ICONS)),1)
$(error Choose only one system for icons (O_ICONS, O_NERD or O_EMOJI))
endif
T_ICONS := 1
endif
ifeq ($(strip $(O_EMOJI)),1)
ICONS_INCLUDE = icons-generated-emoji.h
CPPFLAGS += -DEMOJI -DICONS_INCLUDE=\"$(ICONS_INCLUDE)\"
ifeq ($(strip $(T_ICONS)),1)
$(error Choose only one system for icons (O_ICONS, O_NERD or O_EMOJI))
endif
T_ICONS := 1
endif
ifeq ($(strip $(O_QSORT)),1)
@ -169,7 +182,6 @@ LOGOSVG = misc/logo/logo.svg
LOGO64X64 = misc/logo/logo-64x64.png
COLEMAK = patches/colemak
COLEMAK-DH = patches/colemak-dh
GITSTATUS = patches/gitstatus
NAMEFIRST = patches/namefirst
RESTOREPREVIEW = patches/restorepreview
@ -342,9 +354,6 @@ endif
ifeq ($(strip $(O_COLEMAK)),1)
patch --forward $(PATCH_OPTS) --strip=1 --input=$(COLEMAK)/mainline.diff
endif
ifeq ($(strip $(O_COLEMAK-DH)),1)
patch --forward $(PATCH_OPTS) --strip=1 --input=$(COLEMAK-DH)/mainline.diff
endif
postpatch:
ifeq ($(strip $(O_NAMEFIRST)),1)
@ -361,9 +370,6 @@ endif
ifeq ($(strip $(O_COLEMAK)),1)
patch --reverse $(PATCH_OPTS) --strip=1 --input=$(COLEMAK)/mainline.diff
endif
ifeq ($(strip $(O_COLEMAK-DH)),1)
patch --reverse $(PATCH_OPTS) --strip=1 --input=$(COLEMAK-DH)/mainline.diff
endif
skip: ;

View File

@ -104,7 +104,7 @@ Runs on the Pi, [Termux](https://www.youtube.com/embed/AbaauM7gUJw) (Android), L
## Quickstart
1. [Install](https://github.com/jarun/nnn/wiki/Usage) `nnn` and the deps you need.
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`.

View File

@ -9,10 +9,10 @@ resource app_signature "application/x-vnd.Jarun-nnn";
resource app_version {
major = 4,
middle = 7,
middle = 9,
minor = 0,
variety = B_APPV_FINAL,
variety = B_APPV_DEVELOPMENT,
internal = 0,
short_info = "nnn",

View File

@ -40,7 +40,7 @@ git checkout v0.3.2
if [ ! -d "./libs" ]; then
mkdir libs
else
rm -vf libs/*
rm -vf -- libs/*
fi
make CC=musl-gcc CFLAGS=-O3 LDFLAGS=-static all-static -j$(($(nproc)+1))
cp -v libcurses/libcurses.a libterminfo/libterminfo.a libs/
@ -57,7 +57,7 @@ make CC=musl-gcc CFLAGS=-O3 LDFLAGS=-static -j$(($(nproc)+1))
# Compile nnn
cd ..
[ -e "./netbsd-curses" ] || rm "$BIN"
[ -e "./netbsd-curses" ] || rm -- "$BIN"
musl-gcc -O3 -DNORL -DNOMOUSE -std=c11 -Wall -Wextra -Wshadow -I./netbsd-curses/libcurses -I./musl-fts -o "$BIN" src/nnn.c -Wl,-Bsymbolic-functions -lpthread -L./netbsd-curses/libs -lcurses -lterminfo -static -L./musl-fts/.libs -lfts
strip "$BIN"

View File

@ -1,16 +1,16 @@
n ()
{
# Block nesting of nnn in subshells
if [[ "${NNNLVL:-0}" -ge 1 ]]; then
[ "${NNNLVL:-0}" -eq 0 ] || {
echo "nnn is already running"
return
fi
}
# The behaviour is set to cd on quit (nnn checks if NNN_TMPFILE is set)
# If NNN_TMPFILE is set to a custom path, it must be exported for nnn to
# see. To cd on quit only on ^G, remove the "export" and make sure not to
# use a custom path, i.e. set NNN_TMPFILE *exactly* as follows:
# NNN_TMPFILE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.lastd"
# NNN_TMPFILE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.lastd"
export NNN_TMPFILE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.lastd"
# Unmask ^Q (, ^V etc.) (if required, see `stty -a`) to Quit nnn
@ -19,12 +19,12 @@ n ()
# stty lwrap undef
# stty lnext undef
# The backslash allows one to alias n to nnn if desired without making an
# infinitely recursive alias
\nnn "$@"
# The command builtin allows one to alias nnn to n, if desired, without
# making an infinitely recursive alias
command nnn "$@"
if [ -f "$NNN_TMPFILE" ]; then
. "$NNN_TMPFILE"
rm -f "$NNN_TMPFILE" > /dev/null
fi
[ ! -f "$NNN_TMPFILE" ] || {
. "$NNN_TMPFILE"
rm -f -- "$NNN_TMPFILE" > /dev/null
}
}

View File

@ -14,4 +14,4 @@ set NNN_TMPFILE=~/.config/nnn/.lastd
# The backslash allows one to alias n to nnn if desired without making an
# infinitely recursive alias
alias n '\nnn; source "$NNN_TMPFILE"; rm -f "$NNN_TMPFILE"'
alias n '\nnn; source "$NNN_TMPFILE"; rm -f -- "$NNN_TMPFILE"'

View File

@ -36,6 +36,6 @@ fn n {|@a|
if (path:is-regular $E:NNN_TMPFILE) {
eval (slurp < $E:NNN_TMPFILE)
rm $E:NNN_TMPFILE
rm -- $E:NNN_TMPFILE
}
}

View File

@ -31,6 +31,6 @@ function n --wraps nnn --description 'support nnn quit and change directory'
if test -e $NNN_TMPFILE
source $NNN_TMPFILE
rm $NNN_TMPFILE
rm -- $NNN_TMPFILE
end
end

View File

@ -1,18 +1,37 @@
# The behaviour is set to cd on quit (nnn checks if NNN_TMPFILE is set)
let cfgHome = ($env | default $"($env.HOME)/.config" XDG_CONFIG_HOME | get XDG_CONFIG_HOME)
let-env NNN_TMPFILE = $"($cfgHome)/nnn/.lastd"
# Run nnn with dynamic changing directory to the environment.
#
# $env.XDG_CONFIG_HOME sets the home folder for `nnn` folder and its $env.NNN_TMPFILE variable.
# See manual NNN(1) for more information.
#
# Import module using `use quitcd.nu n` to have `n` command in your context.
export def --env n [
...args : string # Extra flags to launch nnn with.
--selective = false # Change directory only when exiting via ^G.
] -> nothing {
def-env n [...x] {
# Launch nnn. Add desired flags after `^nnn`, ex: `^nnn -eda ($x | str join)`
^nnn ($x | str join)
let newpath = (
if ($env.NNN_TMPFILE | path exists) {
let newpath = (open $env.NNN_TMPFILE | parse 'cd "{nnnpath}"').0.nnnpath
^rm -f $env.NNN_TMPFILE
echo $newpath
} else {
pwd
}
)
cd $newpath
# The behaviour is set to cd on quit (nnn checks if $env.NNN_TMPFILE is set).
# Hard-coded to its respective behaviour in `nnn` source-code.
let nnn_tmpfile = $env
| default '~/.config/' 'XDG_CONFIG_HOME'
| get 'XDG_CONFIG_HOME'
| path join 'nnn/.lastd'
| path expand
# Launch nnn. Add desired flags after `^nnn`, ex: `^nnn -eda ...$args`,
# or make an alias `alias n = n -eda`.
if $selective {
^nnn ...$args
} else {
NNN_TMPFILE=$nnn_tmpfile ^nnn ...$args
}
if ($nnn_tmpfile | path exists) {
# Remove <cd '> from the first part of the string and the last single quote <'>.
# Fix post-processing of nnn's given path that escapes its single quotes with POSIX syntax.
let path = open $nnn_tmpfile | str substring 4..-1 | str replace --all `'\''` `'`
^rm -- $nnn_tmpfile
cd $path
}
}

22
nnn.1
View File

@ -1,4 +1,4 @@
.Dd Apr 13, 2023
.Dd Aug 27, 2023
.Dt NNN 1
.Os
.Sh NAME
@ -59,7 +59,7 @@ to see the list of keybinds.
supports the following options:
.Pp
.Fl a
auto-setup temporary NNN_FIFO (described in ENVIRONMENT section)
auto-setup temporary \fBNNN_FIFO\fR (described in \fIENVIRONMENT\fR section)
.Pp
.Fl A
disable directory auto-enter on unique filter match
@ -148,7 +148,7 @@ supports the following options:
.Pp
.Fl "T key"
sort order
keys: 'a'u / 'd'u / 'e'xtension / 'r'everse / 's'ize / 't'ime / 'v'ersion
keys: 'a'pparent disk usage / 'd'isk usage / 'e'xtension / 'r'everse / 's'ize / 't'ime / 'v'ersion
capitalize to reverse (except 'r')
.Pp
.Fl u
@ -353,7 +353,7 @@ Handy bash/zsh shell function to list files by mime-type in current directory:
list ()
{
find . -maxdepth 1 | file -if- | grep "$1" | awk -F: '{printf "%s\0", $1}' | nnn
find . -maxdepth 1 | file -if- | grep "$1" | awk -F: '{printf "%s%c", $1, 0}' | nnn
}
.Ed
.Pp
@ -369,17 +369,17 @@ selected entries from the listed results.
.Sh BOOKMARKS
There are 2 ways (can be used together) to manage bookmarks.
.Pp
(1) Bookmark keys: See \fINNN_BMS\fR under \fIENVIORNMENT\fR section on how to set
(1) Bookmark keys: See \fBNNN_BMS\fR under \fIENVIORNMENT\fR section on how to set
bookmark keys.
The select bookmark key \fIb\fR lists all the bookmark keys set in \fINNN_BMS\fR
The select bookmark key \fIb\fR lists all the bookmark keys set in \fBNNN_BMS\fR
in the bookmarks prompt.
.Pp
(2) Symlinked bookmarks: A symlinked bookmark to the current directory can
be created with the \fIB\fR key (or manually under ~/.config/nnn/bookmarks).
Pressing 'Enter' at the bookmarks prompt takes to this directory.
If \fINNN_BMS\fR is not set, the select bookmark key directly opens it.
If \fBNNN_BMS\fR is not set, the select bookmark key directly opens it.
.Pp
On entering a bookmark, the directory where the select bookmark key was
pressed is set as the previous directory. Press '-' to return to it.
@ -540,6 +540,11 @@ separated by \fI;\fR:
NOTE: Non-default formats may require a third-party utility.
.Ed
.Pp
\fBNNN_ARCHMNT:\fR optional archive mounter utility (default: archivemount).
.Bd -literal
export NNN_ARCHIVE='fuse-archive'
.Ed
.Pp
\fBNNN_SSHFS:\fR specify custom sshfs command with options:
.Bd -literal
export NNN_SSHFS='sshfs -o reconnect,idmap=user,cache_timeout=3600'
@ -561,6 +566,9 @@ separated by \fI;\fR:
.Ed
.Pp
\fBNNN_SEL:\fR absolute path to custom selection file.
.Bd -literal
export NNN_SEL='/tmp/.sel'
.Ed
.Pp
\fBNNN_FIFO:\fR path of a named pipe to write the hovered file path:
.Bd -literal

View File

@ -8,7 +8,7 @@ The patches will be adapted on each release when necessary (v4.1 onwards). Each
| Patch (a-z) | Description | Make var |
| --- | --- | --- |
| colemak | Key bindings for Colemak-DH keyboard layout | `O_COLEMAK` |
| colemak | Key bindings for Colemak keyboard layout | `O_COLEMAK` |
| 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` |

View File

@ -1,173 +0,0 @@
# Description: Change key bindings for comfortable use with Colemak-DH keyboard
# layout. This diff was made in 4.5 release version of nnn.
#
# Author: github.com/anjerukare
diff --git a/src/nnn.c b/src/nnn.c
index b821f808..87ebfbbf 100644
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -5050,40 +5050,40 @@ static void show_help(const char *path)
const char helpstr[] = {
"0\n"
"1NAVIGATION\n"
- "9Up k Up%-16cPgUp ^U Page up\n"
- "9Dn j Down%-14cPgDn ^D Page down\n"
- "9Lt h Parent%-12c~ ` @ - ~, /, start, prev\n"
- "5Ret Rt l Open%-20c' First file/match\n"
- "9g ^A Top%-21cJ Jump to entry/offset\n"
- "9G ^E End%-20c^J Toggle auto-advance on open\n"
+ "9Up e Up%-16cPgUp ^U Page up\n"
+ "9Dn n Down%-14cPgDn ^D Page down\n"
+ "9Lt m Parent%-12c~ ` @ - ~, /, start, prev\n"
+ "5Ret Rt i Open%-20c' First file/match\n"
+ "9g ^E Top%-21cJ Jump to entry/offset\n"
+ "9G ^N End%-20c^J Toggle auto-jump on open\n"
"8B (,) Book(mark)%-11cb ^/ Select bookmark\n"
"a1-4 Context%-11c(Sh)Tab Cycle/new context\n"
"62Esc ^Q Quit%-20cq Quit context\n"
"b^G QuitCD%-18cQ Pick/err, quit\n"
"0\n"
"1FILTER & PROMPT\n"
- "c/ Filter%-17c^N Toggle type-to-nav\n"
+ "c/ Filter%-17c^F Toggle type-to-nav\n"
"aEsc Exit prompt%-12c^L Toggle last filter\n"
"c. Toggle hidden%-5cAlt+Esc Unfilter, quit context\n"
"0\n"
"1FILES\n"
- "9o ^O Open with%-15cn Create new/link\n"
- "9f ^F File stats%-14cd Detail mode toggle\n"
+ "9o ^O Open with%-15cc Create new/link\n"
+ "cf File stats%-14cd Detail mode toggle\n"
"b^R Rename/dup%-14cr Batch rename\n"
- "cz Archive%-17ce Edit file\n"
+ "cz Archive%-17cy Edit file\n"
"c* Toggle exe%-14c> Export list\n"
- "6Space + (Un)select%-12cm-m Select range/clear\n"
+ "6Space + (Un)select%-12cs-s Select range/clear\n"
"ca Select all%-14cA Invert sel\n"
"9p ^P Copy here%-12cw ^W Cp/mv sel as\n"
- "9v ^V Move here%-15cE Edit sel list\n"
+ "9v ^V Move here%-15cl Edit sel list\n"
"9x ^X Delete%-18cS Listed sel size\n"
"aEsc Send to FIFO\n"
"0\n"
"1MISC\n"
"8Alt ; Select plugin%-11c= Launch app\n"
"9! ^] Shell%-19c] Cmd prompt\n"
- "cc Connect remote%-10cu Unmount remote/archive\n"
- "9t ^T Sort toggles%-12cs Manage session\n"
+ "ch Connect remote%-10cu Unmount remote/archive\n"
+ "9t ^T Sort toggles%-12ck Manage session\n"
"cT Set time type%-11c0 Lock\n"
"b^L Redraw%-18c? Help, conf\n"
};
diff --git a/src/nnn.h b/src/nnn.h
index 3e4ea19c..c81ef392 100644
--- a/src/nnn.h
+++ b/src/nnn.h
@@ -131,18 +131,18 @@ struct key {
static struct key bindings[] = {
/* Back */
{ KEY_LEFT, SEL_BACK },
- { 'h', SEL_BACK },
+ { 'm', SEL_BACK },
/* Inside or select */
{ KEY_ENTER, SEL_OPEN },
{ '\r', SEL_OPEN },
/* Pure navigate inside */
{ KEY_RIGHT, SEL_NAV_IN },
- { 'l', SEL_NAV_IN },
+ { 'i', SEL_NAV_IN },
/* Next */
- { 'j', SEL_NEXT },
+ { 'n', SEL_NEXT },
{ KEY_DOWN, SEL_NEXT },
/* Previous */
- { 'k', SEL_PREV },
+ { 'e', SEL_PREV },
{ KEY_UP, SEL_PREV },
/* Page down */
{ KEY_NPAGE, SEL_PGDN },
@@ -155,11 +155,11 @@ static struct key bindings[] = {
/* First entry */
{ KEY_HOME, SEL_HOME },
{ 'g', SEL_HOME },
- { CONTROL('A'), SEL_HOME },
+ { CONTROL('E'), SEL_HOME },
/* Last entry */
{ KEY_END, SEL_END },
{ 'G', SEL_END },
- { CONTROL('E'), SEL_END },
+ { CONTROL('N'), SEL_END },
/* Go to first file */
{ '\'', SEL_FIRST },
/* Jump to an entry number/offset */
@@ -176,7 +176,7 @@ static struct key bindings[] = {
{ 'b', SEL_BMOPEN },
{ CONTROL('_'), SEL_BMOPEN },
/* Connect to server over SSHFS */
- { 'c', SEL_REMOTE },
+ { 'h', SEL_REMOTE },
/* Cycle contexts in forward direction */
{ '\t', SEL_CYCLE },
/* Cycle contexts in reverse direction */
@@ -199,14 +199,13 @@ static struct key bindings[] = {
/* Filter */
{ '/', SEL_FLTR },
/* Toggle filter mode */
- { CONTROL('N'), SEL_MFLTR },
+ { CONTROL('F'), SEL_MFLTR },
/* Toggle hide .dot files */
{ '.', SEL_HIDDEN },
/* Detailed listing */
{ 'd', SEL_DETAIL },
/* File details */
{ 'f', SEL_STATS },
- { CONTROL('F'), SEL_STATS },
/* Toggle executable status */
{ '*', SEL_CHMODX },
/* Create archive */
@@ -220,13 +219,13 @@ static struct key bindings[] = {
{ ' ', SEL_SEL },
{ '+', SEL_SEL },
/* Toggle select multiple files */
- { 'm', SEL_SELMUL },
+ { 's', SEL_SELMUL },
/* Select all files in current dir */
{ 'a', SEL_SELALL },
/* Invert selection in current dir */
{ 'A', SEL_SELINV },
/* List, edit selection */
- { 'E', SEL_SELEDIT },
+ { 'l', SEL_SELEDIT },
/* Copy from selection buffer */
{ 'p', SEL_CP },
{ CONTROL('P'), SEL_CP },
@@ -243,7 +242,7 @@ static struct key bindings[] = {
{ 'o', SEL_OPENWITH },
{ CONTROL('O'), SEL_OPENWITH },
/* Create a new file */
- { 'n', SEL_NEW },
+ { 'c', SEL_NEW },
/* Show rename prompt */
{ CONTROL('R'), SEL_RENAME },
/* Rename contents of current dir */
@@ -255,7 +254,7 @@ static struct key bindings[] = {
/* Toggle auto-advance on file open */
{ CONTROL('J'), SEL_AUTONEXT },
/* Edit in EDITOR */
- { 'e', SEL_EDIT },
+ { 'y', SEL_EDIT },
/* Run a plugin */
{ ';', SEL_PLUGIN },
/* Show total size of listed selection */
@@ -270,7 +269,7 @@ static struct key bindings[] = {
/* Lock screen */
{ '0', SEL_LOCK },
/* Manage sessions */
- { 's', SEL_SESSIONS },
+ { 'k', SEL_SESSIONS },
/* Export list */
{ '>', SEL_EXPORT },
/* Set time type */

View File

@ -1,58 +1,63 @@
# Description: Change key bindings for comfortable use with Colemak keyboard
# layout. This diff was made in 4.7 release version of nnn.
#
# Author: github.com/jacmoe
diff --git a/src/nnn.c b/src/nnn.c
index b351e202..71193476 100644
index d7c53166..bb7ff3e8 100644
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -5050,32 +5050,32 @@ static void show_help(const char *path)
const char helpstr[] = {
@@ -5149,12 +5149,12 @@ static void show_help(const char *path)
"2(___n))\n"
"0\n"
"1NAVIGATION\n"
- "9Up k Up%-16cPgUp ^U Page up\n"
- "9Dn j Down%-14cPgDn ^D Page down\n"
+ "9Up e Up%-16cPgUp ^U Page up\n"
+ "9Dn n Down%-14cPgDn ^D Page down\n"
"9Lt h Parent%-12c~ ` @ - ~, /, start, prev\n"
- "5Ret Rt l Open%-20c' First file/match\n"
- "9g ^A Top%-21cJ Jump to entry/offset\n"
- "9G ^E End%-20c^J Toggle auto-advance on open\n"
+ "5Ret Rt i Open%-20c' First file/match\n"
+ "9g ^E Top%-21cJ Jump to entry/offset\n"
+ "9G ^N End%-20c^J Toggle auto-advance on open\n"
"8B (,) Book(mark)%-11cb ^/ Select bookmark\n"
"a1-4 Context%-11c(Sh)Tab Cycle/new context\n"
"62Esc ^Q Quit%-20cq Quit context\n"
"b^G QuitCD%-18cQ Pick/err, quit\n"
- "9Up k Up%16PgUp ^U Page up\n"
- "9Dn j Down%14PgDn ^D Page down\n"
+ "9Up e Up%16PgUp ^U Page up\n"
+ "9Dn n Down%14PgDn ^D Page down\n"
"9Lt h Parent%12~ ` @ - ~, /, start, prev\n"
- "5Ret Rt l Open%20' First file/match\n"
- "9g ^A Top%21J Jump to entry/offset\n"
- "9G ^E End%20^J Toggle auto-advance on open\n"
+ "5Ret Rt i Open%20' First file/match\n"
+ "9g ^E Top%21J Jump to entry/offset\n"
+ "9G ^N End%20^J Toggle auto-advance on open\n"
"8B (,) Book(mark)%11b ^/ Select bookmark\n"
"a1-4 Context%11(Sh)Tab Cycle/new context\n"
"62Esc ^Q Quit%19^y Next young\n"
@@ -5162,27 +5162,27 @@ static void show_help(const char *path)
"cq Quit context\n"
"0\n"
"1FILTER & PROMPT\n"
- "c/ Filter%-17c^N Toggle type-to-nav\n"
+ "c/ Filter%-17c^M Toggle type-to-nav\n"
"aEsc Exit prompt%-12c^L Toggle last filter\n"
"c. Toggle hidden%-5cAlt+Esc Unfilter, quit context\n"
- "c/ Filter%17^N Toggle type-to-nav\n"
+ "c/ Filter%17^K Toggle type-to-nav\n"
"aEsc Exit prompt%12^L Toggle last filter\n"
"c. Toggle hidden%05Alt+Esc Unfilter, quit context\n"
"0\n"
"1FILES\n"
- "9o ^O Open with%-15cn Create new/link\n"
+ "9o ^O Open with%-15cc Create new/link\n"
"9f ^F File stats%-14cd Detail mode toggle\n"
"b^R Rename/dup%-14cr Batch rename\n"
- "cz Archive%-17ce Edit file\n"
+ "cz Archive%-17cy Edit file\n"
"c* Toggle exe%-14c> Export list\n"
"6Space + (Un)select%-12cm-m Select range/clear\n"
"ca Select all%-14cA Invert sel\n"
"9p ^P Copy here%-12cw ^W Cp/mv sel as\n"
- "9v ^V Move here%-15cE Edit sel list\n"
+ "9v ^V Move here%-15cl Edit sel list\n"
"9x ^X Delete%-18cS Listed sel size\n"
"aEsc Send to FIFO\n"
- "9o ^O Open with%15n Create new/link\n"
+ "9o ^O Open with%15c Create new/link\n"
"9f ^F File stats%14d Detail mode toggle\n"
"b^R Rename/dup%14r Batch rename\n"
- "cz Archive%17e Edit file\n"
+ "cz Archive%17y Edit file\n"
"c* Toggle exe%14> Export list\n"
"6Space + (Un)select%12m-m Select range/clear\n"
"ca Select all%14A Invert sel\n"
"9p ^P Copy here%12w ^W Cp/mv sel as\n"
- "9v ^V Move here%15E Edit sel list\n"
+ "9v ^V Move here%15l Edit sel list\n"
"9x ^X Delete or trash%09S Listed sel size\n"
"cX Delete (rm -rf)%07Esc Send to FIFO\n"
"0\n"
"1MISC\n"
"8Alt ; Select plugin%11= Launch app\n"
"9! ^] Shell%19] Cmd prompt\n"
- "cc Connect remote%10u Unmount remote/archive\n"
+ "cC Connect remote%10u Unmount remote/archive\n"
"9t ^T Sort toggles%12s Manage session\n"
"cT Set time type%110 Lock\n"
"b^L Redraw%18? Help, conf\n"
diff --git a/src/nnn.h b/src/nnn.h
index 3e4ea19c..b0eb7cdb 100644
index bd500244..43b7fa22 100644
--- a/src/nnn.h
+++ b/src/nnn.h
@@ -137,12 +137,12 @@ static struct key bindings[] = {
@@ -139,12 +139,12 @@ static struct key bindings[] = {
{ '\r', SEL_OPEN },
/* Pure navigate inside */
{ KEY_RIGHT, SEL_NAV_IN },
@ -68,7 +73,7 @@ index 3e4ea19c..b0eb7cdb 100644
{ KEY_UP, SEL_PREV },
/* Page down */
{ KEY_NPAGE, SEL_PGDN },
@@ -155,11 +155,11 @@ static struct key bindings[] = {
@@ -157,11 +157,11 @@ static struct key bindings[] = {
/* First entry */
{ KEY_HOME, SEL_HOME },
{ 'g', SEL_HOME },
@ -82,16 +87,25 @@ index 3e4ea19c..b0eb7cdb 100644
/* Go to first file */
{ '\'', SEL_FIRST },
/* Jump to an entry number/offset */
@@ -199,7 +199,7 @@ static struct key bindings[] = {
@@ -179,7 +179,7 @@ static struct key bindings[] = {
{ 'b', SEL_BMOPEN },
{ CONTROL('_'), SEL_BMOPEN },
/* Connect to server over SSHFS */
- { 'c', SEL_REMOTE },
+ { 'C', SEL_REMOTE },
/* Cycle contexts in forward direction */
{ '\t', SEL_CYCLE },
/* Cycle contexts in reverse direction */
@@ -202,7 +202,7 @@ static struct key bindings[] = {
/* Filter */
{ '/', SEL_FLTR },
/* Toggle filter mode */
- { CONTROL('N'), SEL_MFLTR },
+ { CONTROL('M'), SEL_MFLTR },
+ { CONTROL('K'), SEL_MFLTR },
/* Toggle hide .dot files */
{ '.', SEL_HIDDEN },
/* Detailed listing */
@@ -226,7 +226,7 @@ static struct key bindings[] = {
@@ -229,7 +229,7 @@ static struct key bindings[] = {
/* Invert selection in current dir */
{ 'A', SEL_SELINV },
/* List, edit selection */
@ -100,7 +114,7 @@ index 3e4ea19c..b0eb7cdb 100644
/* Copy from selection buffer */
{ 'p', SEL_CP },
{ CONTROL('P'), SEL_CP },
@@ -243,7 +243,7 @@ static struct key bindings[] = {
@@ -247,7 +247,7 @@ static struct key bindings[] = {
{ 'o', SEL_OPENWITH },
{ CONTROL('O'), SEL_OPENWITH },
/* Create a new file */
@ -109,7 +123,7 @@ index 3e4ea19c..b0eb7cdb 100644
/* Show rename prompt */
{ CONTROL('R'), SEL_RENAME },
/* Rename contents of current dir */
@@ -255,7 +255,7 @@ static struct key bindings[] = {
@@ -259,7 +259,7 @@ static struct key bindings[] = {
/* Toggle auto-advance on file open */
{ CONTROL('J'), SEL_AUTONEXT },
/* Edit in EDITOR */

View File

@ -18,10 +18,10 @@ index 83ecdb90..4397944a 100644
+#define GIT_ADD ""
+#define GIT_DEL ""
+#define GIT_IGN ""
+#define GIT_MOD ""
+#define GIT_MOD ""
+#define GIT_NEW ""
+#define GIT_NON "-"
+#define GIT_UPD ""
+#define GIT_UPD "󰚰"
+#else
+#define GIT_ADD "A"
+#define GIT_DEL "D"
@ -206,8 +206,8 @@ index 83ecdb90..4397944a 100644
while ((opt = (env_opts_id > 0
? env_opts[--env_opts_id]
- : getopt(argc, argv, "aAb:BcCdDeEfF:gHiJKl:nop:P:QrRs:St:T:uUVxh"))) != -1) {
+ : getopt(argc, argv, "aAb:BcCdDeEfF:gGHiJKl:nop:P:QrRs:St:T:uUVxh"))) != -1) {
- : getopt(argc, argv, "aAb:BcCdDeEfF:gHiJKl:nNop:P:QrRs:St:T:uUVxh"))) != -1) {
+ : getopt(argc, argv, "aAb:BcCdDeEfF:gGHiJKl:nNop:P:QrRs:St:T:uUVxh"))) != -1) {
switch (opt) {
#ifndef NOFIFO
case 'a':

View File

@ -19,10 +19,10 @@ index 88538787..d4af7c43 100644
+#define GIT_ADD ""
+#define GIT_DEL ""
+#define GIT_IGN ""
+#define GIT_MOD ""
+#define GIT_MOD ""
+#define GIT_NEW ""
+#define GIT_NON "-"
+#define GIT_UPD ""
+#define GIT_UPD "󰚰"
+#else
+#define GIT_ADD "A"
+#define GIT_DEL "D"
@ -209,8 +209,8 @@ index 88538787..d4af7c43 100644
while ((opt = (env_opts_id > 0
? env_opts[--env_opts_id]
- : getopt(argc, argv, "aAb:BcCdDeEfF:gHiJKl:nop:P:QrRs:St:T:uUVxh"))) != -1) {
+ : getopt(argc, argv, "aAb:BcCdDeEfF:gGHiJKl:nop:P:QrRs:St:T:uUVxh"))) != -1) {
- : getopt(argc, argv, "aAb:BcCdDeEfF:gHiJKl:nNop:P:QrRs:St:T:uUVxh"))) != -1) {
+ : getopt(argc, argv, "aAb:BcCdDeEfF:gGHiJKl:nNop:P:QrRs:St:T:uUVxh"))) != -1) {
switch (opt) {
#ifndef NOFIFO
case 'a':

View File

@ -71,9 +71,9 @@ index f8a2c58..9802a1f 100644
}
static off_t get_size(off_t size, off_t *pval, int comp)
@@ -4134,33 +4141,7 @@ static uchar_t get_color_pair_name_ind(const struct entry *ent, char *pind, int
static void printent(const struct entry *ent, uint_t namecols, bool sel)
@@ -4228,38 +4235,13 @@ static void printent(int pdents_index, uint_t namecols, bool sel)
{
const struct entry *ent = &pdents[pdents_index];
char ind = '\0';
- int attrs;
-
@ -99,14 +99,19 @@ index f8a2c58..9802a1f 100644
- if (attrs)
- attroff(attrs);
- }
-
+ int attrs = 0, namelen;
if (g_state.showlines) {
ptrdiff_t rel_num = pdents_index - cur;
printw(rel_num == 0 ? "%4td" : "%+4td", rel_num);
}
- attrs = 0;
-
+ int attrs = 0, namelen;
uchar_t color_pair = get_color_pair_name_ind(ent, &ind, &attrs);
addch((ent->flags & FILE_SELECTED) ? '+' | A_REVERSE | A_BOLD : ' ');
@@ -4185,15 +4166,40 @@ static void printent(const struct entry *ent, uint_t namecols, bool sel)
@@ -4284,15 +4266,40 @@ static void printent(int pdents_index, uint_t namecols, bool sel)
++namecols;
#ifndef NOLC
@ -149,8 +154,8 @@ index f8a2c58..9802a1f 100644
+ attroff(attrs);
}
static void savecurctx(char *path, char *curname, int nextctx)
@@ -6356,26 +6362,19 @@ static void statusbar(char *path)
/**
@@ -6527,26 +6534,19 @@ static void statusbar(char *path)
tocursor();
}

View File

@ -7,20 +7,22 @@
# Authors: Luuk van Baal
diff --git a/src/nnn.c b/src/nnn.c
index b10143a4..76d6bc5b 100644
index 0388b23c..66d3316a 100644
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -374,6 +374,7 @@ typedef struct {
uint_t trash : 2; /* Trash method 0: rm -rf, 1: trash-cli, 2: gio trash */
uint_t uidgid : 1; /* Show owner and group info */
@@ -391,7 +391,8 @@ typedef struct {
uint_t usebsdtar : 1; /* Use bsdtar as default archive utility */
uint_t xprompt : 1; /* Use native prompt instead of readline prompt */
uint_t showlines : 1; /* Show line numbers */
- uint_t reserved : 3; /* Adjust when adding/removing a field */
+ uint_t previewer : 1; /* Run state of previewer */
uint_t reserved : 5; /* Adjust when adding/removing a field */
+ uint_t reserved : 2; /* Adjust when adding/removing a field */
} runstate;
@@ -500,6 +501,9 @@ static char g_tmpfpath[TMP_LEN_MAX] __attribute__ ((aligned));
/* Contexts or workspaces */
@@ -516,6 +517,9 @@ alignas(max_align_t) static char g_tmpfpath[TMP_LEN_MAX];
/* Buffer to store plugins control pipe location */
static char g_pipepath[TMP_LEN_MAX] __attribute__ ((aligned));
alignas(max_align_t) static char g_pipepath[TMP_LEN_MAX];
+/* Buffer to store preview plugins control pipe location */
+static char g_ppipepath[TMP_LEN_MAX] __attribute__ ((aligned));
@ -28,7 +30,7 @@ index b10143a4..76d6bc5b 100644
/* Non-persistent runtime states */
static runstate g_state;
@@ -676,12 +680,13 @@ static const char * const messages[] = {
@@ -696,12 +700,13 @@ static const char * const messages[] = {
#define NNN_FCOLORS 5
#define NNNLVL 6
#define NNN_PIPE 7
@ -48,7 +50,7 @@ index b10143a4..76d6bc5b 100644
static const char * const env_cfg[] = {
"NNN_OPTS",
@@ -692,6 +697,7 @@ static const char * const env_cfg[] = {
@@ -712,6 +717,7 @@ static const char * const env_cfg[] = {
"NNN_FCOLORS",
"NNNLVL",
"NNN_PIPE",
@ -56,16 +58,16 @@ index b10143a4..76d6bc5b 100644
"NNN_MCLICK",
"NNN_SEL",
"NNN_ARCHIVE",
@@ -833,7 +839,7 @@ static int set_sort_flags(int r);
@@ -850,7 +856,7 @@ static int set_sort_flags(int r);
static void statusbar(char *path);
static bool get_output(char *file, char *arg1, char *arg2, int fdout, bool multi, bool page);
static bool get_output(char *file, char *arg1, char *arg2, int fdout, bool page);
#ifndef NOFIFO
-static void notify_fifo(bool force);
+static void notify_fifo(bool force, bool closepreview);
#endif
/* Functions */
@@ -3022,7 +3028,7 @@ try_quit:
@@ -3140,7 +3146,7 @@ try_quit:
} else {
#ifndef NOFIFO
if (!g_state.fifomode)
@ -74,7 +76,7 @@ index b10143a4..76d6bc5b 100644
#endif
escaped = TRUE;
settimeout();
@@ -5120,15 +5126,20 @@ static void run_cmd_as_plugin(const char *file, char *runfile, uchar_t flags)
@@ -5258,15 +5264,20 @@ static void run_cmd_as_plugin(const char *file, uchar_t flags)
static bool plctrl_init(void)
{
@ -99,7 +101,7 @@ index b10143a4..76d6bc5b 100644
return EXIT_SUCCESS;
}
@@ -5157,6 +5168,21 @@ static ssize_t read_nointr(int fd, void *buf, size_t count)
@@ -5295,6 +5306,21 @@ static ssize_t read_nointr(int fd, void *buf, size_t count)
return len;
}
@ -121,7 +123,7 @@ index b10143a4..76d6bc5b 100644
static char *readpipe(int fd, char *ctxnum, char **path)
{
char ctx, *nextpath = NULL;
@@ -5841,7 +5867,7 @@ static void populate(char *path, char *lastname)
@@ -5979,7 +6005,7 @@ static void populate(char *path, char *lastname)
}
#ifndef NOFIFO
@ -130,7 +132,7 @@ index b10143a4..76d6bc5b 100644
{
if (!fifopath)
return;
@@ -5857,6 +5883,12 @@ static void notify_fifo(bool force)
@@ -5995,6 +6021,12 @@ static void notify_fifo(bool force)
}
}
@ -143,7 +145,7 @@ index b10143a4..76d6bc5b 100644
static struct entry lastentry;
if (!force && !memcmp(&lastentry, &pdents[cur], sizeof(struct entry))) // NOLINT
@@ -5889,7 +5921,7 @@ static void send_to_explorer(int *presel)
@@ -6027,7 +6059,7 @@ static void send_to_explorer(int *presel)
if (fd > 1)
close(fd);
} else
@ -152,7 +154,7 @@ index b10143a4..76d6bc5b 100644
}
#endif
@@ -5922,7 +5954,7 @@ static void move_cursor(int target, int ignore_scrolloff)
@@ -6060,7 +6092,7 @@ static void move_cursor(int target, int ignore_scrolloff)
#ifndef NOFIFO
if (!g_state.fifomode)
@ -161,7 +163,7 @@ index b10143a4..76d6bc5b 100644
#endif
}
@@ -6539,7 +6571,7 @@ static bool browse(char *ipath, const char *session, int pkey)
@@ -6733,7 +6765,7 @@ static bool browse(char *ipath, const char *session, int pkey)
pEntry pent;
enum action sel;
struct stat sb;
@ -170,7 +172,7 @@ index b10143a4..76d6bc5b 100644
const uchar_t opener_flags = (cfg.cliopener ? F_CLI : (F_NOTRACE | F_NOSTDIN | F_NOWAIT));
bool watch = FALSE, cd = TRUE;
ino_t inode = 0;
@@ -6797,7 +6829,7 @@ nochange:
@@ -6991,7 +7023,7 @@ nochange:
move_cursor(r, 1);
#ifndef NOFIFO
else if ((event.bstate == BUTTON1_PRESSED) && !g_state.fifomode)
@ -179,7 +181,7 @@ index b10143a4..76d6bc5b 100644
#endif
/* Handle right click selection */
if (event.bstate == BUTTON3_PRESSED) {
@@ -6959,7 +6991,14 @@ nochange:
@@ -7153,7 +7185,14 @@ nochange:
&& strstr(g_buf, "text")
#endif
) {
@ -194,7 +196,7 @@ index b10143a4..76d6bc5b 100644
if (cfg.filtermode) {
presel = FILTER;
clearfilter();
@@ -7272,8 +7311,14 @@ nochange:
@@ -7471,8 +7510,14 @@ nochange:
copycurname();
goto nochange;
case SEL_EDIT:
@ -209,7 +211,7 @@ index b10143a4..76d6bc5b 100644
continue;
default: /* SEL_LOCK */
lock_terminal();
@@ -7642,6 +7687,7 @@ nochange:
@@ -7860,6 +7905,7 @@ nochange:
cd = FALSE;
goto begin;
}
@ -217,7 +219,7 @@ index b10143a4..76d6bc5b 100644
case SEL_PLUGIN:
/* Check if directory is accessible */
if (!xdiraccess(plgpath)) {
@@ -7667,6 +7713,12 @@ nochange:
@@ -7885,6 +7931,12 @@ nochange:
goto nochange;
}
@ -230,13 +232,13 @@ index b10143a4..76d6bc5b 100644
if (tmp[0] == '-' && tmp[1]) {
++tmp;
r = FALSE; /* Do not refresh dir after completion */
@@ -7722,7 +7774,13 @@ nochange:
@@ -7943,7 +7995,13 @@ nochange:
case SEL_SHELL: // fallthrough
case SEL_LAUNCH: // fallthrough
case SEL_PROMPT:
+ if (g_state.previewer)
+ notify_fifo(FALSE, TRUE);
r = handle_cmd(sel, newpath);
r = handle_cmd(sel, path, newpath);
+ if (g_state.previewer) {
+ pkey = previewkey;
+ goto run_plugin;
@ -244,7 +246,7 @@ index b10143a4..76d6bc5b 100644
/* Continue in type-to-nav mode, if enabled */
if (cfg.filtermode)
@@ -8263,8 +8321,10 @@ static void cleanup(void)
@@ -8492,8 +8550,10 @@ static void cleanup(void)
if (g_state.autofifo)
unlink(fifopath);
#endif
@ -256,7 +258,7 @@ index b10143a4..76d6bc5b 100644
#ifdef DEBUG
disabledbg();
#endif
@@ -8769,7 +8829,7 @@ int main(int argc, char *argv[])
@@ -9020,7 +9080,7 @@ int main(int argc, char *argv[])
#ifndef NOFIFO
if (!g_state.fifomode)

View File

@ -29,6 +29,7 @@ awk 'BEGIN {
color_docs=202 #color_docs=173 #color_docs="208;135;112"
color_archive=209 #color_archive=179 #color_archive="235;203;139"
color_c=81 #color_c=150 #color_c="163;190;140"
color_elixir=104 #color_elixir=109 #color_elixir="143;188;187"
color_java=32 #color_java=139 #color_java="180;142;173"
color_js=47 #color_js=109 #color_js="143;188;187"
color_react=39 #color_react=111 #color_react="129;161;193"
@ -44,49 +45,53 @@ awk 'BEGIN {
# icons[][1] contains icon and icons[][2] contains color
icons["directory"][1] = ""; icons["directory"][2] = color_default
icons["file"][1] = ""; icons["file"][2] = color_default
icons["file"][1] = "󰈔"; icons["file"][2] = color_default
icons["exec"][1] = ""; icons["exec"][2] = color_default
icons["manual"][1] = ""; icons["manual"][2] = color_docs
icons["pipe"][1] = ""; icons["pipe"][2] = color_default
icons["socket"][1] = ""; icons["socket"][2] = color_default
icons["manual"][1] = "󱓷"; icons["manual"][2] = color_docs
icons["pipe"][1] = "󰟥"; icons["pipe"][2] = color_default
icons["socket"][1] = "󰟩"; icons["socket"][2] = color_default
icons["door"][1] = "➡"; icons["door"][2] = color_default
# top level and common icons
icons[".git"][1] = ""; icons[".git"][2] = color_default
icons["desktop"][1] = ""; icons["desktop"][2] = color_default
icons["briefcase"][1] = ""; icons["briefcase"][2] = color_default
icons["document"][1] = ""; icons["document"][2] = color_default
icons["downloads"][1] = ""; icons["downloads"][2] = color_default
icons["music"][1] = ""; icons["music"][2] = color_default
icons["musicfile"][1] = ""; icons["musicfile"][2] = color_audio
icons["pictures"][1] = ""; icons["pictures"][2] = color_default
icons["picturefile"][1] = ""; icons["picturefile"][2] = color_image
icons["desktop"][1] = "󰟀"; icons["desktop"][2] = color_default
icons["briefcase"][1] = "󰃖"; icons["briefcase"][2] = color_default
icons["document"][1] = "󰃖"; icons["document"][2] = color_default
icons["downloads"][1] = "󰃘"; icons["downloads"][2] = color_default
icons["music"][1] = "󱍙"; icons["music"][2] = color_default
icons["musicfile"][1] = "󰎈"; icons["musicfile"][2] = color_audio
icons["pictures"][1] = "󰉔"; icons["pictures"][2] = color_default
icons["picturefile"][1] = "󰈟"; icons["picturefile"][2] = color_image
icons["public"][1] = ""; icons["public"][2] = color_default
icons["templates"][1] = ""; icons["templates"][2] = color_default
icons["videos"][1] = ""; icons["videos"][2] = color_default
icons["videofile"][1] = ""; icons["videofile"][2] = color_video
icons["changelog"][1] = ""; icons["changelog"][2] = color_docs
icons["templates"][1] = "󰗇"; icons["templates"][2] = color_default
icons["videos"][1] = "󰈰"; icons["videos"][2] = color_default
icons["videofile"][1] = "󰈫"; icons["videofile"][2] = color_video
icons["changelog"][1] = "󰋚"; icons["changelog"][2] = color_docs
icons["configure"][1] = ""; icons["configure"][2] = color_default
icons["license"][1] = ""; icons["license"][2] = color_docs
icons["makefile"][1] = ""; icons["makefile"][2] = color_default
icons["archive"][1] = ""; icons["archive"][2] = color_archive
icons["license"][1] = "󰈙"; icons["license"][2] = color_docs
icons["makefile"][1] = "󰆍"; icons["makefile"][2] = color_default
icons["archive"][1] = "󰀼"; icons["archive"][2] = color_archive
icons["rust"][1] = ""; icons["rust"][2] = color_default
icons["script"][1] = ""; icons["script"][2] = color_shell
icons["subtitle"][1] = "󰅺"; icons["subtitle"][2] = color_default
icons["cplusplus"][1] = ""; icons["cplusplus"][2] = color_c
icons["java"][1] = ""; icons["java"][2] = color_java
icons["clojure"][1] = ""; icons["clojure"][2] = color_default
icons["js"][1] = ""; icons["js"][2] = color_js
icons["linux"][1] = ""; icons["linux"][2] = color_default
icons["js"][1] = "󰌞"; icons["js"][2] = color_js
icons["linux"][1] = "󰌽"; icons["linux"][2] = color_default
icons["elixir"][1] = ""; icons["elixir"][2] = color_fsharp
icons["fsharp"][1] = ""; icons["fsharp"][2] = color_fsharp
icons["ruby"][1] = ""; icons["ruby"][2] = color_ruby
icons["c"][1] = ""; icons["c"][2] = color_c
icons["chess"][1] = ""; icons["chess"][2] = color_default
icons["chess"][1] = "󰄺"; icons["chess"][2] = color_default
icons["haskell"][1] = ""; icons["haskell"][2] = color_vim
icons["html"][1] = ""; icons["html"][2] = color_default
icons["font"][1] = ""; icons["font"][2] = color_default
icons["html"][1] = "󰌝"; icons["html"][2] = color_default
icons["react"][1] = ""; icons["react"][2] = color_react
icons["python"][1] = ""; icons["python"][2] = color_python
icons["database"][1] = ""; icons["database"][2] = color_default
icons["worddoc"][1] = ""; icons["worddoc"][2] = color_document
icons["playlist"][1] = ""; icons["playlist"][2] = color_audio
icons["database"][1] = "󰆼"; icons["database"][2] = color_default
icons["worddoc"][1] = "󰈬"; icons["worddoc"][2] = color_document
icons["playlist"][1] = "󱍙"; icons["playlist"][2] = color_audio
icons["opticaldisk"][1] = ""; icons["opticaldisk"][2] = color_archive
# numbers
@ -140,6 +145,9 @@ awk 'BEGIN {
icons["elf"][1] = icons["linux"][1]; icons["elf"][2] = icons["linux"][2]
icons["epub"][1] = icons["manual"][1]; icons["epub"][2] = icons["manual"][2]
icons["exe"][1] = icons["exec"][1]; icons["exe"][2] = icons["exec"][2]
icons["ex"][1] = icons["elixir"][1]; icons["ex"][2] = icons["elixir"][2]
icons["eex"][1] = icons["elixir"][1]; icons["eex"][2] = icons["elixir"][2]
icons["exs"][1] = icons["elixir"][1]; icons["exs"][2] = icons["elixir"][2]
# f
icons["fsharp"][1] = icons["fsharp"][1]; icons["fsharp"][2] = icons["fsharp"][2]
@ -154,7 +162,7 @@ awk 'BEGIN {
# g
icons["gem"][1] = icons["ruby"][1]; icons["gem"][2] = icons["ruby"][2]
icons["gif"][1] = icons["picturefile"][1]; icons["gif"][2] = icons["picturefile"][2]
icons["go"][1] = ""; icons["go"][2] = color_default
icons["go"][1] = "󰟓"; icons["go"][2] = color_default
icons["gz"][1] = icons["archive"][1]; icons["gz"][2] = icons["archive"][2]
icons["gzip"][1] = icons["archive"][1]; icons["gzip"][2] = icons["archive"][2]
@ -167,12 +175,14 @@ awk 'BEGIN {
icons["htpasswd"][1] = icons["configure"][1]; icons["htpasswd"][2] = icons["configure"][2]
icons["htm"][1] = icons["html"][1]; icons["htm"][2] = icons["html"][2]
icons["hxx"][1] = icons["cplusplus"][1]; icons["hxx"][2] = icons["cplusplus"][2]
icons["heex"][1] = icons["elixir"][1]; icons["heex"][2] = icons["elixir"][2]
# i
icons["ico"][1] = icons["picturefile"][1]; icons["ico"][2] = icons["picturefile"][2]
icons["img"][1] = icons["opticaldisk"][1]; icons["img"][2] = icons["opticaldisk"][2]
icons["ini"][1] = icons["configure"][1]; icons["ini"][2] = icons["configure"][2]
icons["iso"][1] = icons["opticaldisk"][1]; icons["iso"][2] = icons["opticaldisk"][2]
icons["isub"][1] = icons["subtitle"][1]; icons["isub"][2] = icons["subtitle"][2]
# j
icons["jar"][1] = icons["java"][1]; icons["jar"][2] = icons["java"][2]
@ -180,10 +190,12 @@ awk 'BEGIN {
icons["jl"][1] = icons["configure"][1]; icons["jl"][2] = icons["configure"][2]
icons["jpeg"][1] = icons["picturefile"][1]; icons["jpeg"][2] = icons["picturefile"][2]
icons["jpg"][1] = icons["picturefile"][1]; icons["jpg"][2] = icons["picturefile"][2]
icons["json"][1] = ""; icons["json"][2] = color_js
icons["json"][1] = ""; icons["json"][2] = color_js
icons["jsx"][1] = icons["react"][1]; icons["jsx"][2] = icons["react"][2]
icons["jxl"][1] = icons["picturefile"][1]; icons["jxl"][2] = icons["picturefile"][2]
# k
icons["ksh"][1] = icons["font"][1]; icons["ksf"][2] = icons["font"][2]
# l
icons["lha"][1] = icons["archive"][1]; icons["lha"][2] = icons["archive"][2]
@ -194,7 +206,7 @@ awk 'BEGIN {
icons["lzma"][1] = icons["archive"][1]; icons["lzma"][2] = icons["archive"][2]
# m
icons["m"][1] = ""; icons["mat"][2] = color_c
icons["m"][1] = "󰠞"; icons["mat"][2] = color_c
icons["m4a"][1] = icons["musicfile"][1]; icons["m4a"][2] = icons["musicfile"][2]
icons["m4v"][1] = icons["videofile"][1]; icons["m4v"][2] = icons["videofile"][2]
icons["mat"][1] = ""; icons["mat"][2] = color_c
@ -207,7 +219,7 @@ awk 'BEGIN {
icons["mp4"][1] = icons["videofile"][1]; icons["mp4"][2] = icons["videofile"][2]
icons["mpeg"][1] = icons["videofile"][1]; icons["mpeg"][2] = icons["videofile"][2]
icons["mpg"][1] = icons["videofile"][1]; icons["mpg"][2] = icons["videofile"][2]
icons["msi"][1] = ""; icons["msi"][2] = color_default
icons["msi"][1] = "󰍲"; icons["msi"][2] = color_default
# n
icons["nix"][1] = ""; icons["nix"][2] = color_fsharp
@ -216,17 +228,18 @@ awk 'BEGIN {
icons["o"][1] = icons["manual"][1]; icons["o"][2] = icons["manual"][2]
icons["ogg"][1] = icons["musicfile"][1]; icons["ogg"][2] = icons["musicfile"][2]
icons["odownload"][1] = icons["download"][1]; icons["odownload"][2] = icons["download"][2]
icons["otf"][1] = icons["font"][1]; icons["otf"][2] = icons["font"][2]
icons["out"][1] = icons["linux"][1]; icons["out"][2] = icons["linux"][2]
# p
icons["part"][1] = icons["download"][1]; icons["part"][2] = icons["download"][2]
icons["patch"][1] = icons["diff"][1]; icons["patch"][2] = icons["diff"][2]
icons["pdf"][1] = ""; icons["pdf"][2] = color_docs
icons["pdf"][1] = "󰈦"; icons["pdf"][2] = color_docs
icons["pgn"][1] = icons["chess"][1]; icons["pgn"][2] = icons["chess"][2]
icons["php"][1] = ""; icons["php"][2] = color_default
icons["png"][1] = icons["picturefile"][1]; icons["png"][2] = icons["picturefile"][2]
icons["ppt"][1] = ""; icons["ppt"][2] = color_default
icons["pptx"][1] = ""; icons["pptx"][2] = color_default
icons["ppt"][1] = "󰈧"; icons["ppt"][2] = color_default
icons["pptx"][1] = "󰈧"; icons["pptx"][2] = color_default
icons["psb"][1] = ""; icons["psb"][2] = color_default
icons["psd"][1] = ""; icons["psd"][2] = color_default
icons["py"][1] = icons["python"][1]; icons["py"][2] = icons["python"][2]
@ -239,10 +252,10 @@ awk 'BEGIN {
# r
icons["rar"][1] = icons["archive"][1]; icons["rar"][2] = icons["archive"][2]
icons["rc"][1] = icons["configure"][1]; icons["rc"][2] = icons["configure"][2]
icons["rom"][1] = ""; icons["rom"][2] = color_default
icons["rom"][1] = "󰊖"; icons["rom"][2] = color_default
icons["rpm"][1] = icons["archive"][1]; icons["rpm"][2] = icons["archive"][2]
icons["rss"][1] = ""; icons["rss"][2] = color_default
icons["rtf"][1] = ""; icons["rtf"][2] = color_default
icons["rss"][1] = ""; icons["rss"][2] = color_default
icons["rtf"][1] = "󰈦"; icons["rtf"][2] = color_default
# s
icons["sass"][1] = ""; icons["sass"][2] = color_css
@ -253,18 +266,18 @@ awk 'BEGIN {
icons["slim"][1] = icons["script"][1]; icons["slim"][2] = icons["script"][2]
icons["sln"][1] = ""; icons["sln"][2] = color_default
icons["sql"][1] = icons["database"][1]; icons["sql"][2] = icons["database"][2]
icons["srt"][1] = ""; icons["srt"][2] = color_default
icons["isub"][1] = ""; icons["isub"][2] = color_default
icons["srt"][1] = icons["subtitle"][1]; icons["srt"][2] = icons["subtitle"][2]
icons["svg"][1] = icons["picturefile"][1]; icons["svg"][2] = icons["picturefile"][2]
# t
icons["tar"][1] = icons["archive"][1]; icons["tar"][2] = icons["archive"][2]
icons["tex"][1] = ""; icons["tex"][2] = color_default
icons["tex"][1] = "󰙩"; icons["tex"][2] = color_default
icons["tgz"][1] = icons["archive"][1]; icons["tgz"][2] = icons["archive"][2]
icons["ts"][1] = ""; icons["ts"][2] = color_js
icons["tsx"][1] = icons["react"][1]; icons["tsx"][2] = icons["react"][2]
icons["txt"][1] = icons["document"][1]; icons["txt"][2] = icons["document"][2]
icons["txz"][1] = icons["archive"][1]; icons["txz"][2] = icons["archive"][2]
icons["ttf"][1] = icons["font"][1]; icons["ttf"][2] = icons["font"][2]
# u
@ -272,7 +285,7 @@ awk 'BEGIN {
icons["vid"][1] = icons["videofile"][1]; icons["vid"][2] = icons["videofile"][2]
icons["vim"][1] = ""; icons["vim"][2] = color_vim
icons["vimrc"][1] = ""; icons["vimrc"][2] = color_vim
icons["vtt"][1] = ""; icons["vtt"][2] = color_default
icons["vtt"][1] = icons["subtitle"][1]; icons["vtt"][2] = icons["subtitle"][2]
# w
icons["wav"][1] = icons["musicfile"][1]; icons["wav"][2] = icons["musicfile"][2]
icons["webm"][1] = icons["videofile"][1]; icons["webm"][2] = icons["videofile"][2]
@ -283,8 +296,8 @@ awk 'BEGIN {
icons["xbps"][1] = icons["archive"][1]; icons["xbps"][2] = color_archive
icons["xcf"][1] = icons["picturefile"][1]; icons["xcf"][2] = color_image
icons["xhtml"][1] = icons["html"][1]; icons["xhtml"][2] = icons["html"][2]
icons["xls"][1] = ""; icons["xls"][2] = color_default
icons["xlsx"][1] = ""; icons["xlsx"][2] = color_default
icons["xls"][1] = "󰈛"; icons["xls"][2] = color_default
icons["xlsx"][1] = "󰈛"; icons["xlsx"][2] = color_default
icons["xml"][1] = icons["html"][1]; icons["xml"][2] = icons["html"][2]
icons["xz"][1] = icons["archive"][1]; icons["xz"][2] = icons["archive"][2]

View File

@ -32,7 +32,7 @@ case "$NNN_TRASH" in
2)
RM_UTIL="gio trash" ;;
*)
RM_UTIL="rm -ri" ;;
RM_UTIL="rm -ri --" ;;
esac
exit_status=0
@ -64,7 +64,7 @@ lines=$(printf "%s\n" "$arr" | wc -l)
width=${#lines}
dst_file=$(mktemp "$TMPDIR/.nnnXXXXXX")
trap 'rm -f "$dst_file"' EXIT
trap 'rm -f -- "$dst_file"' EXIT
printf "%s" "$arr" | awk '{printf("%'"${width}"'d %s\n", NR, $0)}' > "$dst_file"
@ -122,7 +122,7 @@ while read -r num name; do
tmp="$tmp~$c"
done
if mv "$name" "$tmp"; then
if mv -- "$name" "$tmp"; then
if [ "$VERBOSE" -ne 0 ]; then
printf "'%s' -> '%s'\n" "$name" "$tmp"
fi
@ -142,7 +142,7 @@ while read -r num name; do
if [ ! -d "$dir" ] && ! mkdir -p "$dir"; then
printf "%s: failed to create directory tree %s\n" "$0" "$dir" > /dev/stderr
exit_status=1
elif ! mv -i "$src" "$name"; then
elif ! mv -i -- "$src" "$name"; then
printf "%s: failed to rename %s to %s: %s\n" "$0" "$name" "$tmp" "$!" > /dev/stderr
exit_status=1
else

View File

@ -16,6 +16,8 @@ Plugins extend the capabilities of `nnn`. They are _executable_ scripts (or bina
| [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 |
@ -39,13 +41,13 @@ Plugins extend the capabilities of `nnn`. They are _executable_ scripts (or bina
| [ipinfo](ipinfo) | Fetch external IP address and whois information | sh | curl, whois |
| [kdeconnect](kdeconnect) | Send selected files to an Android device [✓] | sh | kdeconnect-cli |
| [launch](launch) | GUI application launcher | sh | fzf |
| [mimelist](mimelist) | List files by mime in subtree | sh | - |
| [mimelist](mimelist) | List files by mime in subtree | sh | file/mimetype |
| [moclyrics](moclyrics) | Show lyrics of the track playing in moc | sh | [ddgr](https://github.com/jarun/ddgr), [moc](http://moc.daper.net/) |
| [mocq](mocq) | Queue/play selection/dir/file in moc [✓] | sh | [moc](http://moc.daper.net/) |
| [mp3conv](mp3conv) | Extract audio from multimedia as mp3 | sh | ffmpeg |
| [mtpmount](mtpmount) | Toggle mount of MTP device (eg. Android) | sh | gvfs-mtp |
| [nbak](nbak) | Backs up `nnn` config | sh | tar, awk, mktemp |
| [nmount](nmount) | Toggle mount status of a device as normal user | sh | pmount, udisks2 |
| [nmount](nmount) | Toggle mount status of a device as normal user | sh | pmount (optional), udisks2 |
| [nuke](nuke) | Sample file opener (CLI-only by default) | sh | _see in-file docs_ |
| [oldbigfile](oldbigfile) | List large files by access time | sh | find, sort |
| [openall](openall) | Open selected files together or one by one [✓] | bash | - |
@ -75,11 +77,11 @@ Notes:
- [Installation](#installation)
- [Configuration](#configuration)
- [Skip directory refresh after running a plugin](#skip-directory-refresh-after-running-a-plugin)
- [Running commands as plugin](#running-commands-as-plugin)
- [Skip user confirmation after command execution](#skip-user-confirmation-after-command-execution)
- [Run a GUI app as plugin](#run-a-gui-app-as-plugin)
- [Page non-interactive command output](#page-non-interactive-command-output)
- [Skip directory refresh after running a plugin](#skip-directory-refresh-after-running-a-plugin--)
- [Running commands as plugin](#running-commands-as-plugin-)
- [Skip user confirmation after command execution](#skip-user-confirmation-after-command-execution-)
- [Run a GUI app as plugin](#run-a-gui-app-as-plugin-)
- [Page non-interactive command output](#page-non-interactive-command-output-)
- [Some useful key-command examples](#some-useful-key-command-examples)
- [Access level of plugins](#access-level-of-plugins)
- [Create your own plugins](#create-your-own-plugins)
@ -368,6 +370,10 @@ if [ -n "$pattern" ]; then
fi
```
#### Change directory
NNN_PLUG='c:!read -r to && [ -n "$to" ] && printf "0c%s" "${to}" > "$NNN_PIPE"*'
## Contributing plugins
1. Add informative sections like _Description_, _Notes_, _Dependencies_, _Shell_, _Author_ etc. in the plugin.

View File

@ -29,4 +29,4 @@ $EDITOR "$tmpfile"
sed "/^\//d" "$tmpfile" | xargs -n1 -I{} sh -c "$cmd"
rm "$tmpfile"
rm -- "$tmpfile"

16
plugins/cbcopy-mac Executable file
View File

@ -0,0 +1,16 @@
#!/usr/bin/osascript
# Description: Copy the hovered file to MacOS clipboard.
#
# Note: Supports only MacOS
#
# Shell: POSIX compliant
# Author: Syed Umar Anis
on run args
set filePath to (second item of args & "/" & first item of args)
tell application "Finder"
set the clipboard to (filePath as POSIX file)
end tell
end

24
plugins/cbpaste-mac Executable file
View File

@ -0,0 +1,24 @@
#!/usr/bin/env sh
# shellcheck disable=all
# Description: Paste the clipboard files into the current directory.
# Only works if clipboard contents are files.
#
# Note: Supports only MacOS
#
# Shell: POSIX compliant
# Author: Syed Umar Anis
fs=($( osascript -e "use framework \"Foundation\"
property this : a reference to the current application
property NSPasteboard : a reference to NSPasteboard of this
property NSURL : a reference to NSURL of this
property pb : a reference to NSPasteboard's generalPasteboard
property text item delimiters : linefeed
pb's readObjectsForClasses:[NSURL] options:[]
(result's valueForKey:\"path\") as list as text" ))
cp -R -- "${fs[@]}" "$2/"

View File

@ -25,7 +25,7 @@ dirdiff() {
ls -A1 "$1" > "$dir1"
ls -A1 "$2" > "$dir2"
$diffcmd "$dir1" "$dir2"
rm "$dir1" "$dir2"
rm -- "$dir1" "$dir2"
}
if [ -s "$selection" ]; then

View File

@ -58,13 +58,13 @@ read -r force
if [ "$force" = "f" ]; then
#shellcheck disable=SC2016
sed -e "$sedcmd" "$tmpfile" | tr '\n' '\0' | xargs -0 -r sh -c 'rm -f "$0" "$@" </dev/tty'
sed -e "$sedcmd" "$tmpfile" | tr '\n' '\0' | xargs -0 -r sh -c 'rm -f -- "$0" "$@" </dev/tty'
else
#shellcheck disable=SC2016
sed -e "$sedcmd" "$tmpfile" | tr '\n' '\0' | xargs -0 -r sh -c 'rm -i "$0" "$@" </dev/tty'
sed -e "$sedcmd" "$tmpfile" | tr '\n' '\0' | xargs -0 -r sh -c 'rm -i -- "$0" "$@" </dev/tty'
fi
rm "$tmpfile"
rm -- "$tmpfile"
printf "Press any key to exit"
read -r _

View File

@ -55,7 +55,7 @@ readexpr() {
[ -n "$fexpr" ] && readexpr ;;
\$*) cmd="${fexpr:1}" ;;
*) mapexpr && readexpr
cmd="find $fexpr -print0" ;;
cmd="find . $fexpr -print0" ;;
esac
}
@ -84,6 +84,6 @@ if [ -n "$fexpr" ]; then
if [ -n "$fexpr" ]; then
tail -n"$NNN_FINDHISTLEN" "$NNN_FINDHIST" > "$TMPDIR/finderbms"
printf "%s\n" "$fexpr" >> "$TMPDIR/finderbms"
mv "$TMPDIR/finderbms" "$NNN_FINDHIST"
mv -- "$TMPDIR/finderbms" "$NNN_FINDHIST"
fi
fi

View File

@ -65,7 +65,7 @@ for i in "${targets[@]}"; do
if [ -e "$(cleanup "$i")" ]; then
tmp='_'
fi
mv "$i" "$tmp$(cleanup "$i")";
mv -- "$i" "$tmp$(cleanup "$i")";
fi
done

View File

@ -60,7 +60,7 @@ if [ -n "$LIST" ]; then
# Alternative for 'fd'
# sel=$(xargs -d '\n' < "$tmpfile" fd . | fzf --delimiter / --tiebreak=begin --info=hidden)
rm "$tmpfile"
rm -- "$tmpfile"
else
printf "find missing"
read -r _

View File

@ -3,7 +3,9 @@
# Description: Fuzzy find a command from history,
# edit in $EDITOR and run as a command
#
# Note: Supports only bash and fish history
# Note: Supports only bash, zsh and fish history
#
# TODO: For zsh there's also $ZDOTDIR which might need to be checked as well for the -z $HISTFILE && -n $ZDOTDIR case.
#
# Shell: POSIX compliant
# Author: Arun Prakash Jana
@ -17,7 +19,18 @@ fi
shellname="$(basename "$SHELL")"
if [ "$shellname" = "bash" ]; then
hist_file="$HOME/.bash_history"
if [ -f "$HISTFILE" ]; then
hist_file="$HISTFILE"
else
hist_file="$HOME/.bash_history"
fi
entry="$("$fuzzy" < "$hist_file")"
elif [ "$shellname" = "zsh" ]; then
if [ -f "$HISTFILE" ]; then
hist_file="$HISTFILE"
else
hist_file="$HOME/.zsh_history"
fi
entry="$("$fuzzy" < "$hist_file")"
elif [ "$shellname" = "fish" ]; then
hist_file="$HOME/.local/share/fish/fish_history"
@ -33,7 +46,7 @@ if [ -n "$entry" ]; then
$SHELL -c "$(cat "$tmpfile")"
fi
rm "$tmpfile"
rm -- "$tmpfile"
printf "Press any key to exit"
read -r _

View File

@ -59,25 +59,27 @@ if [ "$3" ]; then
exit 0
fi
if [ "$USE_NUKE" -ne 0 ]; then
"$NUKE" "$entry"
exit 0
fi
if [ "$entry" ]; then
if [ "$USE_NUKE" -ne 0 ]; then
"$NUKE" "$entry"
exit 0
fi
# Open the file (works for a single file only)
cmd_file=""
cmd_open=""
if uname | grep -q "Darwin"; then
cmd_file="file -bIL"
cmd_open="open"
else
cmd_file="file -biL"
cmd_open="xdg-open"
fi
# Open the file (works for a single file only)
cmd_file=""
cmd_open=""
if uname | grep -q "Darwin"; then
cmd_file="file -bIL"
cmd_open="open"
else
cmd_file="file -biL"
cmd_open="xdg-open"
fi
case "$($cmd_file "$entry")" in
*text*)
"${VISUAL:-$EDITOR}" "$entry" ;;
*)
$cmd_open "$entry" >/dev/null 2>&1 ;;
esac
case "$($cmd_file "$entry")" in
*text*)
"${VISUAL:-$EDITOR}" "$entry" ;;
*)
$cmd_open "$entry" >/dev/null 2>&1 ;;
esac
fi

View File

@ -24,7 +24,7 @@ prompt () {
if [ "$operation" = "m" ]; then
op="merge"
elif [ "$operation" = "o" ]; then
op="cp -vRf"
op="cp -vRf --"
else
op="true"
fi
@ -62,7 +62,7 @@ for f in $(find . -maxdepth 1 \( ! -iname "." ! -iname "*.md" \)); do
$op "$f" ../../plugins/
fi
else
cp -vRf "$f" ../../plugins/
cp -vRf -- "$f" ../../plugins/
fi
done
cd ../.. || exit 1

View File

@ -583,7 +583,7 @@ for upload_file in "${upload_files[@]}"; do
# delete file if configured
if [ "${keep_file}" = "false" ] && [ -z "${1}" ]; then
echo "Deleting temp file ${file_dir}/${img_file}"
rm -rf "${img_file}"
rm -rf -- "${img_file}"
fi
echo ""

View File

@ -54,7 +54,7 @@ make_thumbs() {
done
for file in "$NNN_PREVIEWDIR$dir"/*; do
filename="$(basename "$file" .jpg)"
[ ! -e "$dir/$filename" ] && rm "$file" 2>/dev/null
[ ! -e "$dir/$filename" ] && rm -- "$file" 2>/dev/null
done
}

View File

@ -2,8 +2,12 @@
# Description: Find and list files by mime type in smart context
#
# Dependencies:
# - file
# - mimetype (optional, PERL File MimeInfo)
#
# Shell: POSIX compliant
# Author: Arun Prakash Jana
# Author: Arun Prakash Jana, Michel DHOOGE
# shellcheck disable=SC1090,SC1091
. "$(dirname "$0")"/.nnn-plugin-helper
@ -12,4 +16,8 @@ printf "mime (e.g., video/audio/image): "
read -r mime
printf "%s" "+l" > "$NNN_PIPE"
find . | file -if- | grep "$mime" | awk -F: '{printf "%s\0", $1}' > "$NNN_PIPE"
if type mimetype >/dev/null 2>&1; then
find . | mimetype -f - | grep "$mime" | awk -F: '{printf "%s%c", $1, 0}' > "$NNN_PIPE"
else
find . | file -if- | grep "$mime" | awk -F: '{printf "%s%c", $1, 0}' > "$NNN_PIPE"
fi

View File

@ -34,7 +34,7 @@ fi
cd "$tempdir/$outdir" || exit 1
# Backing up config dir content
cp -r "$configdir" . || exit 1
cp -r -- "$configdir" . || exit 1
# Environment config
env | sed "s/'/'\\\\''/" |\
@ -72,4 +72,4 @@ printf "Saving as '%s' ... " "$workdir/$outfile"
tar caf "$workdir/$outfile" "$outdir" && echo "Done" || echo "Failed"
cd "$workdir" && rm -rf "$tempdir"
cd "$workdir" && rm -rf -- "$tempdir"

View File

@ -4,7 +4,7 @@
# If the device is not mounted, it will be mounted.
# If the device is mounted, it will be unmounted and powered down.
#
# Dependencies: lsblk, pmount
# Dependencies: lsblk, pmount (optional), udisks2
#
# Usage: Runs `lsblk` on 'l', exits on 'Return`.
#
@ -13,7 +13,7 @@
# macOS: "diskutil list"
# BSD: "geom disk list"
# - The script uses udisksctl (from udisks2) to power down devices. This is also Linux-specific.
# Users on non-Linux platforms can comment it and use an alterntive to power-down disks.
# Users on non-Linux platforms can comment it and use an alternative to power-down disks.
#
# Shell: POSIX compliant
# Author: Arun Prakash Jana
@ -32,16 +32,48 @@ while [ -n "$dev" ]; do
elif [ "$dev" = "q" ]; then
exit
else
if grep -qs "$dev " /proc/mounts; then
# LUKS volumes mounted with udisksctl appear differently than with pmount
if grep -qs "$dev " /proc/mounts || [ -n "$(lsblk -n "/dev/$dev" -o MOUNTPOINT)" ]; then
sync "$(lsblk -n "/dev/$dev" -o MOUNTPOINT | sed "/^$/d")"
if pumount "/dev/$dev"; then
if type pumount >/dev/null 2>&1; then
pumount "/dev/$dev"
exit_code="$?"
else
# Unlike pmount, udisksctl does not transparently handle LUKS volumes
# We need to manually get the unlocked device, unmount it, and then lock the volume
if lsblk -n "/dev/$dev" -o FSTYPE | grep "crypto_LUKS" >/dev/null; then
dev_map="$(udisksctl info -b /dev/"$dev" | grep "CleartextDevice" | grep -o "dm_2d[[:digit:]]*" | sed "s/_2d/-/")"
udisksctl unmount -b "/dev/$dev_map" --no-user-interaction >/dev/null
exit_code="$?"
udisksctl lock -b "/dev/$dev" --no-user-interaction >/dev/null
else
udisksctl unmount -b "/dev/$dev" --no-user-interaction >/dev/null
exit_code="$?"
fi
fi
if [ $exit_code -eq 0 ]; then
echo "/dev/$dev unmounted."
if udisksctl power-off -b "/dev/$dev" --no-user-interaction; then
echo "/dev/$dev ejected."
fi
fi
elif [ -b "/dev/$dev" ]; then
if pmount "/dev/$dev"; then
if type pmount >/dev/null 2>&1; then
pmount "/dev/$dev"
exit_code="$?"
else
# Unlike pmount, udisksctl does not transparently handle LUKS volumes
# We need to manually get the unlocked device and mount that instead of the volume itself
if [ "$(lsblk "/dev/$dev" -n -o FSTYPE)" = "crypto_LUKS" ]; then
dev_map=$(udisksctl unlock -b "/dev/$dev" --no-user-interaction | grep -o "dm-[[:digit:]]*")
udisksctl mount -b "/dev/$dev_map" --no-user-interaction >/dev/null
exit_code="$?"
else
udisksctl mount -b "/dev/$dev" --no-user-interaction >/dev/null
exit_code="$?"
fi
fi
if [ $exit_code -eq 0 ]; then
sleep 1
echo "/dev/$dev mounted to $(lsblk -n "/dev/$dev" -o MOUNTPOINT | sed "/^$/d")."
fi

View File

@ -271,13 +271,13 @@ abspath() {
listimages() {
find -L "///${1%/*}" -maxdepth 1 -type f -print0 |
grep -izZE '\.(jpe?g|png|gif|webp|tiff|bmp|ico|svg)$' |
sort -z | tee "$tmp"
sort -zV | tee "$tmp"
}
load_dir() {
abspath "$2"
tmp="${TMPDIR:-/tmp}/nuke_$$"
trap 'rm -f $tmp' EXIT
trap 'rm -f -- "$tmp"' EXIT
count="$(listimages "$abs_target" | grep -a -m 1 -ZznF "$abs_target" | cut -d: -f1)"
if [ -n "$count" ]; then
@ -402,7 +402,7 @@ handle_multimedia() {
# "${FPATH}";
# then
# convert -- "${preview_png}" "${IMAGE_CACHE_PATH}" \
# && rm "${preview_png}" \
# && rm -- "${preview_png}" \
# && exit 6
# else
# exit 1

View File

@ -13,36 +13,36 @@ organize() {
case "$(file -biL "$1")" in
*video*)
[ ! -d "Videos" ] && mkdir "Videos"
mv "$1" "Videos/$1"
mv -- "$1" "Videos/$1"
printf "Moved %s to Videos\n" "$1" ;;
*audio*) [ ! -d "Audio" ] && mkdir "Audio"
mv "$1" "Audio/$1"
mv -- "$1" "Audio/$1"
printf "Moved %s to Audio\n" "$1" ;;
*image*)
[ ! -d "Images" ] && mkdir "Images"
mv "$1" "Images/$1"
mv -- "$1" "Images/$1"
printf "Moved %s to Images\n" "$1" ;;
*pdf*|*document*|*epub*|*djvu*|*cb*)
[ ! -d "Documents" ] && mkdir "Documents"
mv "$1" "Documents/$1"
mv -- "$1" "Documents/$1"
printf "Moved %s to Documents\n" "$1" ;;
*text*)
[ ! -d "Plaintext" ] && mkdir "Plaintext"
mv "$1" "Plaintext/$1"
mv -- "$1" "Plaintext/$1"
printf "Moved %s to Plaintext\n" "$1" ;;
*tar*|*xz*|*compress*|*7z*|*rar*|*zip*)
[ ! -d "Archives" ] && mkdir "Archives"
mv "$1" "Archives/$1"
mv -- "$1" "Archives/$1"
printf "Moved %s to Archives\n" "$1" ;;
*binary*)
[ ! -d "Binaries" ] && mkdir "Binaries"
mv "$1" "Binaries/$1"
mv -- "$1" "Binaries/$1"
printf "Moved %s to Binaries\n" "$1" ;;
esac
}

View File

@ -15,7 +15,7 @@ if [ -n "$1" ]; then
pico2wave -w "$tmpf".wav -l en-GB "$(tr '\n' ' ' < "$tmpf".txt)"
rm "$tmpf".txt
rm -- "$tmpf".txt
else
pico2wave -w "$tmpf".wav -l en-GB "$(tr '\n' ' ' < "$1")"
fi
@ -26,5 +26,5 @@ if [ -n "$1" ]; then
# flat read but better quality
# play -qV0 "$tmpf".wav treble 2 gain -l 2
rm "$tmpf".wav
rm -- "$tmpf".wav
fi

View File

@ -4,7 +4,7 @@
#
# Dependencies:
# - tabbed (https://tools.suckless.org/tabbed): xembed host
# - xterm (or urxvt or st) : xembed client for text-based preview
# - xterm (or urxvt or st or alacritty) : xembed client for text-based preview
# - mpv (https://mpv.io): xembed client for video/audio
# - sxiv (https://github.com/muennich/sxiv) or,
# - nsxiv (https://codeberg.org/nsxiv/nsxiv) : xembed client for images
@ -63,10 +63,15 @@ elif type urxvt >/dev/null 2>&1 ; then
TERMINAL="urxvt -embed"
elif type st >/dev/null 2>&1 ; then
TERMINAL="st -w"
elif type alacritty >/dev/null 2>&1 ; then
TERMINAL="alacritty --embed"
else
echo "No xembed term found" >&2
fi
if type xdg-user-dir >/dev/null 2>&1 ; then
PICTURES_DIR=$(xdg-user-dir PICTURES)
fi
term_nuke () {
# $1 -> $XID, $2 -> $FILE
@ -90,7 +95,7 @@ start_tabbed () {
read -r XID < "$FIFO"
rm "$FIFO"
rm -- "$FIFO"
}
get_viewer_pid () {
@ -175,7 +180,17 @@ previewer_loop () {
fi
;;
inode/directory)
$TERMINAL "$XID" -e nnn "$FILE" &
if [[ -n $PICTURES_DIR && "$FILE" == "$PICTURES_DIR"* ]] ; then
if type sxiv >/dev/null 2>&1 ; then
sxiv -te "$XID" "$FILE" &
elif type nsxiv >/dev/null 2>&1 ; then
nsxiv -te "$XID" "$FILE" &
else
$TERMINAL "$XID" -e nnn "$FILE" &
fi
else
$TERMINAL "$XID" -e nnn "$FILE" &
fi
;;
text/*)
if [ -x "$NUKE" ] ; then

View File

@ -1,4 +1,4 @@
#!/usr/bin/env sh
#!/usr/bin/env bash
# Description: Terminal based file previewer
#
@ -13,7 +13,7 @@
# - Windows Terminal (https://github.com/Microsoft/Terminal | https://aka.ms/terminal) with WSL, or
# - $NNN_TERMINAL set to a terminal (it's xterm by default).
# - less or $NNN_PAGER
# - tree or exa or ls
# - tree or exa/eza or (GNU) ls
# - mediainfo or file
# - mktemp
# - unzip
@ -21,8 +21,12 @@
# - man
# - optional: bsdtar or atool for additional archive preview
# - optional: bat for code syntax highlighting
# - optional: ueberzug, kitty terminal, wezterm terminal, viu, catimg or chafa for images
# - optional: convert(ImageMagick) for playing gif preview (required for kitty image previews)
# - optional: ueberzug, kitty terminal, wezterm terminal, img2sixel, viu, catimg or chafa for images
# - optional: convert(ImageMagick) for playing gif preview (mandatory for kitty image previews)
# - optional: mpv for gif and video
# Also requires a terminal supporting the sixel (https://www.arewesixelyet.com/)
# or kitty (https://sw.kovidgoyal.net/kitty/graphics-protocol) video_output backends.
# Requires tmux compiled with `./configure --enable-sixel` if used.
# - optional: ffmpegthumbnailer for video thumbnails (https://github.com/dirkvdb/ffmpegthumbnailer)
# - optional: ffmpeg for audio thumbnails
# - optional: libreoffce for opendocument/officedocument preview
@ -40,6 +44,7 @@
# - optional: pistol file viewer (https://github.com/doronbehar/pistol).
# 1. install pistol
# 2. set/export $NNN_PISTOL as 1
# - optional: librsvg for rsvg-convert
#
# Usage:
# You need to set a NNN_FIFO path and a key for the plugin with NNN_PLUG,
@ -61,10 +66,6 @@
# will try to use a kitty terminal split. And as a final fallback, a
# different terminal window will be used ($NNN_TERMINAL).
#
# Tmux, wezterm and kitty users can configure $NNN_SPLIT to either "h" or "v" to set a
# 'h'orizontal split or a 'v'ertical split (as in, the line that splits the
# windows will be horizontal or vertical).
#
# Kitty users need something similar to the following in their kitty.conf:
# - `allow_remote_control yes`
# - `listen_on unix:$TMPDIR/kitty`
@ -72,111 +73,128 @@
# With ImageMagick installed, this terminal can use the icat kitten to display images.
# Refer to kitty documentation for further details.
#
# Users with both tmux and kitty can leverage image previews inside tmux with kitty's icat kitten
# - setup kitty as stated above
# - tmux >= v3.3a required
# - add the following to your tmux.conf:
# - `set -g allow-passthrough on`
#
# Wezterm should work out of the box. If `NNN_PREVIEWIMGPROG` is not specified it will use
# built in iTerm2 image protocol.
#
# Iterm2 users are recommended to use viu to view images without getting pixelated.
# Note that GNU ls is used for its `--group-directories-first` flag.
# On MacOS this may be installed with `brew install coreutils`, or the flag can be removed.
# iTerm2 users are recommended to use viu to view images without getting pixelated.
#
# Windows Terminal users can set "Profile termination behavior" under "Profile > Advanced" settings
# to automatically close pane on quit when exit code is 0.
#
# Shell: POSIX compliant
# Authors: Todd Yamakawa, Léo Villeveygoux, @Recidiviste, Mario Ortiz Manero, Luuk van Baal, @WanderLanz
# When specifying a different terminal, additional arguments are supported. In particular, you can
# append a specific title to the terminal and set it to "nofocus" in your WM config.
# E.g for alacritty and i3, you can set $NNN_TERMINAL to 'alacritty --title preview-tui' and add
# 'no_focus [title="preview-tui"]' to your i3 config file.
#
# Shell: Bash (for environment manipulation through arrays)
# Authors: Todd Yamakawa, Léo Villeveygoux, @Recidiviste, Mario Ortiz Manero, Luuk van Baal, @WanderLanz, @flipflop133
NNN_SPLIT=${NNN_SPLIT:-} # Set permanent split direction
NNN_TERMINAL=${NNN_TERMINAL:-} # Set external terminal to be used
NNN_SPLITSIZE=${NNN_SPLITSIZE:-50} # Set previewer split size percentage
TMPDIR=${TMPDIR:-/tmp}
# Configurable environment variables:
NNN_SPLIT=${NNN_SPLIT:-} # permanent split direction
NNN_TERMINAL=${NNN_TERMINAL:-} # external terminal to be used
NNN_SPLITSIZE=${NNN_SPLITSIZE:-50} # previewer split size percentage
TMPDIR=${TMPDIR:-/tmp} # location of temporary files
ENVVARS=(
"NNN_SCOPE=${NNN_SCOPE:-0}" # use scope
"NNN_PISTOL=${NNN_PISTOL:-0}" # use pistol
"NNN_ICONLOOKUP=${NNN_ICONLOOKUP:-0}" # use .iconlookup
"NNN_PAGER=${NNN_PAGER:-less -P?n -R -C}" # pager options
"NNN_BATTHEME=${NNN_BATTHEME:-ansi}" # bat theme
"NNN_BATSTYLE=${NNN_BATSTYLE:-numbers}" # bat style
"NNN_PREVIEWWIDTH=${NNN_PREVIEWWIDTH:-1920}" # width of generated preview images
"NNN_PREVIEWHEIGHT=${NNN_PREVIEWHEIGHT:-1080}" # height of generated preview images
"NNN_PREVIEWDIR=${NNN_PREVIEWDIR:-$TMPDIR/nnn/previews}" # location of generated preview images
"NNN_PREVIEWIMGPROG=${NNN_PREVIEWIMGPROG:-}" # program used to preview images
"NNN_PREVIEWVIDEO=${NNN_PREVIEWVIDEO:-}" # mpv backend used to preview video
)
# Non-configurable environment variables
NNN_PARENT=${NNN_FIFO#*.}
[ "$NNN_PARENT" -eq "$NNN_PARENT" ] 2>/dev/null || NNN_PARENT="" # Make empty if non-numeric
ENVVARS="
PWD=$PWD
PATH=$PATH
PREVIEW_MODE=$2
NNN_FIFO=$NNN_FIFO
NNN_SCOPE=${NNN_SCOPE:-0}
NNN_PISTOL=${NNN_PISTOL:-0}
NNN_ICONLOOKUP=${NNN_ICONLOOKUP:-0}
NNN_PAGER=${NNN_PAGER:-less -P?n -R}
NNN_BATTHEME=${NNN_BATTHEME:-ansi}
NNN_BATSTYLE=${NNN_BATSTYLE:-numbers}
NNN_PREVIEWWIDTH=${NNN_PREVIEWWIDTH:-1920}
NNN_PREVIEWHEIGHT=${NNN_PREVIEWHEIGHT:-1080}
NNN_PREVIEWDIR=${NNN_PREVIEWDIR:-$TMPDIR/nnn/previews}
NNN_PREVIEWIMGPROG=${NNN_PREVIEWIMGPROG:-}
FIFOPID=$TMPDIR/nnn-preview-tui-fifopid.$NNN_PARENT
FIFOPATH=$TMPDIR/nnn-preview-tui-fifo.$NNN_PARENT
PREVIEWPID=$TMPDIR/nnn-preview-tui-previewpid.$NNN_PARENT
CURSEL=$TMPDIR/nnn-preview-tui-selection.$NNN_PARENT
FIFO_UEBERZUG=$TMPDIR/nnn-preview-tui-ueberzug-fifo.$NNN_PARENT
POSOFFSET=$TMPDIR/nnn-preview-tui-posoffset"
if [ -e "${TMUX%%,*}" ] && tmux -V | grep -q '[ -][3456789]\.'; then
NNN_TERMINAL=tmux
elif [ -n "$KITTY_LISTEN_ON" ]; then
NNN_TERMINAL=kitty
elif [ -n "$WEZTERM_PANE" ]; then
NNN_TERMINAL=wezterm
elif [ -z "$NNN_TERMINAL" ] && [ "$TERM_PROGRAM" = "iTerm.app" ]; then
NNN_TERMINAL=iterm
elif [ -n "$WT_SESSION" ]; then
NNN_TERMINAL=winterm
else
NNN_TERMINAL="${NNN_TERMINAL:-xterm}"
fi
if [ -z "$NNN_SPLIT" ] && [ $(($(tput lines) * 2)) -gt "$(tput cols)" ]; then
NNN_SPLIT='h'
elif [ "$NNN_SPLIT" != 'h' ]; then
NNN_SPLIT='v'
fi
ENVVARS="$ENVVARS
NNN_SPLIT=$NNN_SPLIT
NNN_TERMINAL=$NNN_TERMINAL"
IFS='
'
for env in $ENVVARS; do
export "${env?}"
case "$NNN_TERMINAL" in
tmux) ENVSTRING="$ENVSTRING -e '$env'" ;;
kitty) ENVSTRING="$ENVSTRING --env '$env'" ;;
winterm|iterm) ENVSTRING="$ENVSTRING \\\"$env\\\"" ;;
*) ENVSTRING="$ENVSTRING $env";;
esac
done; unset IFS
ENVVARS+=(
"PWD=$PWD"
"PATH=$PATH"
"NNN_FIFO=$NNN_FIFO"
"FIFOPID=$TMPDIR/nnn-preview-tui-fifopid.$NNN_PARENT"
"FIFOPATH=$TMPDIR/nnn-preview-tui-fifo.$NNN_PARENT"
"PREVIEWPID=$TMPDIR/nnn-preview-tui-previewpid.$NNN_PARENT"
"CURSEL=$TMPDIR/nnn-preview-tui-selection.$NNN_PARENT"
"FIFO_UEBERZUG=$TMPDIR/nnn-preview-tui-ueberzug-fifo.$NNN_PARENT"
"POSOFFSET=$TMPDIR/nnn-preview-tui-posoffset"
)
trap '' PIPE
exists() { type "$1" >/dev/null 2>&1 ;}
pkill() { command pkill "$@" >/dev/null 2>&1 ;}
prompt() { printf "%b" "$@"; cfg=$(stty -g); stty raw -echo; head -c 1; stty "$cfg" ;}
prompt() { clear; printf "%b" "$@"; cfg=$(stty -g); stty raw -echo; head -c 1; stty "$cfg" ;}
pidkill() {
if [ -f "$1" ]; then
PID="$(cat "$1" 2>/dev/null)" || return 1
kill "$PID" >/dev/null 2>&1
RET=$?
wait "$PID" 2>/dev/null
return $RET
fi
return 1
if [ -f "$1" ]; then
PID="$(cat "$1" 2>/dev/null)" || return 1
kill "$PID" >/dev/null 2>&1
RET=$?
wait "$PID" 2>/dev/null
return $RET
fi
return 1
}
start_preview() {
if [ -e "${TMUX%%,*}" ] && tmux -V | grep -q '[ -][3456789]\.'; then
NNN_TERMINAL=tmux
exists mpv && tmux display -p '#{client_termfeatures}' | grep -q 'sixel' && ENVVARS+=("NNN_PREVIEWVIDEO=sixel")
elif [ -n "$KITTY_LISTEN_ON" ]; then
NNN_TERMINAL=kitty
exists mpv && ENVVARS+=("NNN_PREVIEWVIDEO=kitty")
elif [ -n "$WEZTERM_PANE" ]; then
NNN_TERMINAL=wezterm
exists mpv && ENVVARS+=("NNN_PREVIEWVIDEO=kitty")
elif [ -z "$NNN_TERMINAL" ] && [ "$TERM_PROGRAM" = "iTerm.app" ]; then
NNN_TERMINAL=iterm
exists mpv && ENVVARS+=("NNN_PREVIEWVIDEO=sixel")
elif [ -n "$WT_SESSION" ]; then
NNN_TERMINAL=winterm
else
NNN_TERMINAL="${NNN_TERMINAL:-xterm}"
fi
if [ -z "$NNN_SPLIT" ] && [ $(($(tput lines) * 2)) -gt "$(tput cols)" ]; then
NNN_SPLIT='h'
elif [ "$NNN_SPLIT" != 'h' ]; then
NNN_SPLIT='v'
fi
ENVVARS+=("NNN_TERMINAL=$NNN_TERMINAL" "NNN_SPLIT=$NNN_SPLIT" "QLPATH=$2" "PREVIEW_MODE=1")
case "$NNN_TERMINAL" in
iterm|winterm) # has to run in separate shell command: escape
ENVVARS=("${ENVVARS[@]/#/\\\"}")
ENVVARS=("${ENVVARS[@]/%/\\\"}")
command="$SHELL -c 'env ${ENVVARS[*]} \\\"$0\\\" \\\"$1\\\"'" ;;
esac
case "$NNN_TERMINAL" in
tmux) # tmux splits are inverted
ENVVARS=("${ENVVARS[@]/#/-e}")
if [ "$NNN_SPLIT" = "v" ]; then split="h"; else split="v"; fi
eval tmux split-window "$ENVSTRING" -d"$split" -p"$NNN_SPLITSIZE" "$0" "$1" 1 ;;
tmux split-window -l"$NNN_SPLITSIZE"% "${ENVVARS[@]}" -d"$split" -p"$NNN_SPLITSIZE" "$0" "$1" ;;
kitty) # Setting the layout for the new window. It will be restored after the script ends.
ENVVARS=("${ENVVARS[@]/#/--env=}")
kitty @ goto-layout splits
# Trying to use kitty's integrated window management as the split window.
eval kitty @ launch --no-response --title "preview-tui" --keep-focus \
--cwd "$PWD" "$ENVSTRING" --location "${NNN_SPLIT}split" "$0" "$1" 1 ;;
kitty @ launch --no-response --title "preview-tui" --keep-focus \
--cwd "$PWD" "${ENVVARS[@]}" --location "${NNN_SPLIT}split" "$0" "$1" ;;
wezterm)
export "${ENVVARS[@]}"
if [ "$NNN_SPLIT" = "v" ]; then split="--horizontal"; else split="--bottom"; fi
wezterm cli split-pane --cwd "$PWD" $split "$0" "$1" 1 >/dev/null
wezterm cli split-pane --cwd "$PWD" $split --percent "$NNN_SPLITSIZE" "$0" "$1" >/dev/null
wezterm cli activate-pane-direction Prev ;;
iterm)
command="$SHELL -c 'cd $PWD; env $ENVSTRING $0 $1 1'"
if [ "$NNN_SPLIT" = "h" ]; then split="horizontally"; else split="vertically"; fi
osascript <<-EOF
tell application "iTerm"
@ -188,17 +206,18 @@ EOF
;;
winterm)
if [ "$NNN_SPLIT" = "h" ]; then split="H"; else split="V"; fi
cmd.exe /c wt -w 0 sp -$split -s"0.$NNN_SPLITSIZE" bash -c "cd $PWD \; \
env $ENVSTRING QLPATH=$2 $0 $1 1" \; -w 0 mf previous 2>/dev/null ;;
wt -w 0 sp -$split -s"0.$NNN_SPLITSIZE" "$command" \; -w 0 mf previous 2>/dev/null ;;
*) if [ -n "$2" ]; then
env "$ENVSTRING" QUICKLOOK=1 QLPATH="$2" "$0" "$1" 1 &
env "${ENVVARS[@]}" QUICKLOOK=1 "$0" "$1" &
else
env "$ENVSTRING" "$NNN_TERMINAL" -e "$0" "$1" 1 &
# shellcheck disable=SC2086 # (allow arguments)
env "${ENVVARS[@]}" $NNN_TERMINAL -e "$0" "$1" &
fi ;;
esac
}
toggle_preview() {
export "${ENVVARS[@]}"
if exists QuickLook.exe; then
QLPATH="QuickLook.exe"
elif exists Bridge.exe; then
@ -241,7 +260,7 @@ fifo_pager() {
fi
)
rm "$FIFOPATH"
rm -- "$FIFOPATH"
}
# Binary file: show file info inside the pager
@ -350,7 +369,9 @@ preview_file() {
elif exists tree; then
fifo_pager tree --filelimit "$(find . -maxdepth 1 | wc -l)" -L 3 -C -F --dirsfirst --noreport
elif exists exa; then
exa -G --group-directories-first --colour=always
fifo_pager exa -T --group-directories-first --colour=always -L 3
elif exists eza; then # eza is a community fork of exa (exa is unmaintained)
fifo_pager eza -T --group-directories-first --colour=always -L 3
else
fifo_pager ls -F --group-directories-first --color=always
fi
@ -365,6 +386,9 @@ preview_file() {
generate_preview() {
if [ -n "$QLPATH" ] && stat "$3"; then
f="$(wslpath -w "$3")" && "$QLPATH" "$f" &
elif [ -n "$NNN_PREVIEWVIDEO" ] && [[ "$4" == +(gif|video) ]]; then
[ "$4" = "video" ] && args=(--start=10% --length=4) || args=()
video_preview "$1" "$2" "$3" "${args[@]}" && return
elif [ ! -f "$NNN_PREVIEWDIR/$3.jpg" ] || [ -n "$(find -L "$3" -newer "$NNN_PREVIEWDIR/$3.jpg")" ]; then
mkdir -p "$NNN_PREVIEWDIR/${3%/*}"
case $4 in
@ -388,25 +412,30 @@ generate_preview() {
done &
printf "%s" "$!" > "$PREVIEWPID"
return
elif [ -n "$NNN_PREVIEWVIDEO" ]; then
video_preview "$1" "$2" "$3" && return
else
image_preview "$1" "$2" "$3"
return
image_preview "$1" "$2" "$3" && return
fi ;;
image) if exists convert; then
image) if exists rsvg-convert && [[ "${3##*.}" == "svg" ]]; then
rsvg-convert -a -w "$NNN_PREVIEWWIDTH" -h "$NNN_PREVIEWHEIGHT" -f png -o "$NNN_PREVIEWDIR/$3.png" "$3"
elif exists convert; then
convert "$3" -flatten -resize "$NNN_PREVIEWWIDTH"x"$NNN_PREVIEWHEIGHT"\> "$NNN_PREVIEWDIR/$3.jpg"
else
image_preview "$1" "$2" "$3" && return
fi ;;
office) libreoffice --convert-to jpg "$3" --outdir "$NNN_PREVIEWDIR/${3%/*}"
filename="$(printf "%s" "${3##*/}" | cut -d. -f1)"
mv "$NNN_PREVIEWDIR/${3%/*}/$filename.jpg" "$NNN_PREVIEWDIR/$3.jpg" ;;
mv -- "$NNN_PREVIEWDIR/${3%/*}/$filename.jpg" "$NNN_PREVIEWDIR/$3.jpg" ;;
pdf) pdftoppm -jpeg -f 1 -singlefile "$3" "$NNN_PREVIEWDIR/$3" ;;
djvu) ddjvu -format=ppm -page=1 "$3" "$NNN_PREVIEWDIR/$3.jpg" ;;
video) ffmpegthumbnailer -m -s0 -i "$3" -o "$NNN_PREVIEWDIR/$3.jpg" || rm "$NNN_PREVIEWDIR/$3.jpg" ;;
video) video_preview "$1" "$2" "$3" && return ;;
esac
fi
if [ -f "$NNN_PREVIEWDIR/$3.jpg" ]; then
image_preview "$1" "$2" "$NNN_PREVIEWDIR/$3.jpg"
elif [[ "${3##*.}" == "svg" ]] && [ -f "$NNN_PREVIEWDIR/$3.png" ]; then
image_preview "$1" "$2" "$NNN_PREVIEWDIR/$3.png"
else
fifo_pager print_bin_info "$3"
fi
@ -415,25 +444,39 @@ generate_preview() {
image_preview() {
clear
exec >/dev/tty
if [ "$NNN_TERMINAL" = "kitty" ]; then
# Kitty terminal users can use the native image preview method
if [ "$NNN_TERMINAL" = "kitty" ] && [[ "$NNN_PREVIEWIMGPROG" == +(|icat) ]]; then
kitty +kitten icat --silent --scale-up --place "$1"x"$2"@0x0 --transfer-mode=stream --stdin=no "$3" &
elif [ "$NNN_TERMINAL" = "wezterm" ] && [ -z "$NNN_PREVIEWIMGPROG" ]; then
elif [ "$NNN_TERMINAL" = "tmux" ] && [[ -n "$KITTY_LISTEN_ON" ]] && [[ "$NNN_PREVIEWIMGPROG" == +(|icat) ]]; then
kitty +kitten icat --silent --scale-up --place "$(($1 - 1))x$(($2 - 1))"@0x0 --transfer-mode=memory --stdin=no "$3" &
elif [ "$NNN_TERMINAL" = "wezterm" ] && [[ "$NNN_PREVIEWIMGPROG" == +(|imgcat) ]]; then
wezterm imgcat "$3" &
elif exists ueberzug && { [ -z "$NNN_PREVIEWIMGPROG" ] || [ "$NNN_PREVIEWIMGPROG" = "ueberzug" ] ;}; then
elif exists ueberzug && [[ "$NNN_PREVIEWIMGPROG" == +(|ueberzug) ]]; then
ueberzug_layer "$1" "$2" "$3" && return
elif exists catimg && { [ -z "$NNN_PREVIEWIMGPROG" ] || [ "$NNN_PREVIEWIMGPROG" = "catimg" ] ;}; then
elif exists catimg && [[ "$NNN_PREVIEWIMGPROG" == +(|catimg) ]]; then
catimg "$3" &
elif exists viu && { [ -z "$NNN_PREVIEWIMGPROG" ] || [ "$NNN_PREVIEWIMGPROG" = "viu" ] ;}; then
elif exists viu && [[ "$NNN_PREVIEWIMGPROG" == +(|viu) ]]; then
viu -t "$3" &
elif exists chafa && { [ -z "$NNN_PREVIEWIMGPROG" ] || [ "$NNN_PREVIEWIMGPROG" = "chafa" ] ;}; then
elif exists chafa && [[ "$NNN_PREVIEWIMGPROG" == +(|chafa) ]]; then
chafa "$3" &
elif exists img2sixel && [[ "$NNN_PREVIEWIMGPROG" == +(|img2sixel) ]]; then
img2sixel -g "$3" &
else
fifo_pager print_bin_info "$3" && return
fi
printf "%s" "$!" > "$PREVIEWPID"
}
video_preview() {
clear
exec >/dev/tty
if [ -n "$NNN_PREVIEWVIDEO" ]; then
mpv --no-config --really-quiet --vo="$NNN_PREVIEWVIDEO" --profile=sw-fast --loop-file --no-audio "$4" "$3" &
else
ffmpegthumbnailer -m -s0 -i "$3" -o "$NNN_PREVIEWDIR/$3.jpg" || rm -- "$NNN_PREVIEWDIR/$3.jpg" &
fi
printf "%s" "$!" > "$PREVIEWPID"
}
ueberzug_layer() {
[ -f "$POSOFFSET" ] && read -r x y < "$POSOFFSET"
printf '{"action": "add", "identifier": "nnn_ueberzug", "x": %d, "y": %d, "width": "%d", "height": "%d", "scaler": "fit_contain", "path": "%s"}\n'\
@ -469,25 +512,25 @@ preview_fifo() {
}
if [ "$PREVIEW_MODE" -eq 1 ] 2>/dev/null; then
if [ "$NNN_TERMINAL" != "kitty" ] && exists ueberzug; then
if exists ueberzug && [ "$NNN_TERMINAL" != "kitty" ] && [[ "$NNN_PREVIEWIMGPROG" == +(|ueberzug) ]]; then
mkfifo "$FIFO_UEBERZUG"
tail --follow "$FIFO_UEBERZUG" | ueberzug layer --silent --parser json &
fi
preview_file "$PWD/$1"
preview_fifo &
preview_fifo & WAITPID=$!
printf "%s" "$!" > "$FIFOPID"
printf "%s" "$PWD/$1" > "$CURSEL"
trap 'winch_handler; wait' WINCH
trap 'rm "$PREVIEWPID" "$CURSEL" "$FIFO_UEBERZUG" "$FIFOPID" "$POSOFFSET" 2>/dev/null' INT HUP EXIT
wait "$!" 2>/dev/null
trap 'winch_handler' WINCH
trap 'rm -- "$PREVIEWPID" "$CURSEL" "$FIFO_UEBERZUG" "$FIFOPID" "$POSOFFSET" 2>/dev/null' INT HUP EXIT
while kill -s 0 $WAITPID; do
wait $WAITPID 2>/dev/null
done
exit 0
else
if [ ! -r "$NNN_FIFO" ]; then
clear
prompt "No FIFO available! (\$NNN_FIFO='$NNN_FIFO')\nPlease read Usage in '$0'."
elif [ "$KITTY_WINDOW_ID" ] && [ -z "$TMUX" ] && [ -z "$KITTY_LISTEN_ON" ]; then
clear
prompt "\$KITTY_LISTEN_ON not set!\nPlease read Usage in '$0'."
else
toggle_preview "$1" &

View File

@ -8,11 +8,19 @@
# Shell: POSIX compliant
# Author: juacq97
resp=
if [ -n "$1" ]; then
if [ "$(file --mime-type "$1" | awk '{print $NF}' | awk -F '/' '{print $1}')" = "image" ]; then
if [ "$XDG_SESSION_TYPE" = "x11" ]; then
if type nitrogen >/dev/null 2>&1; then
nitrogen --set-zoom-fill --save "$1"
printf "Set to full desktop or a specific monitors? [0, 1, etc. Defaults to full.]"
read -r resp
if [ "$resp" != "" ]; then
nitrogen --set-zoom-fill --save "$1" --head="$resp"
else
nitrogen --set-zoom-fill --save "$1"
fi
elif type wal >/dev/null 2>&1; then
wal -i "$1"
else

View File

@ -1,5 +1,35 @@
---
Checks: 'clang-diagnostic-*,clang-analyzer-*,readability-*,modernize-*,bugprone-*,misc-*,-misc-unused-parameters,google-runtime-int,-llvm-header-guard,fuchsia-restrict-system-includes,-clang-analyzer-valist.Uninitialized,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,-clang-analyzer-security.insecureAPI.rand,-clang-analyzer-alpha.*,-modernize-macro-to-enum,-readability-magic-numbers,-readability-braces-around-statements,-readability-function-cognitive-complexity,-readability-identifier-length,-readability-isolate-declaration,-readability-suspicious-call-argument,-bugprone-easily-swappable-parameters,-bugprone-narrowing-conversions,-bugprone-reserved-identifier'
Checks: >
clang-diagnostic-*,
clang-analyzer-*,
readability-*,
modernize-*,
bugprone-*,
misc-*,
google-runtime-int,
fuchsia-restrict-system-includes,
-misc-unused-parameters,
-misc-include-cleaner,
-llvm-header-guard,
-clang-analyzer-valist.Uninitialized,
-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
-clang-analyzer-security.insecureAPI.rand,
-clang-analyzer-alpha.*,
-modernize-macro-to-enum,
-readability-magic-numbers,
-readability-braces-around-statements,
-readability-function-cognitive-complexity,
-readability-identifier-length,
-readability-isolate-declaration,
-readability-suspicious-call-argument,
-readability-avoid-nested-conditional-operator,
-bugprone-easily-swappable-parameters,
-bugprone-narrowing-conversions,
-bugprone-reserved-identifier,
-bugprone-switch-missing-default-case,
-bugprone-inc-dec-in-conditions,
-bugprone-multi-level-implicit-pointer-conversion,
WarningsAsErrors: '*'
HeaderFilterRegex: '.*(?<!lookup3.c)$'
FormatStyle: 'file'

View File

@ -21,17 +21,19 @@
*/
#ifdef ICONS_GENERATE
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include "icons.h"
#ifdef NDEBUG
#error "The hash-table generator relies on assert() to verify correctness."
#endif
#define ASSERT(X) assert(X)
/* like assert, but always sticks around during generation. */
#define ENSURE(X) do { \
if (!(X)) { \
fprintf(stderr, "%s:%d: `%s`\n", __FILE__, __LINE__, #X); \
abort(); \
} \
} while (0)
#define ARRLEN(X) (sizeof(X) / sizeof((X)[0]))
#define MAX(A, B) ((A) > (B) ? (A) : (B))
#define HGEN_ITERARATION (1ul << 13)
@ -61,13 +63,13 @@ static uint32_t hash_mul = 251; /* unused as of now */
static void
rh_insert(const struct icon_pair item, uint32_t idx, uint32_t n)
{
assert(n != 0);
ENSURE(n != 0);
for (uint32_t tries = 0; tries < ARRLEN(table); ++tries, ++n) {
if (seen[idx] < n) {
struct icon_pair tmp_item = table[idx];
uint32_t tmp_n = seen[idx];
assert(n < (uint8_t)-1);
ENSURE(n < (uint8_t)-1);
table[idx] = item;
seen[idx] = n;
@ -77,7 +79,7 @@ rh_insert(const struct icon_pair item, uint32_t idx, uint32_t n)
}
idx = (idx + 1) % ARRLEN(table);
}
assert(0); /* unreachable */
ENSURE(0 && "unreachable");
}
enum { PROBE_MAX, PROBE_TOTAL, PROBE_CNT };
@ -115,17 +117,17 @@ pcg(uint64_t *state)
int
main(void)
{
assert(ARRLEN(icons_ext) <= ARRLEN(table));
assert(ICONS_TABLE_SIZE < 16);
assert(1u << ICONS_TABLE_SIZE == ARRLEN(table));
assert((GOLDEN_RATIO_32 & 1) == 1); /* must be odd */
assert((GOLDEN_RATIO_64 & 1) == 1); /* must be odd */
assert(hash_start > 1);
assert(hash_mul > 1);
ENSURE(ARRLEN(icons_ext) <= ARRLEN(table));
ENSURE(ICONS_TABLE_SIZE < 16);
ENSURE(1u << ICONS_TABLE_SIZE == ARRLEN(table));
ENSURE((GOLDEN_RATIO_32 & 1) == 1); /* must be odd */
ENSURE((GOLDEN_RATIO_64 & 1) == 1); /* must be odd */
ENSURE(hash_start > 1);
ENSURE(hash_mul > 1);
/* ensure power of 2 hashtable size which allows compiler to optimize
* away mod (`%`) operations
*/
assert((ARRLEN(table) & (ARRLEN(table) - 1)) == 0);
ENSURE((ARRLEN(table) & (ARRLEN(table) - 1)) == 0);
unsigned int max_probe = (unsigned)-1;
uint32_t best_hash_start = 0, best_hash_mul = 0, best_total_probe = 9999;
@ -144,13 +146,13 @@ main(void)
hash_start = pcg(&hash_start_rng);
hash_mul = pcg(&hash_mul_rng);
}
assert(max_probe < ICONS_PROBE_MAX_ALLOWED);
ENSURE(max_probe < ICONS_PROBE_MAX_ALLOWED);
hash_start = best_hash_start;
hash_mul = best_hash_mul;
{
unsigned *p = table_populate((unsigned [PROBE_CNT]){0});
assert(p[PROBE_MAX] == max_probe);
assert(p[PROBE_TOTAL] == best_total_probe);
ENSURE(p[PROBE_MAX] == max_probe);
ENSURE(p[PROBE_TOTAL] == best_total_probe);
}
/* sanity check */
@ -168,10 +170,10 @@ main(void)
break;
}
}
assert(found);
ENSURE(found);
++nitems;
}
assert(total_probe == best_total_probe);
ENSURE(total_probe == best_total_probe);
size_t match_max = 0, icon_max = 0;
for (size_t i = 0; i < ARRLEN(icons_name); ++i) {
@ -185,7 +187,7 @@ main(void)
icon_max = MAX(icon_max, strlen(dir_icon.icon) + 1);
icon_max = MAX(icon_max, strlen(exec_icon.icon) + 1);
icon_max = MAX(icon_max, strlen(file_icon.icon) + 1);
assert(icon_max < ICONS_MATCH_MAX);
ENSURE(icon_max < ICONS_MATCH_MAX);
const char *uniq[ARRLEN(icons_ext)] = {0};
size_t uniq_head = 0;
@ -200,11 +202,11 @@ main(void)
}
}
if (isuniq) {
assert(uniq_head < ARRLEN(uniq));
ENSURE(uniq_head < ARRLEN(uniq));
uniq[uniq_head++] = icons_ext[i].icon;
}
}
assert(uniq_head < (unsigned char)-1);
ENSURE(uniq_head < (unsigned char)-1);
log("load-factor: %.2f (%u/%zu)\n", (nitems * 100.0) / (double)ARRLEN(table),
(unsigned int)nitems, ARRLEN(table));
@ -248,7 +250,7 @@ main(void)
if (strcasecmp(table[i].icon, uniq[k]) == 0)
break;
}
assert(k < uniq_head);
ENSURE(k < uniq_head);
printf("\t[%3zu] = {\"%s\", %zu, %hhu },\n",
i, table[i].match, k, table[i].color);
}
@ -258,7 +260,7 @@ main(void)
}
#else
#define ASSERT(X) ((void)0)
#define ENSURE(X) ((void)0)
#endif /* ICONS_GENERATE */
#if defined(ICONS_GENERATE) || defined(ICONS_ENABLED)
@ -282,7 +284,7 @@ icon_ext_hash(const char *str)
hash *= GOLDEN_RATIO_32;
hash >>= z;
ASSERT(hash < ARRLEN(table));
ENSURE(hash < ARRLEN(table));
return hash;
}

View File

@ -43,88 +43,89 @@
#define ICON_PADDING_RIGHT_LEN (sizeof ICON_PADDING_RIGHT - 1)
/* ARROWS */
#define ICON_ARROW_UP ICON_STR(MD_ARROW_UPWARD, "\uf55c", "⬆")
#define ICON_ARROW_FORWARD ICON_STR(MD_ARROW_FORWARD, "\uf553", "➡")
#define ICON_ARROW_DOWN ICON_STR(MD_ARROW_DOWNWARD, "\uf544", "⬇")
#define ICON_ARROW_UP ICON_STR(MD_ARROW_UPWARD, "󰁝", "⬆")
#define ICON_ARROW_FORWARD ICON_STR(MD_ARROW_FORWARD, "󰁔", "➡")
#define ICON_ARROW_DOWN ICON_STR(MD_ARROW_DOWNWARD, "󰁅", "⬇")
/* GENERIC */
#define ICON_DIRECTORY ICON_STR(FA_FOLDER, "\ue5ff", "📂")
#define ICON_FILE ICON_STR(FA_FILE, "\uf713", "📃")
#define ICON_EXEC ICON_STR(FA_COG, "\uf144", "⚙️ ")
#define ICON_DIRECTORY ICON_STR(FA_FOLDER, "", "📂")
#define ICON_FILE ICON_STR(FA_FILE, "󰈔", "📃")
#define ICON_EXEC ICON_STR(FA_COG, "", "⚙️ ")
/* Top level and common icons */
#define ICON_ARCHIVE ICON_STR(FA_FILE_ARCHIVE_O, "\uf53b", "📦")
#define ICON_BRIEFCASE ICON_STR(FA_BRIEFCASE, "\uf5d5", "💼")
#define ICON_C ICON_STR(MFIZZ_C, "\ue61e", "🇨 ")
#define ICON_CHANGELOG ICON_STR(FA_HISTORY, "\uf7d9", "🔺")
#define ICON_CHESS ICON_STR("", "\uf639", "")
#define ICON_CLOJURE ICON_STR(MFIZZ_CLOJURE, "\ue76a", "")
#define ICON_CONFIGURE ICON_STR(FILE_CONFIG, "\uf423", "🔧")
#define ICON_CPLUSPLUS ICON_STR(MFIZZ_CPLUSPLUS, "\ue61d", ICON_C)
#define ICON_DATABASE ICON_STR(MFIZZ_DATABASE_ALT2, "\uf6b7", "🗃️ ")
#define ICON_DESKTOP ICON_STR(FA_DESKTOP, "\ufcbe", "🖥️ ")
#define ICON_DOCUMENT ICON_STR(FA_FILE_TEXT_O, "\uf718", "🗒 ")
#define ICON_DOWNLOADS ICON_STR(FA_DOWNLOAD, "\uf5d7", "📥")
#define ICON_ELIXIR ICON_STR(MFIZZ_ELIXIR, "\ue62d", "💧")
#define ICON_ENCRYPT ICON_STR("", "\uf805", "🔒")
#define ICON_FSHARP ICON_STR(DEV_FSHARP, "\ue7a7", "")
#define ICON_FONT ICON_STR(FILE_FONT, "\uf031", "")
#define ICON_GIT ICON_STR(FA_GIT, "\ue5fb", "🌱")
#define ICON_HASKELL ICON_STR("", "\ue777", "")
#define ICON_HTML ICON_STR(FA_FILE_CODE_O, "\uf72d", "")
#define ICON_JAVA ICON_STR(MFIZZ_JAVA, "\ue738", "☕")
#define ICON_JAVASCRIPT ICON_STR(FA_FILE_CODE_O, "\uf81d", "")
#define ICON_LICENSE ICON_STR(FA_COPYRIGHT, "\uf718", "⚖️ ")
#define ICON_LINUX ICON_STR(FA_LINUX, "\uf83c", "🐧")
#define ICON_MAKEFILE ICON_STR(FILE_CMAKE, "\uf68c", "🛠 ")
#define ICON_MANUAL ICON_STR(FILE_MANPAGE, "\uf5bd", "❓")
#define ICON_MS_EXCEL ICON_STR(FILE_EXCEL, "\uf71a", ICON_WORDDOC)
#define ICON_MUSIC ICON_STR(FA_MUSIC, "\uf832", "🎧")
#define ICON_MUSICFILE ICON_STR(FA_FILE_AUDIO_O, "\uf886", ICON_MUSIC)
#define ICON_OPTICALDISK ICON_STR(LINEA_MUSIC_CD, "\ue271", "💿")
#define ICON_PDF ICON_STR(FA_FILE_PDF_O, "\uf724", "📕")
#define ICON_PHOTOSHOP ICON_STR(DEV_PHOTOSHOP, "\ue7b8", ICON_PICTUREFILE)
#define ICON_PICTUREFILE ICON_STR(FA_FILE_IMAGE_O, "\uf71e", ICON_PICTURES)
#define ICON_PICTURES ICON_STR(MD_CAMERA_ALT, "\uf753", "🎨")
#define ICON_PLAYLIST ICON_STR(ICON_MUSICFILE, "\uf831", "")
#define ICON_POWERPOINT ICON_STR(FILE_POWERPOINT, "\uf726", "📊")
#define ICON_PUBLIC ICON_STR(FA_INBOX, "\ue5ff", "👀")
#define ICON_PYTHON ICON_STR(MFIZZ_PYTHON, "\ue235", "🐍")
#define ICON_REACT ICON_STR(FILE_JSX, "\ue625", ICON_JAVASCRIPT)
#define ICON_RUBY ICON_STR(MFIZZ_RUBY, "\ue23e", "💎")
#define ICON_RUST ICON_STR(DEV_RUST, "\ue7a8", "")
#define ICON_SASS ICON_STR("", "\ue603", "")
#define ICON_SCRIPT ICON_STR(MFIZZ_SCRIPT, "\ue795", "📜")
#define ICON_SUBTITLE ICON_STR(FA_COMMENTS_O, "\uf679", "💬")
#define ICON_TEMPLATES ICON_STR(FA_PAPERCLIP, "\ufac6", "📎")
#define ICON_TEX ICON_STR(FILE_TEX, "\ufb68", ICON_DOCUMENT)
#define ICON_VIDEOFILE ICON_STR(FA_FILE_MOVIE_O, "\uf72a", ICON_VIDEOS)
#define ICON_VIDEOS ICON_STR(FA_FILM, "\uf72f", "🎞 ")
#define ICON_VIM ICON_STR(DEV_VIM, "\ue62b", "")
#define ICON_WORDDOC ICON_STR(FILE_WORD, "\uf72b", "📘")
#define ICON_ARCHIVE ICON_STR(FA_FILE_ARCHIVE_O, "󰀼", "📦")
#define ICON_BRIEFCASE ICON_STR(FA_BRIEFCASE, "󰃖", "💼")
#define ICON_C ICON_STR(MFIZZ_C, "", "🇨 ")
#define ICON_CHANGELOG ICON_STR(FA_HISTORY, "󰋚", "🔺")
#define ICON_CHESS ICON_STR("", "󰄺", "")
#define ICON_CLOJURE ICON_STR(MFIZZ_CLOJURE, "", "")
#define ICON_CONFIGURE ICON_STR(FILE_CONFIG, "", "🔧")
#define ICON_CPLUSPLUS ICON_STR(MFIZZ_CPLUSPLUS, "", ICON_C)
#define ICON_DATABASE ICON_STR(MFIZZ_DATABASE_ALT2, "󰆼", "🗃️ ")
#define ICON_DESKTOP ICON_STR(FA_DESKTOP, "󰟀", "🖥️ ")
#define ICON_DJVU ICON_STR(FA_PAPERCLIP, "", "📎")
#define ICON_DOCUMENT ICON_STR(FA_FILE_TEXT_O, "󰈙", "🗒 ")
#define ICON_DOWNLOADS ICON_STR(FA_DOWNLOAD, "󰃘", "📥")
#define ICON_ELIXIR ICON_STR(MFIZZ_ELIXIR, "", "💧")
#define ICON_ENCRYPT ICON_STR("", "󰌆", "🔒")
#define ICON_FSHARP ICON_STR(DEV_FSHARP, "", "")
#define ICON_FONT ICON_STR(FILE_FONT, "", "")
#define ICON_GIT ICON_STR(FA_GIT, "", "🌱")
#define ICON_HASKELL ICON_STR("", "", "")
#define ICON_HTML ICON_STR(FA_FILE_CODE_O, "󰌝", "")
#define ICON_JAVA ICON_STR(MFIZZ_JAVA, "", "☕")
#define ICON_JAVASCRIPT ICON_STR(FA_FILE_CODE_O, "󰌞", "")
#define ICON_LICENSE ICON_STR(FA_COPYRIGHT, "󰈙", "⚖️ ")
#define ICON_LINUX ICON_STR(FA_LINUX, "󰌽", "🐧")
#define ICON_MAKEFILE ICON_STR(FILE_CMAKE, "󰆍", "🛠 ")
#define ICON_MANUAL ICON_STR(FILE_MANPAGE, "󱓷", "❓")
#define ICON_MS_EXCEL ICON_STR(FILE_EXCEL, "󰈛", ICON_WORDDOC)
#define ICON_MUSIC ICON_STR(FA_MUSIC, "󱍙", "🎧")
#define ICON_MUSICFILE ICON_STR(FA_FILE_AUDIO_O, "󰎈", ICON_MUSIC)
#define ICON_OPTICALDISK ICON_STR(LINEA_MUSIC_CD, "", "💿")
#define ICON_PDF ICON_STR(FA_FILE_PDF_O, "󰈦", "📕")
#define ICON_PHOTOSHOP ICON_STR(DEV_PHOTOSHOP, "", ICON_PICTUREFILE)
#define ICON_PICTUREFILE ICON_STR(FA_FILE_IMAGE_O, "󰈟", ICON_PICTURES)
#define ICON_PICTURES ICON_STR(MD_CAMERA_ALT, "󰉔", "🎨")
#define ICON_PLAYLIST ICON_STR(ICON_MUSICFILE, "󱍙", "")
#define ICON_POWERPOINT ICON_STR(FILE_POWERPOINT, "󰈧", "📊")
#define ICON_PUBLIC ICON_STR(FA_INBOX, "", "👀")
#define ICON_PYTHON ICON_STR(MFIZZ_PYTHON, "", "🐍")
#define ICON_REACT ICON_STR(FILE_JSX, "", ICON_JAVASCRIPT)
#define ICON_RUBY ICON_STR(MFIZZ_RUBY, "", "💎")
#define ICON_RUST ICON_STR(DEV_RUST, "", "")
#define ICON_SASS ICON_STR("", "", "")
#define ICON_SCRIPT ICON_STR(MFIZZ_SCRIPT, "", "📜")
#define ICON_SUBTITLE ICON_STR(FA_COMMENTS_O, "󰅺", "💬")
#define ICON_TEMPLATES ICON_STR(FA_PAPERCLIP, "󰗇", "📎")
#define ICON_TEX ICON_STR(FILE_TEX, "󰙩", ICON_DOCUMENT)
#define ICON_VIDEOFILE ICON_STR(FA_FILE_MOVIE_O, "󰈫", ICON_VIDEOS)
#define ICON_VIDEOS ICON_STR(FA_FILM, "󰈰", "🎞 ")
#define ICON_VIM ICON_STR(DEV_VIM, "", "")
#define ICON_WORDDOC ICON_STR(FILE_WORD, "󰈬", "📘")
#define ICON_EXT_ASM ICON_STR(FILE_NASM, "", "")
#define ICON_EXT_BIN ICON_STR(OCT_FILE_BINARY, "\uf471", "📓")
#define ICON_EXT_COFFEE ICON_STR(MFIZZ_COFFEE_BEAN, "\ue751", "")
#define ICON_EXT_CSS ICON_STR(MFIZZ_CSS3, "\ue749", "🦋")
#define ICON_EXT_DEB ICON_STR(MFIZZ_DEBIAN, "\ue77d", ICON_LINUX)
#define ICON_EXT_DIFF ICON_STR(FILE_DIFF, "\uf440", "📋")
#define ICON_EXT_GO ICON_STR(MFIZZ_GO, "\ufcd1", "")
#define ICON_EXT_JSON ICON_STR(ICON_JAVASCRIPT, "\ufb25", ICON_JAVASCRIPT)
#define ICON_EXT_LUA ICON_STR(FILE_LUA, "\ue620", "🌘")
#define ICON_EXT_M ICON_STR("", "\ufd1c", "📊")
#define ICON_EXT_MAT ICON_STR("", "\uf0ce", "")
#define ICON_EXT_MD ICON_STR(DEV_MARKDOWN, "\ue609", "📝")
#define ICON_EXT_MSI ICON_STR(FA_WINDOWS, "\uf871", "🪟")
#define ICON_EXT_NIX ICON_STR("", "\uf313", "")
#define ICON_EXT_PATCH ICON_STR(FILE_PATCH, "\uf440", "🩹")
#define ICON_EXT_PHP ICON_STR(MFIZZ_PHP, "\ue73d", "🌐")
#define ICON_EXT_ROM ICON_STR(FA_LOCK, "\uf795", "")
#define ICON_EXT_RSS ICON_STR(FA_RSS_SQUARE, "\uf143", "📡")
#define ICON_EXT_RTF ICON_STR(ICON_PDF, "\uf724", ICON_PDF)
#define ICON_EXT_SCALA ICON_STR(MFIZZ_SCALA, "\ue737", "")
#define ICON_EXT_SLN ICON_STR(DEV_VISUALSTUDIO, "\ue70c", "")
#define ICON_EXT_TS ICON_STR(FILE_TS, "\ue628", "")
#define ICON_EXT_BIN ICON_STR(OCT_FILE_BINARY, "", "📓")
#define ICON_EXT_COFFEE ICON_STR(MFIZZ_COFFEE_BEAN, "", "")
#define ICON_EXT_CSS ICON_STR(MFIZZ_CSS3, "", "🦋")
#define ICON_EXT_DEB ICON_STR(MFIZZ_DEBIAN, "", ICON_LINUX)
#define ICON_EXT_DIFF ICON_STR(FILE_DIFF, "", "📋")
#define ICON_EXT_GO ICON_STR(MFIZZ_GO, "󰟓", "")
#define ICON_EXT_JSON ICON_STR(ICON_JAVASCRIPT, "", ICON_JAVASCRIPT)
#define ICON_EXT_LUA ICON_STR(FILE_LUA, "", "🌘")
#define ICON_EXT_M ICON_STR("", "󰠞", "📊")
#define ICON_EXT_MAT ICON_STR("", "", "")
#define ICON_EXT_MD ICON_STR(DEV_MARKDOWN, "", "📝")
#define ICON_EXT_MSI ICON_STR(FA_WINDOWS, "󰍲", "🪟")
#define ICON_EXT_NIX ICON_STR("", "", "")
#define ICON_EXT_PATCH ICON_STR(FILE_PATCH, "", "🩹")
#define ICON_EXT_PHP ICON_STR(MFIZZ_PHP, "", "🌐")
#define ICON_EXT_ROM ICON_STR(FA_LOCK, "󰊖", "")
#define ICON_EXT_RSS ICON_STR(FA_RSS_SQUARE, "", "📡")
#define ICON_EXT_RTF ICON_STR(ICON_PDF, "󰈦", ICON_PDF)
#define ICON_EXT_SCALA ICON_STR(MFIZZ_SCALA, "", "")
#define ICON_EXT_SLN ICON_STR(DEV_VISUALSTUDIO, "", "")
#define ICON_EXT_TS ICON_STR(FILE_TS, "", "")
/*
@ -252,6 +253,7 @@ static const struct icon_pair icons_ext[] = { /* All entries are case-insensitiv
{"deb", ICON_EXT_DEB, COLOR_ARCHIVE},
{"diff", ICON_EXT_DIFF, 0},
{"dll", ICON_SCRIPT, 0},
{"djvu", ICON_DJVU, COLOR_DOCS},
{"doc", ICON_WORDDOC, COLOR_DOCUMENT},
{"docx", ICON_WORDDOC, COLOR_DOCUMENT},
@ -286,7 +288,7 @@ static const struct icon_pair icons_ext[] = { /* All entries are case-insensitiv
{"h", ICON_C, COLOR_C},
{"hh", ICON_CPLUSPLUS, COLOR_C},
{"hpp", ICON_CPLUSPLUS, COLOR_C},
{"hs", ICON_HASKELL, COLOR_VIM},
{"hs", ICON_HASKELL, COLOR_ELIXIR},
{"htaccess", ICON_CONFIGURE, 0},
{"htpasswd", ICON_CONFIGURE, 0},
{"htm", ICON_HTML, 0},

381
src/nnn.c
View File

@ -28,14 +28,13 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define _FILE_OFFSET_BITS 64 /* Support large files on 32-bit glibc */
#if defined(__linux__) || defined(MINGW) || defined(__MINGW32__) \
|| defined(__MINGW64__) || defined(__CYGWIN__)
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#if defined(__arm__) || defined(__i386__)
#define _FILE_OFFSET_BITS 64 /* Support large files on 32-bit */
#endif
#if defined(__linux__)
#include <sys/inotify.h>
#define LINUX_INOTIFY
@ -132,12 +131,24 @@
#include "icons.h"
#endif
#if defined(ICONS_ENABLED) && defined(__APPLE__)
/*
* For some reason, wcswidth returns 2 for certain icons on macOS
* leading to duplicated first characters in filenames when navigating.
* https://github.com/jarun/nnn/issues/1692
* There might be a better way to fix it without requiring a refresh.
*/
#define macos_icons_hack() do { clrtoeol(); refresh(); } while(0)
#else
#define macos_icons_hack()
#endif
#ifdef TOURBIN_QSORT
#include "qsort.h"
#endif
/* Macro definitions */
#define VERSION "4.8"
#define VERSION "4.9"
#define GENERAL_INFO "BSD 2-Clause\nhttps://github.com/jarun/nnn"
#ifndef NOSSN
@ -378,7 +389,9 @@ typedef struct {
uint_t trash : 2; /* Trash method 0: rm -rf, 1: trash-cli, 2: gio trash */
uint_t uidgid : 1; /* Show owner and group info */
uint_t usebsdtar : 1; /* Use bsdtar as default archive utility */
uint_t reserved : 5; /* Adjust when adding/removing a field */
uint_t xprompt : 1; /* Use native prompt instead of readline prompt */
uint_t showlines : 1; /* Show line numbers */
uint_t reserved : 3; /* Adjust when adding/removing a field */
} runstate;
/* Contexts or workspaces */
@ -536,6 +549,7 @@ static runstate g_state;
#define UTIL_TRASH_CLI 18
#define UTIL_GIO_TRASH 19
#define UTIL_RM_RF 20
#define UTIL_ARCHMNT 21
/* Utilities to open files, run actions */
static char * const utils[] = {
@ -575,7 +589,8 @@ static char * const utils[] = {
".nmv",
"trash-put",
"gio trash",
"rm -rf",
"rm -rf --",
"archivemount",
};
/* Common strings */
@ -726,13 +741,10 @@ static const char * const envs[] = {
#define T_CHANGE 1
#define T_MOD 2
#ifdef __linux__
static char cp[] = "cp -iRp";
static char mv[] = "mv -i";
#else
static char cp[] = "cp -iRp";
static char mv[] = "mv -i";
#endif
#define PROGRESS_CP "cpg -giRp --"
#define PROGRESS_MV "mvg -gi --"
static char cp[sizeof PROGRESS_CP] = "cp -iRp --";
static char mv[sizeof PROGRESS_MV] = "mv -i --";
/* Archive commands */
static char * const archive_cmd[] = {"atool -a", "bsdtar -acvf", "zip -r", "tar -acvf"};
@ -913,7 +925,7 @@ static bool test_set_bit(uint_t nr)
nr &= HASH_BITS;
pthread_mutex_lock(&hardlink_mutex);
ullong_t *m = ((ullong_t *)ihashbmp) + (nr >> 6);
ullong_t *m = ihashbmp + (nr >> 6);
if (*m & (1 << (nr & 63))) {
pthread_mutex_unlock(&hardlink_mutex);
@ -1299,6 +1311,18 @@ static char *abspath(const char *filepath, char *cwd, char *buf)
return resolved_path;
}
/* finds abspath of link pointed by filepath, taking cwd into account */
static char *bmtarget(const char *filepath, char *cwd, char *buf)
{
char target[PATH_MAX + 1];
ssize_t n = readlink(filepath, target, PATH_MAX);
if (n != -1) {
target[n] = '\0';
return abspath(target, cwd, buf);
}
return NULL;
}
/* wraps the argument in single quotes so it can be safely fed to shell */
static bool shell_escape(char *output, size_t outlen, const char *s)
{
@ -1527,12 +1551,13 @@ static void xdelay(useconds_t delay)
usleep(delay);
}
static char confirm_force(bool selection)
static char confirm_force(bool selection, bool use_trash)
{
char str[64];
/* Note: ideally we should use utils[UTIL_RM_RF] instead of the "rm -rf" string */
snprintf(str, 64, messages[MSG_FORCE_RM],
g_state.trash ? utils[UTIL_GIO_TRASH] + 4 : utils[UTIL_RM_RF],
use_trash ? utils[UTIL_GIO_TRASH] + 4 : "rm -rf",
(selection ? "selected" : "hovered"));
int r = get_input(str);
@ -1541,7 +1566,7 @@ static char confirm_force(bool selection)
return '\0'; /* cancel */
if (r == 'y' || r == 'Y')
return 'f'; /* forceful for rm */
return (g_state.trash ? '\0' : 'i'); /* interactive for rm */
return (use_trash ? '\0' : 'i'); /* interactive for rm */
}
/* Writes buflen char(s) from buf to a file */
@ -2524,14 +2549,14 @@ static void opstr(char *buf, char *op)
snprintf(buf, CMD_LEN_MAX, "xargs -0 sh -c '%s \"$0\" \"$@\" . < /dev/tty' < %s", op, selpath);
}
static bool rmmulstr(char *buf)
static bool rmmulstr(char *buf, bool use_trash)
{
char r = confirm_force(TRUE);
char r = confirm_force(TRUE, use_trash);
if (!r)
return FALSE;
if (!g_state.trash)
snprintf(buf, CMD_LEN_MAX, "xargs -0 sh -c 'rm -%cr \"$0\" \"$@\" < /dev/tty' < %s",
if (!use_trash)
snprintf(buf, CMD_LEN_MAX, "xargs -0 sh -c 'rm -%cr -- \"$0\" \"$@\" < /dev/tty' < %s",
r, selpath);
else
snprintf(buf, CMD_LEN_MAX, "xargs -0 %s < %s",
@ -2541,17 +2566,17 @@ static bool rmmulstr(char *buf)
}
/* Returns TRUE if file is removed, else FALSE */
static bool xrm(char * const fpath)
static bool xrm(char * const fpath, bool use_trash)
{
char r = confirm_force(FALSE);
char r = confirm_force(FALSE, use_trash);
if (!r)
return FALSE;
if (!g_state.trash) {
if (!use_trash) {
char rm_opts[] = "-ir";
rm_opts[1] = r;
spawn("rm", rm_opts, fpath, NULL, F_NORMAL | F_CHKRTN);
spawn("rm", rm_opts, "--", fpath, F_NORMAL | F_CHKRTN);
} else
spawn(utils[(g_state.trash == 1) ? UTIL_TRASH_CLI : UTIL_GIO_TRASH],
fpath, NULL, NULL, F_NORMAL | F_MULTI);
@ -2678,8 +2703,8 @@ static bool cpmvrm_selection(enum action sel, char *path)
return FALSE;
}
break;
default: /* SEL_RM */
if (!rmmulstr(g_buf)) {
default: /* SEL_TRASH, SEL_RM_ONLY */
if (!rmmulstr(g_buf, g_state.trash && sel == SEL_TRASH)) {
printmsg(messages[MSG_CANCEL]);
return FALSE;
}
@ -2704,7 +2729,7 @@ static bool batch_rename(void)
bool dir = FALSE, ret = FALSE;
char foriginal[TMP_LEN_MAX] = {0};
static const char batchrenamecmd[] = "paste -d'\n' %s %s | "SED" 'N; /^\\(.*\\)\\n\\1$/!p;d' | "
"tr '\n' '\\0' | xargs -0 -n2 sh -c 'mv -i \"$0\" \"$@\" <"
"tr '\n' '\\0' | xargs -0 -n2 sh -c 'mv -i -- \"$0\" \"$@\" <"
" /dev/tty'";
char buf[sizeof(batchrenamecmd) + (PATH_MAX << 1)];
int i = get_cur_or_sel();
@ -2990,7 +3015,7 @@ static int (*filterfn)(const fltrexp_t *fltr, const char *fname) = &visible_str;
static void clearfilter(void)
{
char *fltr = g_ctx[cfg.curctx].c_fltr;
char * const fltr = g_ctx[cfg.curctx].c_fltr;
if (fltr[1]) {
fltr[REGEX_MAX - 1] = fltr[1];
@ -3412,7 +3437,14 @@ static int filterentries(char *path, char *lastname)
continue;
#ifndef NOMOUSE
case KEY_MOUSE:
{
MEVENT event = {0};
getmouse(&event);
if (event.bstate == 0)
continue;
ungetmouse(&event);
goto end;
}
#endif
case ESC:
if (handle_alt_key(ch) != ERR) {
@ -4200,8 +4232,9 @@ static uchar_t get_color_pair_name_ind(const struct entry *ent, char *pind, int
return C_UND;
}
static void printent(const struct entry *ent, uint_t namecols, bool sel)
static void printent(int pdents_index, uint_t namecols, bool sel)
{
const struct entry *ent = &pdents[pdents_index];
char ind = '\0';
int attrs;
@ -4228,6 +4261,11 @@ static void printent(const struct entry *ent, uint_t namecols, bool sel)
attroff(attrs);
}
if (g_state.showlines) {
ptrdiff_t rel_num = pdents_index - cur;
printw(rel_num == 0 ? "%4td" : "%+4td", rel_num);
}
attrs = 0;
uchar_t color_pair = get_color_pair_name_ind(ent, &ind, &attrs);
@ -4265,6 +4303,18 @@ static void printent(const struct entry *ent, uint_t namecols, bool sel)
addch(ind);
}
/**
* Sets the global cfg variable and restores related state to match the new
* cfg.
*/
static void setcfg(settings newcfg)
{
cfg = newcfg;
/* Synchronize the global function pointers to match the new cfg. */
entrycmpfn = cfg.reverse ? &reventrycmp : &entrycmp;
namecmpfn = cfg.version ? &xstrverscasecmp : &xstricmp;
}
static void savecurctx(char *path, char *curname, int nextctx)
{
settings tmpcfg = cfg;
@ -4296,7 +4346,7 @@ static void savecurctx(char *path, char *curname, int nextctx)
}
tmpcfg.curctx = nextctx;
cfg = tmpcfg;
setcfg(tmpcfg);
}
#ifndef NOSSN
@ -4453,6 +4503,7 @@ static void set_smart_ctx(int ctx, char *nextpath, char **path, char *file, char
ctx = (int)(get_free_ctx() + 1);
if (ctx == 0 || ctx == cfg.curctx + 1) { /* Same context */
clearfilter();
xstrsncpy(*lastdir, *path, PATH_MAX);
xstrsncpy(*path, nextpath, PATH_MAX);
} else { /* New context */
@ -4604,12 +4655,12 @@ static bool show_stats(char *fpath)
return TRUE;
}
static bool xchmod(const char *fpath, mode_t mode)
static bool xchmod(const char *fpath, mode_t *mode)
{
/* (Un)set (S_IXUSR | S_IXGRP | S_IXOTH) */
(0100 & mode) ? (mode &= ~0111) : (mode |= 0111);
(0100 & *mode) ? (*mode &= ~0111) : (*mode |= 0111);
return (chmod(fpath, mode) == 0);
return (chmod(fpath, *mode) == 0);
}
static size_t get_fs_info(const char *path, uchar_t type)
@ -4681,7 +4732,7 @@ next:
return FALSE;
}
} else {
int fd = open(path, O_CREAT | O_TRUNC, S_IWUSR | S_IRUSR); /* Forced create mode for files */
int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IWUSR | S_IRUSR); /* Forced create mode for files */
if (fd == -1 && errno != EEXIST) {
DPRINTF_S("open!");
@ -4800,14 +4851,13 @@ static void valid_parent(char *path, char *lastname)
static bool archive_mount(char *newpath)
{
char *str = "install archivemount";
char *dir, *cmd = str + 8; /* Start of "archivemount" */
char *dir, *cmd = xgetenv("NNN_ARCHMNT", utils[UTIL_ARCHMNT]);
char *name = pdents[cur].name;
size_t len = pdents[cur].nlen;
char mntpath[PATH_MAX];
if (!getutil(cmd)) {
printmsg(str);
printmsg("install utility");
return FALSE;
}
@ -5007,12 +5057,12 @@ static void lock_terminal(void)
spawn(xgetenv("NNN_LOCKER", utils[UTIL_LOCKER]), NULL, NULL, NULL, F_CLI);
}
static void printkv(kv *kvarr, int fd, uchar_t max, uchar_t id)
static void printkv(kv *kvarr, FILE *f, uchar_t max, uchar_t id)
{
char *val = (id == NNN_BMS) ? bmstr : pluginstr;
for (uchar_t i = 0; i < max && kvarr[i].key; ++i)
dprintf(fd, " %c: %s\n", (char)kvarr[i].key, val + kvarr[i].off);
fprintf(f, " %c: %s\n", (char)kvarr[i].key, val + kvarr[i].off);
}
static void printkeys(kv *kvarr, char *buf, uchar_t max)
@ -5080,121 +5130,134 @@ static void add_bookmark(char *path, char *newpath, int *presel)
}
/*
* The help string tokens (each line) start with a HEX value
* which indicates the number of spaces to print before the
* particular token. This method was chosen instead of a flat
* string because the number of bytes in help was increasing
* the binary size by around a hundred bytes. This would only
* have increased as we keep adding new options.
* The help string tokens (each line) start with a HEX value which indicates
* the number of spaces to print before the particular token. In the middle,
* %NN can be used to insert a run of spaces, e.g %10 will print 10 spaces.
* %NN MUST be 2 characters long, e.g %05 for 5 spaces.
*
* This method was chosen instead of a flat string because the number of bytes
* in help was increasing the binary size by around a hundred bytes. This would
* only have increased as we keep adding new options.
*/
static void show_help(const char *path)
{
const char *start, *end;
const char helpstr[] = {
static const char helpstr[] = {
"2|V\\_\n"
"2/. \\\\\n"
"1(;^; ||\n"
"3/___3\n"
"2(___n))\n"
"0\n"
"1NAVIGATION\n"
"9Up k Up%-16cPgUp ^U Page up\n"
"9Dn j Down%-14cPgDn ^D Page down\n"
"9Lt h Parent%-12c~ ` @ - ~, /, start, prev\n"
"5Ret Rt l Open%-20c' First file/match\n"
"9g ^A Top%-21cJ Jump to entry/offset\n"
"9G ^E End%-20c^J Toggle auto-advance on open\n"
"8B (,) Book(mark)%-11cb ^/ Select bookmark\n"
"a1-4 Context%-11c(Sh)Tab Cycle/new context\n"
"62Esc ^Q Quit%-20cq Quit context\n"
"b^G QuitCD%-18cQ Pick/err, quit\n"
"9Up k Up%16PgUp ^U Page up\n"
"9Dn j Down%14PgDn ^D Page down\n"
"9Lt h Parent%12~ ` @ - ~, /, start, prev\n"
"5Ret Rt l Open%20' First file/match\n"
"9g ^A Top%21J Jump to entry/offset\n"
"9G ^E End%20^J Toggle auto-advance on open\n"
"8B (,) Book(mark)%11b ^/ Select bookmark\n"
"a1-4 Context%11(Sh)Tab Cycle/new context\n"
"62Esc ^Q Quit%19^y Next young\n"
"b^G QuitCD%18Q Pick/err, quit\n"
"cq Quit context\n"
"0\n"
"1FILTER & PROMPT\n"
"c/ Filter%-17c^N Toggle type-to-nav\n"
"aEsc Exit prompt%-12c^L Toggle last filter\n"
"c. Toggle hidden%-5cAlt+Esc Unfilter, quit context\n"
"c/ Filter%17^N Toggle type-to-nav\n"
"aEsc Exit prompt%12^L Toggle last filter\n"
"c. Toggle hidden%05Alt+Esc Unfilter, quit context\n"
"0\n"
"1FILES\n"
"9o ^O Open with%-15cn Create new/link\n"
"9f ^F File stats%-14cd Detail mode toggle\n"
"b^R Rename/dup%-14cr Batch rename\n"
"cz Archive%-17ce Edit file\n"
"c* Toggle exe%-14c> Export list\n"
"6Space + (Un)select%-12cm-m Select range/clear\n"
"ca Select all%-14cA Invert sel\n"
"9p ^P Copy here%-12cw ^W Cp/mv sel as\n"
"9v ^V Move here%-15cE Edit sel list\n"
"9x ^X Delete%-18cS Listed sel size\n"
"aEsc Send to FIFO\n"
"9o ^O Open with%15n Create new/link\n"
"9f ^F File stats%14d Detail mode toggle\n"
"b^R Rename/dup%14r Batch rename\n"
"cz Archive%17e Edit file\n"
"c* Toggle exe%14> Export list\n"
"6Space + (Un)select%12m-m Select range/clear\n"
"ca Select all%14A Invert sel\n"
"9p ^P Copy here%12w ^W Cp/mv sel as\n"
"9v ^V Move here%15E Edit sel list\n"
"9x ^X Delete or trash%09S Listed sel size\n"
"cX Delete (rm -rf)%07Esc Send to FIFO\n"
"0\n"
"1MISC\n"
"8Alt ; Select plugin%-11c= Launch app\n"
"9! ^] Shell%-19c] Cmd prompt\n"
"cc Connect remote%-10cu Unmount remote/archive\n"
"9t ^T Sort toggles%-12cs Manage session\n"
"cT Set time type%-11c0 Lock\n"
"b^L Redraw%-18c? Help, conf\n"
"8Alt ; Select plugin%11= Launch app\n"
"9! ^] Shell%19] Cmd prompt\n"
"cc Connect remote%10u Unmount remote/archive\n"
"9t ^T Sort toggles%12s Manage session\n"
"cT Set time type%110 Lock\n"
"b^L Redraw%18? Help, conf\n"
};
int fd = create_tmp_file();
if (fd == -1)
return;
dprintf(fd, " |V\\_\n"
" /. \\\\\n"
" (;^; ||\n"
" /___3\n"
" (___n))\n");
FILE *f = fdopen(fd, "wb");
if (f == NULL) {
close(fd);
unlink(g_tmpfpath);
return;
}
char *prog = xgetenv(env_cfg[NNN_HELP], NULL);
if (prog)
get_output(prog, NULL, NULL, fd, FALSE);
start = end = helpstr;
while (*end) {
if (*end == '\n') {
snprintf(g_buf, CMD_LEN_MAX, "%*c%.*s",
xchartohex(*start), ' ', (int)(end - start), start + 1);
dprintf(fd, g_buf, ' ');
start = end + 1;
}
bool hex = true;
const char *end = helpstr + sizeof(helpstr) - 1;
++end;
for (const char *s = helpstr; s < end; ++s) {
if (hex) {
for (int k = 0, n = xchartohex(*s); k < n; ++k)
fputc(' ', f);
} else if (*s == '%') {
int n = ((s[1] - '0') * 10) + (s[2] - '0');
for (int k = 0; k < n; ++k)
fputc(' ', f);
s += 2;
} else {
fputc(*s, f);
}
hex = (*s == '\n');
}
dprintf(fd, "\nLOCATIONS\n");
fprintf(f, "\nLOCATIONS\n");
for (uchar_t i = 0; i < CTX_MAX; ++i)
if (g_ctx[i].c_cfg.ctxactive)
dprintf(fd, " %u: %s\n", i + 1, g_ctx[i].c_path);
fprintf(f, " %u: %s\n", i + 1, g_ctx[i].c_path);
dprintf(fd, "\nVOLUME: avail:%s ", coolsize(get_fs_info(path, VFS_AVAIL)));
dprintf(fd, "used:%s ", coolsize(get_fs_info(path, VFS_USED)));
dprintf(fd, "size:%s\n\n", coolsize(get_fs_info(path, VFS_SIZE)));
fprintf(f, "\nVOLUME: avail:%s ", coolsize(get_fs_info(path, VFS_AVAIL)));
fprintf(f, "used:%s ", coolsize(get_fs_info(path, VFS_USED)));
fprintf(f, "size:%s\n\n", coolsize(get_fs_info(path, VFS_SIZE)));
if (bookmark) {
dprintf(fd, "BOOKMARKS\n");
printkv(bookmark, fd, maxbm, NNN_BMS);
dprintf(fd, "\n");
fprintf(f, "BOOKMARKS\n");
printkv(bookmark, f, maxbm, NNN_BMS);
fprintf(f, "\n");
}
if (plug) {
dprintf(fd, "PLUGIN KEYS\n");
printkv(plug, fd, maxplug, NNN_PLUG);
dprintf(fd, "\n");
fprintf(f, "PLUGIN KEYS\n");
printkv(plug, f, maxplug, NNN_PLUG);
fprintf(f, "\n");
}
for (uchar_t i = NNN_OPENER; i <= NNN_TRASH; ++i) {
start = getenv(env_cfg[i]);
if (start)
dprintf(fd, "%s: %s\n", env_cfg[i], start);
char *s = getenv(env_cfg[i]);
if (s)
fprintf(f, "%s: %s\n", env_cfg[i], s);
}
if (selpath)
dprintf(fd, "SELECTION FILE: %s\n", selpath);
fprintf(f, "SELECTION FILE: %s\n", selpath);
dprintf(fd, "\nv%s\n%s\n", VERSION, GENERAL_INFO);
close(fd);
fprintf(f, "\nv%s\n%s\n", VERSION, GENERAL_INFO);
fclose(f); // also closes fd
spawn(pager, g_tmpfpath, NULL, NULL, F_CLI | F_TTY);
unlink(g_tmpfpath);
}
static void setexports(void)
static void setexports(const char *path)
{
char dvar[] = "d0";
char fvar[] = "f0";
@ -5218,6 +5281,7 @@ static void setexports(void)
}
setenv("NNN_INCLUDE_HIDDEN", xitoa(cfg.showhidden), 1);
setenv("NNN_PREFER_SELECTION", xitoa(cfg.prefersel), 1);
setenv("PWD", path, 1);
}
static void run_cmd_as_plugin(const char *file, uchar_t flags)
@ -5348,7 +5412,7 @@ static bool run_plugin(char **path, const char *file, char *runfile, char **last
g_state.pluginit = 1;
}
setexports();
setexports(*path);
/* Check for run-cmd-as-plugin mode */
if (*file == '!') {
@ -5463,7 +5527,7 @@ static bool prompt_run(void)
while (1) {
#ifndef NORL
if (g_state.picker) {
if (g_state.picker || g_state.xprompt) {
#endif
cmdline = xreadline(NULL, PROMPT);
#ifndef NORL
@ -5522,14 +5586,14 @@ static bool prompt_run(void)
return ret;
}
static bool handle_cmd(enum action sel, char *newpath)
static bool handle_cmd(enum action sel, char *path, char *newpath)
{
endselection(FALSE);
if (sel == SEL_LAUNCH)
return launch_app(newpath);
setexports();
setexports(path);
if (sel == SEL_PROMPT)
return prompt_run();
@ -6112,6 +6176,20 @@ static void handle_screen_move(enum action sel)
case SEL_END:
move_cursor(ndents - 1, 1);
break;
case SEL_YOUNG:
{
for (int r = cur;;) {
if (++r >= ndents)
r = 0;
if (r == cur)
break;
if (pdents[r].flags & FILE_YOUNG) {
move_cursor(r, 0);
break;
}
}
break;
}
default: /* case SEL_FIRST */
{
int c = get_input(messages[MSG_FIRST]);
@ -6217,11 +6295,9 @@ static int set_sort_flags(int r)
r = 'd';
}
if (cfg.version)
namecmpfn = &xstrverscasecmp;
if (cfg.reverse)
entrycmpfn = &reventrycmp;
/* Ensure function pointers are in sync with cfg. */
entrycmpfn = cfg.reverse ? &reventrycmp : &entrycmp;
namecmpfn = cfg.version ? &xstrverscasecmp : &xstricmp;
} else if (r == CONTROL('T')) {
/* Cycling order: clear -> size -> time -> clear */
if (cfg.timeorder)
@ -6502,7 +6578,8 @@ static void draw_line(int ncols)
}
move(2 + last - curscroll, 0);
printent(&pdents[last], ncols, FALSE);
macos_icons_hack();
printent(last, ncols, FALSE);
if (g_state.oldcolor && (pdents[cur].flags & DIR_OR_DIRLNK)) {
if (!dir) {/* First file is not a directory */
@ -6515,7 +6592,8 @@ static void draw_line(int ncols)
}
move(2 + cur - curscroll, 0);
printent(&pdents[cur], ncols, TRUE);
macos_icons_hack();
printent(cur, ncols, TRUE);
/* Must reset e.g. no files in dir */
if (dir)
@ -6640,7 +6718,7 @@ static void redraw(char *path)
if (len)
findmarkentry(len, &pdents[i]);
printent(&pdents[i], ncols, i == cur);
printent(i, ncols, i == cur);
}
/* Must reset e.g. no files in dir */
@ -7008,7 +7086,7 @@ nochange:
pent = &pdents[cur];
if (!g_state.selbm || !(S_ISLNK(pent->mode) &&
realpath(pent->name, newpath) &&
bmtarget(pent->name, path, newpath) &&
xstrsncpy(path, lastdir, PATH_MAX)))
mkpath(path, pent->name, newpath);
g_state.selbm = 0;
@ -7193,12 +7271,20 @@ nochange:
case SEL_HOME: // fallthrough
case SEL_END: // fallthrough
case SEL_FIRST: // fallthrough
case SEL_JUMP:
case SEL_YOUNG:
if (ndents) {
g_state.move = 1;
handle_screen_move(sel);
}
break;
case SEL_JUMP:
if (ndents) {
g_state.showlines = 1;
redraw(path);
handle_screen_move(sel);
g_state.showlines = 0;
}
break;
case SEL_CDHOME: // fallthrough
case SEL_CDBEGIN: // fallthrough
case SEL_CDLAST: // fallthrough
@ -7382,13 +7468,13 @@ nochange:
if ((sel == SEL_STATS && !show_stats(newpath))
|| (lstat(newpath, &sb) == -1)
|| (sel == SEL_CHMODX && !xchmod(newpath, sb.st_mode))) {
|| (sel == SEL_CHMODX && !xchmod(newpath, &sb.st_mode))) {
printwarn(&presel);
goto nochange;
}
if (sel == SEL_CHMODX)
pdents[cur].mode ^= 0111;
pdents[cur].mode = sb.st_mode;
}
break;
case SEL_REDRAW: // fallthrough
@ -7571,9 +7657,10 @@ nochange:
case SEL_CP: // fallthrough
case SEL_MV: // fallthrough
case SEL_CPMVAS: // fallthrough
case SEL_RM:
case SEL_TRASH: // fallthrough
case SEL_RM_ONLY:
{
if (sel == SEL_RM) {
if (sel == SEL_TRASH || sel == SEL_RM_ONLY) {
r = get_cur_or_sel();
if (!r) {
statusbar(path);
@ -7584,7 +7671,7 @@ nochange:
tmp = (listpath && xstrcmp(path, listpath) == 0)
? listroot : path;
mkpath(tmp, pdents[cur].name, newpath);
if (!xrm(newpath))
if (!xrm(newpath, g_state.trash && sel == SEL_TRASH))
continue;
xrmfromsel(tmp, newpath);
@ -7662,7 +7749,7 @@ nochange:
break;
case SEL_OPENWITH:
#ifndef NORL
if (g_state.picker) {
if (g_state.picker || g_state.xprompt) {
#endif
tmp = xreadline(NULL, messages[MSG_OPEN_WITH]);
#ifndef NORL
@ -7685,7 +7772,7 @@ nochange:
if (r == 'f' || r == 'd')
tmp = xreadline(tmp, messages[MSG_NEW_PATH]);
else if (r == 's' || r == 'h')
tmp = xreadline(NULL,
tmp = xreadline((nselected == 1 && cfg.prefersel) ? xbasename(pselbuf) : NULL,
messages[nselected <= 1 ? MSG_NEW_PATH : MSG_LINK_PREFIX]);
else
tmp = NULL;
@ -7757,7 +7844,7 @@ nochange:
}
if (!(r == 's' || r == 'h')) {
tmp = abspath(tmp, NULL, newpath);
tmp = abspath(tmp, path, newpath);
if (!tmp) {
printwarn(&presel);
goto nochange;
@ -7780,7 +7867,7 @@ nochange:
if (sel == SEL_RENAME) {
/* Rename the file */
if (ret == 'd')
spawn("cp -rp", pdents[cur].name, tmp, NULL, F_SILENT);
spawn("cp -rp --", pdents[cur].name, tmp, NULL, F_SILENT);
else if (rename(pdents[cur].name, tmp) != 0) {
printwarn(&presel);
goto nochange;
@ -7897,9 +7984,9 @@ nochange:
xstrsncpy(runfile, pdents[cur].name, NAME_MAX);
g_state.runctx = cfg.curctx;
lastname[0] = '\0';
clearfilter();
}
setdirwatch();
clearfilter();
if (g_state.runplugin == 1) /* Allow filtering in plugins directory */
presel = FILTER;
goto begin;
@ -7909,7 +7996,7 @@ nochange:
case SEL_SHELL: // fallthrough
case SEL_LAUNCH: // fallthrough
case SEL_PROMPT:
r = handle_cmd(sel, newpath);
r = handle_cmd(sel, path, newpath);
/* Continue in type-to-nav mode, if enabled */
if (cfg.filtermode)
@ -7983,9 +8070,9 @@ nochange:
lastdir = g_ctx[r].c_last;
lastname = g_ctx[r].c_name;
cfg = g_ctx[r].c_cfg;
g_ctx[r].c_cfg.curctx = r;
setcfg(g_ctx[r].c_cfg);
cfg.curctx = r;
setdirwatch();
goto begin;
}
@ -8307,6 +8394,9 @@ static void usage(void)
" -K detect key collision and exit\n"
" -l val set scroll lines\n"
" -n type-to-nav mode\n"
#ifndef NORL
" -N use native prompt\n"
#endif
" -o open files only on Enter\n"
" -p file selection file [-:stdout]\n"
" -P key run plugin key\n"
@ -8484,7 +8574,7 @@ int main(int argc, char *argv[])
while ((opt = (env_opts_id > 0
? env_opts[--env_opts_id]
: getopt(argc, argv, "aAb:BcCdDeEfF:gHiJKl:nop:P:QrRs:St:T:uUVxh"))) != -1) {
: getopt(argc, argv, "aAb:BcCdDeEfF:gHiJKl:nNop:P:QrRs:St:T:uUVxh"))) != -1) {
switch (opt) {
#ifndef NOFIFO
case 'a':
@ -8557,6 +8647,11 @@ int main(int argc, char *argv[])
case 'n':
cfg.filtermode = 1;
break;
#ifndef NORL
case 'N':
g_state.xprompt = 1;
break;
#endif
case 'o':
cfg.nonavopen = 1;
break;
@ -8586,8 +8681,8 @@ int main(int argc, char *argv[])
break;
case 'r':
#ifdef __linux__
cp[2] = cp[5] = mv[2] = mv[5] = 'g'; /* cp -iRp -> cpg -giRp */
cp[4] = mv[4] = '-';
memcpy(cp, PROGRESS_CP, sizeof PROGRESS_CP);
memcpy(mv, PROGRESS_MV, sizeof PROGRESS_MV);
#endif
break;
case 'R':
@ -8714,7 +8809,7 @@ int main(int argc, char *argv[])
/* Start in the current directory */
char *startpath = getenv("PWD");
initpath = startpath ? xstrdup(startpath) : getcwd(NULL, 0);
initpath = (startpath && *startpath) ? xstrdup(startpath) : getcwd(NULL, 0);
if (!initpath)
initpath = "/";
} else { /* Open a file */
@ -8932,7 +9027,7 @@ int main(int argc, char *argv[])
exitcurses();
#ifndef NORL
if (rlhist) {
if (rlhist && !g_state.xprompt) {
mkpath(cfgpath, ".history", g_buf);
write_history(g_buf);
}

View File

@ -58,6 +58,7 @@ enum action {
SEL_END,
SEL_FIRST,
SEL_JUMP,
SEL_YOUNG,
SEL_CDHOME,
SEL_CDBEGIN,
SEL_CDLAST,
@ -95,7 +96,8 @@ enum action {
SEL_CP,
SEL_MV,
SEL_CPMVAS,
SEL_RM,
SEL_TRASH,
SEL_RM_ONLY,
SEL_OPENWITH,
SEL_NEW,
SEL_RENAME,
@ -164,6 +166,7 @@ static struct key bindings[] = {
{ '\'', SEL_FIRST },
/* Jump to an entry number/offset */
{ 'J', SEL_JUMP },
{ CONTROL('Y'), SEL_YOUNG },
/* HOME */
{ '~', SEL_CDHOME },
/* Initial directory */
@ -237,8 +240,9 @@ static struct key bindings[] = {
{ 'w', SEL_CPMVAS },
{ CONTROL('W'), SEL_CPMVAS },
/* Delete from selection buffer */
{ 'x', SEL_RM },
{ CONTROL('X'), SEL_RM },
{ 'x', SEL_TRASH },
{ CONTROL('X'), SEL_TRASH },
{ 'X', SEL_RM_ONLY },
/* Open in a custom application */
{ 'o', SEL_OPENWITH },
{ CONTROL('O'), SEL_OPENWITH },