diff --git a/README.md b/README.md
index 17d48fda..cb0468ba 100644
--- a/README.md
+++ b/README.md
@@ -60,7 +60,7 @@ Visit the [Wiki](https://github.com/jarun/nnn/wiki) for concepts, program usage,
- Notification on cp, mv, rm completion
- Copy file paths to system clipboard on select
- Create (with parents), rename, duplicate (anywhere) files and dirs
- - Launch GUI apps, run commands, spawn a shell
+ - Launch GUI apps, run commands, spawn a shell, toggle executable
- Hovered file set as `$nnn` at prompt and spawned shell
- Lock terminal (needs a locker)
- Privacy-aware (no unconfirmed user data collection)
diff --git a/plugins/README.md b/plugins/README.md
index 25c5b57e..ecc04789 100644
--- a/plugins/README.md
+++ b/plugins/README.md
@@ -18,7 +18,6 @@ Plugins extend the capabilities of `nnn`. They are _executable_ scripts (or bina
| boom | Play random music from dir | sh | [moc](http://moc.daper.net/) |
| dups | List non-empty duplicate files in current dir | sh | find, md5sum,
sort uniq xargs |
| chksum | Create and verify checksums | sh | md5sum,
sha256sum |
-| chmodx | Toggle executable status of hovered file | sh | chmod |
| diffs | Diff for selection (limited to 2 for directories) | sh | vimdiff |
| dragdrop | Drag/drop files from/into nnn | sh | [dragon](https://github.com/mwh/dragon) |
| fzcd | Change to the directory of a fuzzy-selected file/dir | sh | fzf/fzy
fd/fdfind/find |
diff --git a/plugins/autojump b/plugins/autojump
index b30530fe..ef39dd91 100755
--- a/plugins/autojump
+++ b/plugins/autojump
@@ -15,5 +15,6 @@ if which autojump >/dev/null 2>&1; then
odir="$(autojump "$dir")"
printf "%s" "0$odir" > "$NNN_PIPE"
else
- exit 1
+ printf "autojump missing"
+ read -r _
fi
diff --git a/plugins/chmodx b/plugins/chmodx
deleted file mode 100755
index 1ad8467f..00000000
--- a/plugins/chmodx
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env sh
-
-# Description: Toggle executable status of hovered file
-#
-# Shell: POSIX compliant
-# Author: Arun Prakash Jana
-
-if ! [ -z "$1" ]; then
- if [ -x "$1" ]; then
- chmod -x "$1"
- else
- chmod +x "$1"
- fi
-fi
diff --git a/src/nnn.c b/src/nnn.c
index 85d52fe9..afe7fae4 100644
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -3108,6 +3108,13 @@ static bool show_stats(const char *fpath, const struct stat *sb)
return TRUE;
}
+static bool xchmod(const char *fpath, mode_t mode)
+{
+ (S_IXUSR & mode) ? (mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH)) : (mode |= (S_IXUSR | S_IXGRP | S_IXOTH));
+
+ return (chmod(fpath, mode) == 0);
+}
+
static size_t get_fs_info(const char *path, bool type)
{
struct statvfs svb;
@@ -3491,7 +3498,7 @@ static void show_help(const char *path)
"cV Move sel here%-10c^V Copy/move sel as\n"
"cX Delete sel%-13c^X Delete entry\n"
"ce Edit in EDITOR%-10cp Open in PAGER\n"
- "ci Archive entry%-0c\n"
+ "ci Archive entry%-11c* Toggle exe\n"
"1ORDER TOGGLES\n"
"cS Disk usage%-14cA Apparent du\n"
"cz Size%-20ct Time\n"
@@ -4849,13 +4856,19 @@ nochange:
if (ndents)
copycurname();
goto begin;
- case SEL_STATS:
+ case SEL_STATS: // fallthrough
+ case SEL_CHMODX:
if (ndents) {
mkpath(path, dents[cur].name, newpath);
- if (lstat(newpath, &sb) == -1 || !show_stats(newpath, &sb)) {
+ if (lstat(newpath, &sb) == -1
+ || (sel == SEL_STATS && !show_stats(newpath, &sb))
+ || (sel == SEL_CHMODX && !xchmod(newpath, sb.st_mode))) {
printwarn(&presel);
goto nochange;
}
+
+ if (sel == SEL_CHMODX)
+ dents[cur].mode ^= S_IXUSR;
}
break;
case SEL_REDRAW: // fallthrough
diff --git a/src/nnn.h b/src/nnn.h
index 4ef40bf2..4e1311cf 100644
--- a/src/nnn.h
+++ b/src/nnn.h
@@ -65,6 +65,7 @@ enum action {
SEL_TOGGLEDOT,
SEL_DETAIL,
SEL_STATS,
+ SEL_CHMODX,
SEL_ARCHIVE,
SEL_FSIZE, /* file size */
SEL_ASIZE, /* apparent size */
@@ -177,6 +178,8 @@ static struct key bindings[] = {
{ 'd', SEL_DETAIL },
/* File details */
{ 'D', SEL_STATS },
+ /* Toggle executable status */
+ { '*', SEL_CHMODX },
/* Create archive */
{ 'i', SEL_ARCHIVE },
/* Toggle sort by size */