mirror of https://github.com/jarun/nnn.git
Compare commits
140 Commits
Author | SHA1 | Date |
---|---|---|
Arun | e27d059552 | |
NRK | 4f3662cf88 | |
Arun | 9e95578c22 | |
NRK | 78b9677abd | |
Arun Prakash Jana | 55137600e0 | |
Arun Prakash Jana | be6988d1c8 | |
Arun Prakash Jana | 191e77ec5d | |
Arun Prakash Jana | 46b5255814 | |
Arun | 2fb7490bf0 | |
Arun | d61c983dd0 | |
NRK | e60be2eaa2 | |
NRK | 72ee94ed6e | |
Oktay Imanzade | b20886a29c | |
Arun | ad04944bdf | |
François Bechet | 133c0d329b | |
Arun | 5853ac8e48 | |
Martin Ziemer | 28d993a8e8 | |
Arun | 22aa1455a6 | |
KlzXS | 7806d5d371 | |
Arun | 5456ba4582 | |
c79cea05 | 297b85492f | |
Arun Prakash Jana | f71b1309a9 | |
Arun | eb66598145 | |
KlzXS | 3d6777920a | |
Arun | 4a9587a5e6 | |
KlzXS | b392dd3723 | |
Arun | 0f62c6258a | |
João F. (BeyondMagic/koetemagie) | 2a442ec30c | |
Michel DHOOGE | 5b05c8b9b1 | |
90 | eb3888cb09 | |
Arun Prakash Jana | 94aeaccdbd | |
NRK | 0738f39cf0 | |
Antonio Mancera Gamez | e76d7bbf1d | |
Arun | f2a8648861 | |
Arun | 82f9e544f2 | |
me | 3d2caf861d | |
João F. (BeyondMagic/koetemagie) | eb775914af | |
Arun | 5595d93d29 | |
Arun | bb650eb9dd | |
me | ab718387c2 | |
Jeff Davis | 3849430ebc | |
Arun | f2a909dafd | |
Arun | 404eed5fc7 | |
me | 9aaf9491ad | |
Arun | 485079d3ec | |
me | bca441e00f | |
NRK | 60eabb6170 | |
NRK | 3665541dac | |
Arun | 744a7554ef | |
blissful | c0b3cc8689 | |
blissful | 703d349389 | |
Arun Prakash Jana | 9259170afd | |
Arun | 2f22afcacc | |
luukvbaal | 4009e211f3 | |
Luuk van Baal | 3160442f0c | |
Abhinav Lakhani | 9ff81ca1f9 | |
CronyAkatsuki | 8e8289373a | |
Arun | 1051d7213d | |
Luuk van Baal | f8f6d6a482 | |
Arun | 7f63bef4d6 | |
black | bfb46159a1 | |
Arun | f3397d5ea4 | |
NRK | 336ec8be5d | |
J-Kappes | afe84862ff | |
Arun | 3176eaa85c | |
NRK | 4d5e29c3dd | |
NRK | 6d6fc3419e | |
Arun Prakash Jana | 9b921761b6 | |
Arun | 09bf8fe469 | |
blissful | 3b3ad9ccc6 | |
Arun Prakash Jana | dd07aeb703 | |
Arun Prakash Jana | 9c7c7284c0 | |
Arun | ba439084c5 | |
Xerillic | 06d8da9052 | |
Arun | ed59aa2ac3 | |
umaranis | a06af824ee | |
Xerillic | 66447d52a7 | |
Syed Umar Anis | 547508aa78 | |
Arun Prakash Jana | d72ab3497a | |
Arun Prakash Jana | 2472554e9a | |
Arun Prakash Jana | 785dd3ddf1 | |
Arun Prakash Jana | 33126ee813 | |
Arun | d8c1c99e45 | |
Syed Umar Anis | b28f209c84 | |
Arun | 1ba85825c5 | |
Arun | 66f636de13 | |
Tadeas Uhlir | e500179188 | |
Quan Tong | d220c50773 | |
Arun Prakash Jana | 186f9d01ea | |
Arun Prakash Jana | 693ba757c0 | |
Arun Prakash Jana | 3539e5c1b1 | |
Arun | d65a095d9b | |
ANtlord | dedf0554e5 | |
Arun | b835cfcc2a | |
Anomalocaridid | 80bbf76b5b | |
Anomalocaridid | 5723023491 | |
Anomalocaridid | 280068c5da | |
Arun | 53e4fec75b | |
NRK | db8b61866b | |
Arun | 26d5b5c614 | |
Arun | 899fd5b4cf | |
JingMatrix | e6ce7a614e | |
NRK | 5e3ee08e64 | |
NRK | 4c2ce0a84d | |
Arun | 0dfc6881b4 | |
Luuk van Baal | 05990dc9e5 | |
Arun | fb6e7403cf | |
NRK | b2b830e69d | |
Arun | 4149a2619d | |
Aseem Athale | aed2725cb3 | |
Arun | 04d9f6738d | |
Arun | e013a867da | |
Arun | ed58e07a98 | |
NRK | 16899bda53 | |
Arun | 4c0305f11c | |
leo-arch | 4babedc3e4 | |
NRK | ddcf331205 | |
Delgan | bd4a4454fe | |
Arun | aaf60b93d7 | |
Arun | 145ea41490 | |
Arun | 29779acc57 | |
Delgan | a7262eb4ee | |
Jasper | fb3a648756 | |
UnleashedMarf | 9be3ee9abf | |
UnleashedMarf | d873eb393d | |
Arun Prakash Jana | efd5bc9db1 | |
Arun | 737ebaa9ef | |
J. Brock | 95183fbef8 | |
Arun | fe96bd6bc7 | |
Luuk van Baal | 20e944f5e5 | |
Arun Prakash Jana | 5d81aeb477 | |
Arun | 8fd1822ca6 | |
NRK | 20725b0b4d | |
Arun | 6a8d74a43a | |
Luuk van Baal | d3b5d0e49d | |
musjj | 432b0755d3 | |
Arun | 621dbba02e | |
spfanning | 63891578d7 | |
Arun Prakash Jana | 8a1dce888a | |
Arun Prakash Jana | 9319b638e7 |
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
20
CHANGELOG
20
CHANGELOG
|
@ -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
|
||||
|
||||
|
|
24
Makefile
24
Makefile
|
@ -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: ;
|
||||
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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"'
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
22
nnn.1
|
@ -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
|
||||
|
|
|
@ -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` |
|
||||
|
|
|
@ -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 */
|
|
@ -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 */
|
||||
|
|
|
@ -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':
|
||||
|
|
|
@ -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':
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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]
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -29,4 +29,4 @@ $EDITOR "$tmpfile"
|
|||
|
||||
sed "/^\//d" "$tmpfile" | xargs -n1 -I{} sh -c "$cmd"
|
||||
|
||||
rm "$tmpfile"
|
||||
rm -- "$tmpfile"
|
||||
|
|
|
@ -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
|
|
@ -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/"
|
|
@ -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
|
||||
|
|
|
@ -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 _
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 _
|
||||
|
|
|
@ -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 _
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ""
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" &
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
156
src/icons.h
156
src/icons.h
|
@ -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
381
src/nnn.c
|
@ -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);
|
||||
}
|
||||
|
|
10
src/nnn.h
10
src/nnn.h
|
@ -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 },
|
||||
|
|
Loading…
Reference in New Issue