@@ -389,6 +389,8 @@ To wrap each file path within single quotes, export `NNN_QUOTE_ON`: | |||||
export NNN_QUOTE_ON=1 | export NNN_QUOTE_ON=1 | ||||
This is particularly useful if you are planning to copy the whole string to the shell to run a command. Quotes can be toggled at runtime using <kbd>^T</kbd>. | This is particularly useful if you are planning to copy the whole string to the shell to run a command. Quotes can be toggled at runtime using <kbd>^T</kbd>. | ||||
Note that the filename is not escaped. So copying may still fail for filenames having quote(s) in them. | |||||
#### copy file paths when X is missing | #### copy file paths when X is missing | ||||
A very common scenario on headless remote servers connected via SSH. As the clipboard is missing, `nnn` copies the path names to the tmp file `/tmp/nnncp$USER`. | A very common scenario on headless remote servers connected via SSH. As the clipboard is missing, `nnn` copies the path names to the tmp file `/tmp/nnncp$USER`. | ||||
@@ -263,7 +263,8 @@ screensaver. | |||||
.Ed | .Ed | ||||
.Pp | .Pp | ||||
\fBNNN_QUOTE_ON:\fR wrap copied paths within single quotes. Useful for pasting | \fBNNN_QUOTE_ON:\fR wrap copied paths within single quotes. Useful for pasting | ||||
names in the shell. | names in the shell. Note that the filename is not escaped. So copying may still fail | ||||
for filenames having quote(s) in them. | |||||
.Pp | .Pp | ||||
\fBNNN_SCRIPT:\fR path to a custom script to invoke with currently selected file name as argument 1. | \fBNNN_SCRIPT:\fR path to a custom script to invoke with currently selected file name as argument 1. | ||||
.Bd -literal | .Bd -literal | ||||
@@ -1752,6 +1752,19 @@ xgetgrgid(gid_t gid) | |||||
return grp->gr_name; | return grp->gr_name; | ||||
} | } | ||||
static bool | |||||
istgtdir(const char *tgtpath) | |||||
{ | |||||
if (tgtpath) { | |||||
struct stat tgtsb; | |||||
int r = stat(tgtpath, &tgtsb); | |||||
if ((r == 0) && (tgtsb.st_mode & S_IFMT) == S_IFDIR) | |||||
return TRUE; | |||||
} | |||||
return FALSE; | |||||
} | |||||
/* | /* | ||||
* Follows the stat(1) output closely | * Follows the stat(1) output closely | ||||
*/ | */ | ||||
@@ -1772,16 +1785,19 @@ show_stats(char *fpath, char *fname, struct stat *sb) | |||||
/* Show file name or 'symlink' -> 'target' */ | /* Show file name or 'symlink' -> 'target' */ | ||||
if (perms[0] == 'l') { | if (perms[0] == 'l') { | ||||
/* Note that MAX_CMD_LEN > PATH_MAX */ | /* Note that MAX_CMD_LEN > PATH_MAX */ | ||||
ssize_t len = readlink(fpath, g_buf, MAX_CMD_LEN); | char *tgt = realpath(fpath, g_buf); | ||||
if (tgt) { | |||||
if (len != -1) { | char ch[] = {'\'', '\0', '\0'}; | ||||
g_buf[len] = '\0'; | if (istgtdir(g_buf)) { | ||||
ch[1] = ch[0]; | |||||
ch[0] = '/'; | |||||
} | |||||
/* | /* | ||||
* We pass g_buf but unescape() operates on g_buf too! | * We pass g_buf but unescape() operates on g_buf too! | ||||
* Read the API notes for information on how this works. | * Read the API notes for information on how this works. | ||||
*/ | */ | ||||
dprintf(fd, " -> '%s'", unescape(g_buf, 0)); | dprintf(fd, " -> '%s%s", unescape(g_buf, 0), ch); | ||||
} | } | ||||
} | } | ||||